#![no_std]
extern crate alloc;
use core::ffi::*;
use core::ptr::null_mut;
use alloc::boxed::Box;
#[macro_use]
extern crate playdate_sys as pd;
use pd::ffi::*;
const INITIAL_X: u32 = LCD_COLUMNS / 2;
const INITIAL_Y: u32 = (pd::ffi::LCD_ROWS - TEXT_HEIGHT) / 2;
const TEXT_HEIGHT: u32 = 16;
const TEXT: &str = "Hello, Rust World";
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
const fn new(x: T, y: T) -> Point<T> { Point { x, y } }
}
struct State {
location: Point<i32>,
velocity: Point<i32>,
}
impl State {
const fn new() -> Self {
Self { location: Point::new(INITIAL_X as _, INITIAL_Y as _),
velocity: Point::new(1, 2) }
}
fn update(&mut self) -> Option<()> {
unsafe {
let graphics = (*pd::API).graphics;
(*graphics).clear?(LCDSolidColor::kColorWhite as LCDColor);
let c_text = CString::new(TEXT).ok()?;
let text_width = (*graphics).getTextWidth?(
null_mut(),
c_text.as_ptr() as *const _,
TEXT.len(),
PDStringEncoding::kUTF8Encoding,
0,
);
(*graphics).drawText?(
c_text.as_ptr() as *const _,
TEXT.len(),
PDStringEncoding::kUTF8Encoding,
self.location.x,
self.location.y,
);
self.location.x += self.velocity.x;
self.location.y += self.velocity.y;
if self.location.x < 0 || self.location.x > LCD_COLUMNS as i32 - text_width {
self.velocity.x = -self.velocity.x;
}
if self.location.y < 0 || self.location.y > LCD_ROWS as i32 - TEXT_HEIGHT as i32 {
self.velocity.y = -self.velocity.y;
}
(*(*pd::API).system).drawFPS?(0, 0);
Some(())
}
}
fn event(&mut self, event: PDSystemEvent) -> Option<()> {
match event {
PDSystemEvent::kEventInit => unsafe {
(*(*pd::API).display).setRefreshRate?(20.0);
},
_ => {},
}
Some(())
}
}
#[no_mangle]
pub extern "C" fn eventHandlerShim(api: *const PlaydateAPI, event: PDSystemEvent, _arg: u32) -> c_int {
static mut STATE: Option<Box<State>> = None;
match event {
PDSystemEvent::kEventInit => unsafe {
pd::API = api;
if STATE.is_none() {
STATE = Some(Box::new(State::new()));
}
let state = STATE.as_mut().unwrap().as_mut() as *mut State;
let f = (*(*api).system).setUpdateCallback.expect("setUpdateCallback");
f(Some(on_update), state.cast());
},
_ => {},
}
if let Some(state) = unsafe { STATE.as_mut() } {
state.event(event).and(Some(0)).unwrap_or(1)
} else {
1
}
}
unsafe extern "C" fn on_update(state: *mut c_void) -> i32 {
let ptr: *mut State = state.cast();
let state = ptr.as_mut().expect("missed state");
state.update().and(Some(1)).unwrap_or_default()
}
ll_symbols!();