Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api handlers, entry-point and various improvements #118

Merged
merged 10 commits into from
Sep 25, 2023
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ repository = "https://github.com/boozook/playdate.git"
[workspace.dependencies]
color = { version = "0.1", path = "api/color", package = "playdate-color", default-features = false }
ctrl = { version = "0.1", path = "api/ctrl", package = "playdate-controls", default-features = false }
display = { version = "0.1", path = "api/display", package = "playdate-display", default-features = false }
display = { version = "0.2", path = "api/display", package = "playdate-display", default-features = false }
fs = { version = "0.1", path = "api/fs", package = "playdate-fs", default-features = false }
gfx = { version = "0.2", path = "api/gfx", package = "playdate-graphics", default-features = false }
menu = { version = "0.1", path = "api/menu", package = "playdate-menu", default-features = false }
sound = { version = "0.1", path = "api/sound", package = "playdate-sound", default-features = false }
sprite = { version = "0.1", path = "api/sprite", package = "playdate-sprite", default-features = false }
system = { version = "0.1", path = "api/system", package = "playdate-system", default-features = false }
system = { version = "0.2", path = "api/system", package = "playdate-system", default-features = false }
sys = { version = "0.1", path = "api/sys", package = "playdate-sys", default-features = false }

build = { version = "0.2", path = "support/build", package = "playdate-build", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion api/display/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-display"
version = "0.1.3"
version = "0.2.0"
readme = "README.md"
description = "High-level Display API built on-top of Playdate API"
keywords = ["playdate", "sdk", "api", "gamedev"]
Expand Down
88 changes: 85 additions & 3 deletions api/display/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![cfg_attr(not(test), no_std)]
extern crate sys;

use core::ffi::c_char;
use core::ffi::c_float;
use core::ffi::c_int;
use core::ffi::c_uint;
Expand All @@ -10,6 +9,14 @@ use core::ffi::c_uint;
#[derive(Debug, Clone, Copy)]
pub struct Display<Api = api::Default>(Api);

impl Display<api::Default> {
/// Creates default [`Display`] without type parameter requirement.
///
/// Uses ZST [`api::Default`].
#[allow(non_snake_case)]
pub fn Default() -> Self { Self(Default::default()) }
}

impl<Api: Default + api::Api> Default for Display<Api> {
fn default() -> Self { Self(Default::default()) }
}
Expand All @@ -23,56 +30,117 @@ impl<Api: api::Api> Display<Api> {
}


impl Display<api::Default> {
pub const COLUMNS: u32 = sys::ffi::LCD_COLUMNS;
pub const ROWS: u32 = sys::ffi::LCD_ROWS;
pub const ROW_SIZE: u32 = sys::ffi::LCD_ROWSIZE;
pub const SCREEN_RECT: sys::ffi::LCDRect = sys::ffi::LCDRect { left: 0,
right: 0,
top: Self::COLUMNS as _,
bottom: Self::ROWS as _ };
}


impl<Api: api::Api> Display<Api> {
/// Returns the width of the display, taking the current scale into account;
///
/// e.g., if the scale is `2`, this function returns `200` instead of `400`.
///
/// See also [`Display::COLUMNS`].
///
/// Equivalent to [`sys::ffi::playdate_display::getWidth`]
#[doc(alias = "sys::ffi::playdate_display::getWidth")]
pub fn width(&self) -> c_int {
let f = self.0.get_width();
unsafe { f() }
}

/// Returns the height of the display, taking the current scale into account;
///
/// e.g., if the scale is `2`, this function returns `120` instead of `240`.
///
/// See also [`Display::ROWS`] and [`Display::ROW_SIZE`].
///
/// Equivalent to [`sys::ffi::playdate_display::getHeight`]
#[doc(alias = "sys::ffi::playdate_display::getHeight")]
pub fn height(&self) -> c_int {
let f = self.0.get_height();
unsafe { f() }
}

/// Sets the nominal refresh rate in frames per second.
///
/// Default is 20 fps, the maximum rate supported by the hardware for full-frame updates.
///
/// Equivalent to [`sys::ffi::playdate_display::setRefreshRate`]
#[doc(alias = "sys::ffi::playdate_display::setRefreshRate")]
pub fn set_refresh_rate(&self, rate: c_float) {
let f = self.0.set_refresh_rate();
unsafe { f(rate) }
}

/// If `value` is `true`, the frame buffer is drawn inverted—black instead of white, and vice versa.
///
/// Equivalent to [`sys::ffi::playdate_display::setInverted`]
#[doc(alias = "sys::ffi::playdate_display::setInverted")]
pub fn set_inverted(&self, value: bool) {
let f = self.0.set_inverted();
unsafe { f(value as _) }
}

/// Sets the display scale factor.
///
/// The top-left corner of the frame buffer is scaled up to fill the display;
///
/// e.g., if the scale is set to [`DisplayScale::Quad`],
/// the pixels in rectangle `[0, 100] x [0, 60]` are drawn on the screen as `4 x 4` squares.
///
/// Equivalent to [`sys::ffi::playdate_display::setScale`]
#[doc(alias = "sys::ffi::playdate_display::setScale")]
pub fn set_scale(&self, scale: DisplayScale) { self.set_scale_raw(scale.into()); }

/// Sets the display scale factor.
///
/// Valid values for `scale` are `1`, `2`, `4`, and `8`.
///
/// The top-left corner of the frame buffer is scaled up to fill the display;
/// e.g., if the scale is set to `4`, the pixels in rectangle `[0, 100] x [0, 60]` are drawn on the screen as `4 x 4` squares.
///
/// See also [`Display::set_scale`].
///
/// Equivalent to [`sys::ffi::playdate_display::setScale`]
#[doc(alias = "sys::ffi::playdate_display::setScale")]
pub fn set_scale(&self, scale: c_uint) {
pub fn set_scale_raw(&self, scale: c_uint) {
let f = self.0.set_scale();
unsafe { f(scale) }
}

/// Adds a mosaic effect to the display.
///
/// Valid `x` and `y` values are between `0` and `3`, inclusive.
///
/// Equivalent to [`sys::ffi::playdate_display::setMosaic`]
#[doc(alias = "sys::ffi::playdate_display::setMosaic")]
pub fn set_mosaic(&self, x: c_uint, y: c_uint) {
let f = self.0.set_mosaic();
unsafe { f(x, y) }
}

/// Flips the display on the `x` or `y` axis, or both.
///
/// Equivalent to [`sys::ffi::playdate_display::setFlipped`]
#[doc(alias = "sys::ffi::playdate_display::setFlipped")]
pub fn set_flipped(&self, x: bool, y: bool) {
let f = self.0.set_flipped();
unsafe { f(x as _, y as _) }
}

/// Offsets the display by the given amount.
///
/// Areas outside of the displayed area are filled with the current background color.
///
/// See also [`playdate-graphics::set_background_color`].
///
/// Equivalent to [`sys::ffi::playdate_display::setOffset`]
#[doc(alias = "sys::ffi::playdate_display::setOffset")]
pub fn set_offset(&self, x: c_int, y: c_int) {
Expand All @@ -82,8 +150,22 @@ impl<Api: api::Api> Display<Api> {
}


#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DisplayScale {
Normal = 1,
Double = 2,
Quad = 4,
Eight = 8,
}

impl Into<c_uint> for DisplayScale {
#[inline(always)]
fn into(self) -> c_uint { (self as u8).into() }
}


pub mod api {
use core::ffi::c_char;
use core::ffi::c_float;
use core::ffi::c_int;
use core::ffi::c_uint;
Expand Down
2 changes: 1 addition & 1 deletion api/gfx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-graphics"
version = "0.2.2"
version = "0.2.3"
readme = "README.md"
description = "High-level graphics API built on-top of Playdate API"
keywords = ["playdate", "sdk", "api", "gamedev"]
Expand Down
4 changes: 2 additions & 2 deletions api/gfx/examples/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ impl State {
for (i, code) in RUST.into_iter().enumerate() {
let mut advance = 0;
let (glyph, bitmap_ref) = text::get_page_glyph_with_bitmap(&page, code, &mut advance).unwrap();
let mut char = bitmap_ref.into_bitmap();

let kern = RUST.get(i + 1)
.map(|next| text::get_glyph_kerning(&glyph, code, *next))
.unwrap_or_default();

let w = char.bitmap_data().map(|bd| bd.width).unwrap();
let char = bitmap_ref.into_bitmap();
let w = char.size().map(|(w, h)| w).unwrap();
let x = OFFSET + i as i32 * w;
let y = OFFSET + kern;

Expand Down
26 changes: 26 additions & 0 deletions api/gfx/src/bitmap/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,32 @@ impl<Api: api::Api, const FOD: bool> Bitmap<Api, FOD> {
}


/// Returns `(width, height)` of the bitmap.
///
/// Can return error if there is no bitmap-data or any internal error occurred.
///
/// Calls [`sys::ffi::playdate_graphics::getBitmapData`].
#[doc(alias = "sys::ffi::playdate_graphics::getBitmapData")]
pub fn size(&self) -> Result<(c_int, c_int), Error> {
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut row_bytes: c_int = 0;

let f = self.1.get_bitmap_data();
unsafe {
f(
self.0,
&mut width,
&mut height,
&mut row_bytes,
core::ptr::null_mut(),
core::ptr::null_mut(),
)
};

Ok((width, height))
}

/// Returns mutable borrow of bitmap-data by this bitmap.
///
/// Calls [`sys::ffi::playdate_graphics::getBitmapData`].
Expand Down
7 changes: 2 additions & 5 deletions api/gfx/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,10 @@ pub fn draw_text_cstr(text: &CStr, encoding: StringEncoding, x: c_int, y: c_int)
///
/// Equivalent to [`sys::ffi::playdate_graphics::getTextWidth`].
#[doc(alias = "sys::ffi::playdate_graphics::getTextWidth")]
pub fn get_text_width<S: AsRef<str>>(text: S,
font: Option<&LCDFont>,
tracking: c_int)
-> Result<c_int, NulError> {
pub fn get_text_width<S: AsRef<str>>(text: S, font: Option<&Font>, tracking: c_int) -> Result<c_int, NulError> {
let s = CString::new(text.as_ref())?;
let f = *sys::api!(graphics.getTextWidth);
let font = font.map(|font| font as *const LCDFont as *mut LCDFont)
let font = font.map(|font| unsafe { font.as_raw() })
.unwrap_or(core::ptr::null_mut());
let res = unsafe {
f(
Expand Down
Loading