1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
// Please keep the craydate crate root's comment and README.md in sync.
//! # Craydate
//!
//! This crate and its related crates together provide a safe Rust API for the
//! [Playdate](https://play.date/) hand held gaming system. It is built on the [Playdate C
//! Api](https://sdk.play.date/1.10.0/Inside%20Playdate%20with%20C.html).
//!
//! The name is crustacean pun, with our dear friends the crayfishes.
//!
//! # Requirements
//! Using these crates requires the [Playdate SDK](https://play.date/dev/), which has [its own
//! license](https://play.date/dev/sdk-license). Install the SDK and add an environment variable
//! named `PLAYDATE_SDK_PATH` that points to the directory where you installed it, such as
//! `PLAYDATE_SDK_PATH=C:\playdate`.
//!
//! This crate uses unstable features in order to provide a `#![no_std]` application to run on the
//! Playdate simulator and hardware device. Thus it requires use of the [Rust nightly
//! compiler](https://doc.rust-lang.org/1.2.0/book/nightly-rust.html).
//!
//! # Getting Started
//!
//! Building a `#![no_std]` application that is compiled for the Playdate simulator requires a bit
//! of extra Cargo setup, which we try to make easy for you. The dependency structure of your
//! project will look like this:
//!
//! ```
//! - your-game-project**
//! ├── [dependencies] your-game** (`#![no_std]` crate)
//! | ├── [dependencies] craydate (`#![no_std]` crate)
//! | └── [dependencies] euclid (with `default-features = false` and `features = ["libm"]`)
//! └── [build-dependencies] craydate-build
//!
//! ** = is specific to your game and provided by the game developer.
//! ```
//!
//! Note that your game's crate must include the `#![no_std]` directive in its crate root in order
//! to build for the Playdate device.
//!
//! The `euclid` crate is used in the craydate public Apis, which is why you will need it. The
//! features listed above are specified to make the crate compatible with a `#![no_std]`
//! application.
//!
//! If you choose not to use the root project crate talked about below, then you do not need the
//! [craydate-build](https://github.com/danakj/craydate-build) in `[build-dependencies]`, but will
//! be responsible to build the pdx image and install it yourself.
//!
//! ## The root project crate
//!
//! We provide an template of a root project crate at
//! [craydate-project](https://github.com/danakj/craydate-project), which will act as the
//! coordination point to build your game for the Playdate simulator and the Playdate device. To use
//! it, please rename and customize it for your game.
//!
//! To start using it, download the latest release, unzip it and edit it as follows. See below for
//! more details.
//! 1. Ensure your `PLAYDATE_SDK_PATH` environment variable is set to the location of the Playdate
//! SDK.
//! 1. In the `Cargo.toml` file, change the `name` to include your game's name, such as
//! `foo-project` for the game crate `foo`.
//! 1. In the `Cargo.toml` file, change the `game` dependency's `package` and `path` to point to
//! your game's crate.
//! 1. In the `Cargo.toml` file, if you want to use it, change the `game-assets` dependency's
//! `package` and `path` to point to your game's asset-generating crate (when you have one, you
//! can leave it commented out with a `#` for now).
//! 1. If you have a `game-assets` dependency for generating assets, uncomment and fix the call to
//! it from `src/bin/make_pdx.rs` (when you have one, you can ignore this for now).
//! 1. If you have a `game-assets` dependency for generating assets, uncomment "game-assets" in the
//! `bins` feature (when you have one, you can ignore this for now). It would look like `bins =
//! ["craydate-build", game-assets"]`.
//!
//! ### Development Workflow
//!
//! To build your game for the Playdate simulator, simply build your customized root project
//! `your-game-project` crate with the Cargo `--lib` flag, which will build your game as a
//! dependency.
//!
//! After building the game, the root project crate (if based on
//! [craydate-project](https://github.com/danakj/craydate-project)) includes 2 binaries to help you
//! get it onto the Playdate simulator or a hardware device. Build them by building your root
//! project `your-game-project` crate with the Cargo `--bins` flag. The binaries are:
//! * make_pdx
//! * run_simulator
//!
//! #### make_pdx
//! Combines your built game, along with any asset files into a pdx image for the device or
//! simulator.
//!
//! The `your-game-assets` dependency seen above is an optional place to construct and collect
//! assets for your game that will be included by **make_pdx** when building the game's pdx image.
//! To do so, edit the `make_pdx.rs` file to call `your-game-assets`. Assets should be collected
//! into `env!("PDX_SOURCE_DIR")`. For example:
//! ```rs
//! your_game_assets::generate_assets(env!("PDX_SOURCE_DIR"))?;
//! ```
//!
//! The **make_pdx** binary would then include those assets into your game's pdx image.
//!
//! #### run_simulator
//!
//! Runs the Playdate simulator, loading the pdx image generated by **make_pdx**.
//!
//! #### VSCode
//!
//! We provide configurations for VSCode in the template root project
//! [craydate-project](https://github.com/danakj/craydate-project) to build and use the make_pdx and
//! run_simulator binaries correctly. The `.vscode/settings.json` file configures these tasks. You
//! should not need to change the configuration unless you move the .vscode directory out of the
//! root project crate.
//! * The `"projectRootCrate"` variable should point to the root project crate. By default, since
//! the `.vscode` directory is inside that crate, it is `"."`.
//! * The `"rust-analyzer.linkedProjects"` variable should point to the root project crate's
//! `Cargo.toml` file. By default it is `"./Cargo.toml"`.
//!
//! When running the simulator with this task, VSCode will capture the `stdout` and `stderr` output
//! of the game and write it to a file called `stdout.txt` in the project's root directory.
//!
//! ### Panics
//!
//! The `Cargo.toml` for the root project crate must also set `panic = "abort"`. This is included in
//! the template root project [craydate-project](https://github.com/danakj/craydate-project) crate:
//! ```
//! [profile.dev]
//! panic = "abort"
//! [profile.release]
//! panic = "abort"
//! ```
//! Otherwise you will get a compilation error:
//! ```
//! error: language item required, but not found: `eh_personality`
//! |
//! = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
//! ```
//!
//! ## Your first game
//!
//! Your game's crate must include a function that will be called after the Playdate system
//! initializes. This function should contain your game's main game loop. It's simplest form would
//! look like:
//! ```rs
//! #[craydate::main]
//! async fn main(api: craydate::Api) -> ! {
//! let events = api.system.system_event_watcher();
//! loop {
//! match events.next().await {
//! craydate::SystemEvent::NextFrame { inputs, .. } => {
//! // Read inputs, update game state and draw.
//! }
//! _ => (),
//! }
//! }
//! }
//! ```
//! Then, handle the various events that can be returned from `next()`. In particular, handle input,
//! update game state, and draw to the screen when the `SystemEvent::NextFrame` event happens. You
//! can access the Playdate device through the `craydate::Api` parameter to `main()`.
//!
//! Logging to the Playdate simulator's console, for debugging, is possible through the
//! `craydate::log()` and `craydate::log_error()` functions.
//!
//! # Platforms
//!
//! **Currently the craydate project only supports development for the Windows simulator.** We will
//! expand support to the Playdate hardware device once we get access to one. Simulators on other
//! platforms (e.g. Mac) are possible, and would only need changes to the root project crate.
//!
//! * The "osx.craydateHostTarget" setting may need to change if you're working on an ARM-based mac.
//! * The "linux.craydateHostTarget" setting hasn't been tested to see if it's correct.
//! * A MacOSX simulator build has not been tested and may not link.
//! * A Linux simulator build has not been tested and may not link.
//! * There's no VSCode task to install the pdx on a Playdate device yet.
//! * The build for a Playdate device has not been tested yet and may not load at all.
//!
//! # License
//! This project is licensed under either of
//!
//! * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
//! https://www.apache.org/licenses/LICENSE-2.0)
//! * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
//!
//! at your option.
//!
//! ## Contribution
//! Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
//! Craydate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
//! any additional terms or conditions.
extern crate alloc;
extern crate craydate_macro;
/// A game crate should annotate their game loop function with this attribute macro.
///
/// The annotated function must be async, and will indicate that it's done updating
/// and ready to draw by `await`ing the `Future` returned from
/// `api.system.system_event_watcher()`.
///
/// # Example
/// ```rs
/// #[craydate::main]
/// async fn main(api: craydate::Api) -> ! {
/// let events = api.system.system_event_watcher();
/// loop {
/// match events.next().await {
/// craydate::SystemEvent::NextFrame { inputs, .. } => {
/// // Read inputs, update game state and draw.
/// }
/// _ => (),
/// }
/// }
/// }
/// ```
pub use main;
/// Reexport some of alloc, since things in alloc are not guaranteed to work in `no_std` as it all
/// depends on our global allocator. This makes it clear they can be used, and avoids the need for
/// `extern crate alloc` elsewhere.
pub use ;
pub use *;
pub use ;
pub use Callbacks;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use ;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
/// The global allocator, which will defer allocation requests to the Playdate system, and deal with
/// ensuring correct alignment.
static mut GLOBAL_ALLOCATOR: Allocator = new;
/// A helper implementation of panic_handler for the toplevel crate to forward to.
///
/// Since the top-level crate has to implement the `#[panic_handler]` we make it
/// easy by letting them simply forward over to this function.
!
!
/// The error handler for when allocations fail. It will simply panic.
!
/// A way to store a pointer in a static variable, by telling the compiler it's Sync.
///
/// This is, of course, unsound if the pointer is used across threads and is not
/// thread-safe, but the pointer is only used by the Playdate system.
;
unsafe
extern "C"
static BSS_START_PTR: BssPtr = unsafe ;
static BSS_END_PTR: BssPtr = unsafe ;