Created
May 17, 2020 23:08
-
-
Save rtsuk/bd7fd934c94c5569d271e737625c19b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![no_std] | |
use { | |
playdate::{graphics::Graphics, system::System, Playdate}, | |
playdate_sys::{ | |
PDButtons_kButtonA, PDSystemEvent, PDSystemEvent_kEventInit, PlaydateAPI, LCD_COLUMNS, | |
LCD_ROWS, LCD_ROWSIZE, | |
}, | |
rand::{rngs::SmallRng, Rng, SeedableRng}, | |
}; | |
const LIMIT: usize = (LCD_COLUMNS - 1) as usize; | |
fn ison(row: &'static [u8], x: usize) -> bool { | |
(row[x / 8] & (0x80 >> (x % 8))) == 0 | |
} | |
fn val(row: &'static [u8], x: usize) -> u8 { | |
1 - ((row[x / 8] >> (7 - (x % 8))) & 1) | |
} | |
fn rowsum(row: &'static [u8], x: usize) -> u8 { | |
if x == 0 { | |
val(row, LIMIT) + val(row, x) + val(row, x + 1) | |
} else if x < LIMIT { | |
return val(row, x - 1) + val(row, x) + val(row, x + 1); | |
} else { | |
val(row, x - 1) + val(row, x) + val(row, 0) | |
} | |
} | |
fn middlerowsum(row: &'static [u8], x: usize) -> u8 { | |
if x == 0 { | |
val(row, LIMIT) + val(row, x + 1) | |
} else if x < LIMIT { | |
val(row, x - 1) + val(row, x + 1) | |
} else { | |
val(row, x - 1) + val(row, 0) | |
} | |
} | |
fn do_row<'a>( | |
lastrow: &'static [u8], | |
row: &'static [u8], | |
nextrow: &'static [u8], | |
outrow: &'a mut [u8], | |
) { | |
let mut b = 0; | |
let mut bitpos = 0x80; | |
for x in 0..(LCD_COLUMNS as usize) { | |
// If total is 3 cell is alive | |
// If total is 4, no change | |
// Else, cell is dead | |
let sum = rowsum(lastrow, x) + middlerowsum(row, x) + rowsum(nextrow, x); | |
if sum == 3 || (ison(row, x) && sum == 2) { | |
b |= bitpos; | |
} | |
bitpos >>= 1; | |
if bitpos == 0 { | |
outrow[x / 8] = !b; | |
b = 0; | |
bitpos = 0x80; | |
} | |
} | |
} | |
fn randomize(graphics: &Graphics, rng: &mut SmallRng) { | |
let frame = graphics.get_display_frame(); | |
for element in &mut frame[..] { | |
*element = rng.gen(); | |
} | |
} | |
struct State { | |
graphics: Graphics, | |
system: System, | |
rng: SmallRng, | |
started: bool, | |
} | |
const LAST_ROW_INDEX: usize = ((LCD_ROWS - 1) * LCD_ROWSIZE) as usize; | |
const LAST_ROW_LIMIT: usize = LAST_ROW_INDEX + LCD_ROWSIZE as usize; | |
impl State { | |
pub fn update(&mut self) { | |
if !self.started { | |
randomize(&self.graphics, &mut self.rng); | |
self.started = true; | |
} | |
let (_, pushed, _) = self.system.get_button_state(); | |
if (pushed & PDButtons_kButtonA) != 0 { | |
randomize(&self.graphics, &mut self.rng); | |
} | |
let frame = self.graphics.get_frame(); | |
if let Some(frame) = frame { | |
let last_frame = self.graphics.get_display_frame(); | |
let mut last_row = &last_frame[LAST_ROW_INDEX..LAST_ROW_LIMIT]; | |
let mut row = &last_frame[0..LCD_ROWSIZE as usize]; | |
let mut next_row = &last_frame[LCD_ROWSIZE as usize..(LCD_ROWSIZE * 2) as usize]; | |
for y in 0..LCD_ROWS { | |
let index = (y * LCD_ROWSIZE) as usize; | |
let limit = index + LCD_ROWSIZE as usize; | |
do_row(last_row, row, next_row, &mut frame[index..limit]); | |
last_row = row; | |
row = next_row; | |
let next_row_index = (y + 2) % LCD_ROWS; | |
let index = (next_row_index * LCD_ROWSIZE) as usize; | |
let limit = index + LCD_ROWSIZE as usize; | |
next_row = &last_frame[index..limit]; | |
} | |
} | |
self.graphics.mark_updated_rows(-1, -1); | |
} | |
} | |
static mut STATE: Option<State> = None; | |
#[no_mangle] | |
extern "C" fn update(_user_data: *mut core::ffi::c_void) -> i32 { | |
let state = unsafe { STATE.as_mut().expect("state") }; | |
state.update(); | |
1 | |
} | |
#[no_mangle] | |
extern "C" fn eventHandler( | |
playdate: *mut PlaydateAPI, | |
event: PDSystemEvent, | |
_arg: u32, | |
) -> playdate_sys::ctypes::c_int { | |
if event == PDSystemEvent_kEventInit { | |
let small_rng = SmallRng::seed_from_u64(3); | |
let playdate = Playdate::new(playdate); | |
let system = playdate.system(); | |
let graphics = playdate.graphics(); | |
system.set_update_callback(Some(update)); | |
unsafe { | |
STATE = Some(State { | |
graphics: graphics, | |
system: system, | |
rng: small_rng, | |
started: false, | |
}); | |
} | |
} | |
0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment