Swift bindings to the Playdate C API

Wraps all ten subsystems of the Playdate SDK 3.1.1 C API (system, display,
graphics, sprites, sound, file, JSON, Lua, scoreboards, network) in
idiomatic Swift: namespaced APIs, wrapper types with ownership semantics,
closures for callbacks, and typed throws. Written within the Embedded Swift
subset so the same code can target the device.

The SDK headers are resolved through a "playdate" pkg-config module
(Scripts/install-pkgconfig.sh), so the package works as a normal SwiftPM
dependency without unsafe build flags.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-24 10:33:45 +02:00
co-authored by Claude Fable 5
commit 09760f99b0
29 changed files with 6533 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
//
// Display.swift
// Wraps `playdate->display` (pd_api_display.h).
//
internal import CPlaydate
extension Playdate {
/// The display API: resolution, refresh rate, scaling, and effects.
public enum Display {}
}
extension Playdate.Display {
private static var api: playdate_display { Playdate.api.display.pointee }
/// The display width in pixels, taking the current scale into account.
public static var width: Int { Int(api.getWidth.unsafelyUnwrapped()) }
/// The display height in pixels, taking the current scale into account.
public static var height: Int { Int(api.getHeight.unsafelyUnwrapped()) }
/// Sets the nominal refresh rate in frames per second. Pass 0 to update
/// as fast as possible (the update callback drives the pace).
public static func setRefreshRate(_ rate: Float) {
api.setRefreshRate.unsafelyUnwrapped(rate)
}
/// The current nominal refresh rate.
public static var refreshRate: Float { api.getRefreshRate.unsafelyUnwrapped() }
/// The measured average frames per second.
public static var fps: Float { api.getFPS.unsafelyUnwrapped() }
/// Draws the frame white-on-black when `true`.
public static func setInverted(_ inverted: Bool) {
api.setInverted.unsafelyUnwrapped(inverted ? 1 : 0)
}
/// Sets the display scale factor: 1, 2, 4, or 8.
public static func setScale(_ scale: UInt32) {
api.setScale.unsafelyUnwrapped(scale)
}
/// Adds a mosaic effect. Valid values for each axis are 0...3.
public static func setMosaic(x: UInt32, y: UInt32) {
api.setMosaic.unsafelyUnwrapped(x, y)
}
/// Flips the display on the given axes.
public static func setFlipped(x: Bool, y: Bool) {
api.setFlipped.unsafelyUnwrapped(x ? 1 : 0, y ? 1 : 0)
}
/// Offsets the display by the given amount. Areas outside the frame
/// buffer draw black.
public static func setOffset(x: Int, y: Int) {
api.setOffset.unsafelyUnwrapped(Int32(x), Int32(y))
}
}