Skip to content

Instantly share code, notes, and snippets.

@DanB91
Last active Nov 28, 2022
Embed
What would you like to do?
Playdate Zig starting point
THIS GIST IS OUT OF DATE! Please use my new project template here to get started with Zig on Playdate:
https://github.com/DanB91/Zig-Playdate-Template
The rest of this is preservied for historical reasons:
This is a small snippet of some code to get you started for developing for the Playdate on Zig. This code should be used as a starting point and may not compile without some massaging. This code has only been tested out on macOS and you'll need to modify the addSharedLibrary() portion of build.zig to output a .dll or .so instead of a .dylib, depending on you platform.
This code will help you produce both an executable for the Playdate simulator and also an executable that actually run on the Playdate hardware.
The following files are included:
-build.zig -- Builds 2 Playdate executables: One for hardware and one for the simulator. Read the small README at the top of the file.
-main.zig -- Your game code goes here.
-playdate_hardware_main.zig -- Sets up the required global data used in the Playdate hardware executable. Not used in the simulator
-playdate_api.zig -- An incomplete Playdate API Zig wrapper. You will need to fill in the ?*anyopaque fields in the PlaydateAPI struct. Also, not all of the function pointers that are defined have dedicated wrappers, since it is unfinished. This also has a lot of personal naming and structure decisions (like defining a "Pixel" type) you may want to get rid of.
Feel free to reach out to me on Twitter @dbokser91 for any questions
const std = @import("std");
/////////////////
///!!!!!README!!!!!!!
///This has only been tested on macOS, and you will need to modify when using it on other platforms to generate a .dll or .so
///
///Depends on link_map.ld found in the Playdate SDK
///
///The following programs need to be in your $PATH
///- pdc
///- objcopy
///
///
//////////////
pub fn build(b: *std.build.Builder) !void {
// Standard release options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
const lib = b.addSharedLibrary("pdex", "src/main.zig", .unversioned);
const output_path = try std.fs.path.join(b.allocator, &.{ b.install_path, "Source" });
lib.setOutputDir(output_path);
lib.setBuildMode(mode);
lib.install();
const game_elf = b.addExecutable("pdex.elf", "src/playdate_hardware_main.zig");
game_elf.step.dependOn(&lib.step);
game_elf.link_function_sections = true;
game_elf.stack_size = 61800;
game_elf.setLinkerScriptPath(.{ .path = "link_map.ld" });
game_elf.setOutputDir(b.install_path);
game_elf.setBuildMode(mode);
game_elf.setTarget(try std.zig.CrossTarget.parse(.{
.arch_os_abi = "thumb-freestanding-eabihf",
.cpu_features = "cortex_m7-fp64-fp_armv8d16-fpregs64-vfp2-vfp3d16-vfp4d16",
}));
if (b.is_release) {
game_elf.omit_frame_pointer = true;
}
game_elf.install();
const pdc_step = b.addSystemCommand(&.{ "bash", "-c", "mv zig-out/Source/libpdex.dylib zig-out/Source/pdex.dylib && objcopy -O binary zig-out/pdex.elf zig-out/Source/pdex.bin && pdc --skip-unknown zig-out/Source zig-out/zig_game.pdx " });
pdc_step.step.dependOn(&game_elf.step);
b.getInstallStep().dependOn(&pdc_step.step);
const run_cmd = b.addSystemCommand(&.{ "open", "zig-out/zig_game.pdx" });
run_cmd.step.dependOn(&pdc_step.step);
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
pub export fn eventHandler(playdate: *pdapi.PlaydateAPI, event: pdapi.PDSystemEvent, arg: u32) c_int {
///game code starts here...
}
const std = @import("std");
pub const SCREEN_WIDTH = 400;
pub const SCREEN_HEIGHT = 240;
pub const Pixel = i32;
pub const PlaydateAPI = extern struct {
system: *const PlaydateSys,
file: *anyopaque,
graphics: *const PlaydateGraphics,
sprite: *anyopaque,
display: *const PlaydateDisplay,
sound: *anyopaque,
lua: *anyopaque,
json: *anyopaque,
scoreboards: *anyopaque,
};
pub const PDSystemEvent = enum(c_int) {
EventInit,
EventInitLua,
EventLock,
EventUnlock,
EventPause,
EventResume,
EventTerminate,
EventKeyPressed, // arg is keycode
EventKeyReleased,
EventLowPower,
};
pub const PDLanguage = enum(c_int) {
PDLanguageEnglish,
PDLanguageJapanese,
PDLanguageUnknown,
};
pub const PDPeripherals = enum(c_int) {
None = 0,
Accelerometer = (1 << 0),
// ...
AllPeripherals = 0xffff,
};
pub const PDStringEncoding = enum(c_int) {
ASCIIEncoding,
UTF8Encoding,
@"16BitLEEncoding",
};
pub const LCDBitmap = anyopaque;
pub const PDMenuItem = anyopaque;
pub const PDCallbackFunction = fn (userdata: ?*anyopaque) callconv(.C) c_int;
pub const PDMenuItemCallbackFunction = fn (userdata: ?*anyopaque) callconv(.C) void;
var pd: *PlaydateAPI = undefined;
var current_font: *LCDFont = undefined;
pub inline fn set_playdate_api(playdate: *PlaydateAPI) void {
pd = playdate;
}
////Buttons
pub const PDButtons = c_int;
pub const BUTTON_LEFT = (1 << 0);
pub const BUTTON_RIGHT = (1 << 1);
pub const BUTTON_UP = (1 << 2);
pub const BUTTON_DOWN = (1 << 3);
pub const BUTTON_B = (1 << 4);
pub const BUTTON_A = (1 << 5);
pub inline fn get_button_state(current: ?*PDButtons, pushed: ?*PDButtons, released: ?*PDButtons) void {
pd.system.getButtonState(current, pushed, released);
}
//Draw Color
pub inline fn solid_color_to_color(solid_color: LCDSolidColor) LCDColor {
return @intCast(usize, @enumToInt(solid_color));
}
pub inline fn pattern_to_color(pattern: LCDPatternSlice) LCDColor {
return @intCast(usize, @ptrToInt(pattern.ptr));
}
/////Draw context
pub inline fn push_drawing_context(target: ?*LCDBitmap) void {
pd.graphics.pushContext(target);
}
pub inline fn pop_drawing_context() void {
pd.graphics.popContext();
}
////Draw clipping
pub inline fn set_clip_rect(x: Pixel, y: Pixel, width: Pixel, height: Pixel) void {
pd.graphics.setClipRect(x, y, width, height);
}
pub inline fn clear_clip_rect() void {
pd.graphics.clearClipRect();
}
////Screen
pub inline fn clear_screen(color: LCDSolidColor) void {
pd.graphics.clear(@intCast(LCDColor, @enumToInt(color)));
}
pub inline fn set_screen_clip_rect(x: Pixel, y: Pixel, width: Pixel, height: Pixel) void {
pd.graphics.setScreenClipRect(x, y, width, height);
}
pub inline fn set_refresh_rate(comptime refresh_rate: f32) void {
pd.display.setRefreshRate(refresh_rate);
}
////Fonts and text
pub inline fn load_font(path: [*c]const u8) *LCDFont {
var err: [*c]const u8 = undefined;
const font_opt = pd.graphics.loadFont(path, &err);
if (font_opt) |font| {
return font;
}
@panic("Error loading font");
}
pub inline fn free_font(font: *LCDFont) void {
_ = font;
//TODO: there doesn't seem to be a free font function
//pd.graphics.freeFont(font);
}
pub inline fn set_font(font: *LCDFont) void {
current_font = font;
pd.graphics.setFont(font);
}
pub inline fn draw_text(text: []const u8, x: Pixel, y: Pixel) Pixel {
return pd.graphics.drawText(text.ptr, text.len, .UTF8Encoding, x, y);
}
pub inline fn draw_fmt(comptime fmt: []const u8, args: anytype, x: Pixel, y: Pixel) Pixel {
var buffer = [_]u8{0} ** 128;
const to_print = std.fmt.bufPrintZ(&buffer, fmt, args) catch @panic("draw_fmt failed");
return draw_text(to_print, x, y);
}
pub inline fn get_text_width(text: []const u8) Pixel {
return pd.graphics.getTextWidth(current_font, text.ptr, text.len, .UTF8Encoding, 0);
}
pub inline fn get_fmt_width(comptime fmt: []const u8, args: anytype) Pixel {
var buffer = [_]u8{0} ** 128;
const to_count = std.fmt.bufPrintZ(&buffer, fmt, args) catch @panic("draw_fmt failed");
return pd.graphics.getTextWidth(current_font, to_count.ptr, to_count.len, .UTF8Encoding, 0);
}
pub inline fn get_font_height() Pixel {
return pd.graphics.getFontHeight(current_font);
}
pub inline fn draw_fps(x: Pixel, y: Pixel) void {
pd.system.drawFPS(x, y);
}
////Bitmap
pub inline fn load_bitmap_table(path: [*c]const u8) *LCDBitmapTable {
var err: [*c]const u8 = undefined;
const bitmap_table_opt = pd.graphics.loadBitmapTable(path, &err);
if (bitmap_table_opt) |bitmap_table| {
return bitmap_table;
}
@panic("Error loading bitmap table");
}
pub inline fn free_bitmap_table(bitmap_table: *LCDBitmapTable) void {
pd.graphics.freeBitmapTable(bitmap_table);
}
pub inline fn load_bitmap(path: [*c]const u8) *LCDBitmap {
var err: [*c]const u8 = undefined;
const bitmap_opt = pd.graphics.loadBitmap(path, &err);
if (bitmap_opt) |bitmap| {
return bitmap;
}
@panic("Error loading bitmap");
}
pub inline fn free_bitmap(bitmap: *LCDBitmap) void {
pd.graphics.freeBitmap(bitmap);
}
//Shapes
pub inline fn draw_rect(x: Pixel, y: Pixel, width: Pixel, height: Pixel, color: LCDColor) void {
pd.graphics.drawRect(x, y, width, height, color);
}
pub inline fn fill_rect(x: Pixel, y: Pixel, width: Pixel, height: Pixel, color: LCDColor) void {
pd.graphics.fillRect(x, y, width, height, color);
}
pub const BitmapData = struct {
width: i32,
height: i32,
row_bytes: i32,
has_mask: bool,
data: []u8,
};
pub fn get_bitmap_data(bitmap: *LCDBitmap) BitmapData {
var ret: BitmapData = undefined;
var has_mask: c_int = 0;
var data: [*c]u8 = undefined;
pd.graphics.getBitmapData(bitmap, &ret.width, &ret.height, &ret.row_bytes, &has_mask, &data);
ret.has_mask = if (has_mask != 0) true else false;
ret.data = data[0..@intCast(usize, ret.row_bytes * ret.height)];
return ret;
}
pub inline fn get_table_bitmap(table: *LCDBitmapTable, index: i32) ?*LCDBitmap {
const table_bitmap = pd.graphics.getTableBitmap(table, @intCast(c_int, index));
return table_bitmap;
}
pub fn get_table_bitmap_size(table: *LCDBitmapTable) i32 {
var ret: i32 = 0;
while (get_table_bitmap(table, ret)) |_| {
ret += 1;
}
return ret;
}
pub inline fn tile_bitmap(bitmap: *LCDBitmap, x: Pixel, y: Pixel, width: Pixel, height: Pixel, flip: LCDBitmapFlip) void {
pd.graphics.tileBitmap(bitmap, x, y, width, height, flip);
}
pub inline fn draw_bitmap(bitmap: *LCDBitmap, x: Pixel, y: Pixel, flip: LCDBitmapFlip) void {
pd.graphics.drawBitmap(bitmap, x, y, flip);
}
pub inline fn draw_scaled_bitmap(bitmap: *LCDBitmap, x: Pixel, y: Pixel, xscale: f32, yscale: f32) void {
pd.graphics.drawScaledBitmap(bitmap, x, y, xscale, yscale);
}
//Crank
pub inline fn get_crank_change() f32 {
return pd.system.getCrankChange();
}
pub inline fn get_crank_angle() f32 {
return pd.system.getCrankAngle();
}
pub inline fn is_crank_docked() bool {
return pd.system.isCrankDocked() != 0;
}
pub inline fn set_crank_sounds_disabled(flag: bool) bool {
return pd.system.setCrankSoundsDisabled(if (flag) 1 else 0) != 0; // returns previous setting
}
//Menu items
pub inline fn add_menu_item(comptime title: [:0]const u8, callback: PDMenuItemCallbackFunction, userdata: ?*anyopaque) *PDMenuItem {
return pd.system.addMenuItem(title, callback, userdata).?;
}
pub const PlaydateSys = extern struct {
realloc: fn (ptr: ?*anyopaque, size: usize) callconv(.C) ?*anyopaque,
formatString: fn (ret: ?*[*c]u8, fmt: [*c]const u8, ...) callconv(.C) c_int,
logToConsole: fn (fmt: [*c]const u8, ...) callconv(.C) void,
@"error": fn (fmt: [*c]const u8, ...) callconv(.C) void,
getLanguage: fn () callconv(.C) PDLanguage,
getCurrentTimeMilliseconds: fn () callconv(.C) c_uint,
getSecondsSinceEpoch: fn (milliseconds: ?*c_uint) callconv(.C) c_uint,
drawFPS: fn (x: c_int, y: c_int) callconv(.C) void,
setUpdateCallback: fn (update: ?PDCallbackFunction, userdata: ?*anyopaque) callconv(.C) void,
getButtonState: fn (current: ?*PDButtons, pushed: ?*PDButtons, released: ?*PDButtons) callconv(.C) void,
setPeripheralsEnabled: fn (mask: PDPeripherals) callconv(.C) void,
getAccelerometer: fn (outx: ?*f32, outy: ?*f32, outz: ?*f32) callconv(.C) void,
getCrankChange: fn () callconv(.C) f32,
getCrankAngle: fn () callconv(.C) f32,
isCrankDocked: fn () callconv(.C) c_int,
setCrankSoundsDisabled: fn (flag: c_int) callconv(.C) c_int, // returns previous setting
getFlipped: fn () callconv(.C) c_int,
setAutoLockDisabled: fn (disable: c_int) callconv(.C) void,
setMenuImage: fn (bitmap: ?*LCDBitmap, xOffset: c_int) callconv(.C) void,
addMenuItem: fn (title: [*c]const u8, callback: ?PDMenuItemCallbackFunction, userdata: ?*anyopaque) callconv(.C) ?*PDMenuItem,
addCheckmarkMenuItem: fn (title: [*c]const u8, value: c_int, callback: ?PDMenuItemCallbackFunction, userdata: ?*anyopaque) callconv(.C) ?*PDMenuItem,
addOptionsMenuItem: fn (title: [*c]const u8, optionTitles: [*c][*c]const u8, optionsCount: c_int, f: ?PDMenuItemCallbackFunction, userdata: ?*anyopaque) callconv(.C) ?*PDMenuItem,
removeAllMenuItems: fn () callconv(.C) void,
removeMenuItem: fn (menuItem: ?*PDMenuItem) callconv(.C) void,
getMenuItemValue: fn (menuItem: ?*PDMenuItem) callconv(.C) c_int,
setMenuItemValue: fn (menuItem: ?*PDMenuItem, value: c_int) callconv(.C) void,
getMenuItemTitle: fn (menuItem: ?*PDMenuItem) callconv(.C) [*c]const u8,
setMenuItemTitle: fn (menuItem: ?*PDMenuItem, title: [*c]const u8) callconv(.C) void,
getMenuItemUserdata: fn (menuItem: ?*PDMenuItem) callconv(.C) ?*anyopaque,
setMenuItemUserdata: fn (menuItem: ?*PDMenuItem, ud: ?*anyopaque) callconv(.C) void,
getReduceFlashing: fn () callconv(.C) c_int,
// 1.1
getElapsedTime: fn () callconv(.C) f32,
resetElapsedTime: fn () callconv(.C) void,
// 1.4
getBatteryPercentage: fn () callconv(.C) f32,
getBatteryVoltage: fn () callconv(.C) f32,
};
pub const LCDVideoPlayer = anyopaque;
pub const PlaydateVideo = extern struct {
loadVideo: fn ([*c]const u8) callconv(.C) ?*LCDVideoPlayer,
freePlayer: fn (?*LCDVideoPlayer) callconv(.C) void,
setContext: fn (?*LCDVideoPlayer, ?*LCDBitmap) callconv(.C) c_int,
useScreenContext: fn (?*LCDVideoPlayer) callconv(.C) void,
renderFrame: fn (?*LCDVideoPlayer, c_int) callconv(.C) c_int,
getError: fn (?*LCDVideoPlayer) callconv(.C) [*c]const u8,
getInfo: fn (?*LCDVideoPlayer, [*c]c_int, [*c]c_int, [*c]f32, [*c]c_int, [*c]c_int) callconv(.C) void,
getContext: fn (?*LCDVideoPlayer) callconv(.C) ?*LCDBitmap,
};
const LCD_COLUMNS = 400;
const LCD_ROWS = 240;
const LCD_ROWSIZE = 52;
pub const LCDPattern = [16]u8;
pub const LCDPatternSlice = []u8;
pub const LCDColor = usize; //Pointer to LCDPattern or a LCDSolidColor value
pub const LCDSolidColor = enum(c_int) {
ColorBlack,
ColorWhite,
ColorClear,
ColorXOR,
};
pub const LCDBitmapDrawMode = enum(c_int) {
DrawModeCopy,
DrawModeWhiteTransparent,
DrawModeBlackTransparent,
DrawModeFillWhite,
DrawModeFillBlack,
DrawModeXOR,
DrawModeNXOR,
DrawModeInverted,
};
pub const LCDLineCapStyle = enum(c_int) {
LineCapStyleButt,
LineCapStyleSquare,
LineCapStyleRound,
};
pub const LCDFontLanguage = enum(c_int) {
LCDFontLanguageEnglish,
LCDFontLanguageJapanese,
LCDFontLanguageUnknown,
};
pub const LCDBitmapFlip = enum(c_int) {
BitmapUnflipped,
BitmapFlippedX,
BitmapFlippedY,
BitmapFlippedXY,
};
pub const LCDPolygonFillRule = enum(c_int) {
PolygonFillNonZero,
PolygonFillEvenOdd,
};
pub const LCDBitmapTable = anyopaque;
pub const LCDFont = anyopaque;
pub const LCDFontPage = anyopaque;
pub const LCDFontGlyph = anyopaque;
pub const LCDRect = extern struct {
left: c_int,
right: c_int,
top: c_int,
bottom: c_int,
};
pub const PlaydateGraphics = extern struct {
video: *const PlaydateVideo,
// Drawing Functions
clear: fn (color: LCDColor) callconv(.C) void,
setBackgroundColor: fn (color: LCDSolidColor) callconv(.C) void,
setStencil: fn (stencil: ?*LCDBitmap) callconv(.C) void, // deprecated in favor of setStencilImage, which adds a "tile" flag
setDrawMode: fn (mode: LCDBitmapDrawMode) callconv(.C) void,
setDrawOffset: fn (dx: c_int, dy: c_int) callconv(.C) void,
setClipRect: fn (x: c_int, y: c_int, width: c_int, height: c_int) callconv(.C) void,
clearClipRect: fn () callconv(.C) void,
setLineCapStyle: fn (endCapStyle: LCDLineCapStyle) callconv(.C) void,
setFont: fn (font: ?*LCDFont) callconv(.C) void,
setTextTracking: fn (tracking: c_int) callconv(.C) void,
pushContext: fn (target: ?*LCDBitmap) callconv(.C) void,
popContext: fn () callconv(.C) void,
drawBitmap: fn (bitmap: ?*LCDBitmap, x: c_int, y: c_int, flip: LCDBitmapFlip) callconv(.C) void,
tileBitmap: fn (bitmap: ?*LCDBitmap, x: c_int, y: c_int, width: c_int, height: c_int, flip: LCDBitmapFlip) callconv(.C) void,
drawLine: fn (x1: c_int, y1: c_int, x2: c_int, y2: c_int, width: c_int, color: LCDColor) callconv(.C) void,
fillTriangle: fn (x1: c_int, y1: c_int, x2: c_int, y2: c_int, x3: c_int, y3: c_int, color: LCDColor) callconv(.C) void,
drawRect: fn (x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) callconv(.C) void,
fillRect: fn (x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) callconv(.C) void,
drawEllipse: fn (x: c_int, y: c_int, width: c_int, height: c_int, lineWidth: c_int, startAngle: f32, endAngle: f32, color: LCDColor) callconv(.C) void,
fillEllipse: fn (x: c_int, y: c_int, width: c_int, height: c_int, startAngle: f32, endAngle: f32, color: LCDColor) callconv(.C) void,
drawScaledBitmap: fn (bitmap: ?*LCDBitmap, x: c_int, y: c_int, xscale: f32, yscale: f32) callconv(.C) void,
drawText: fn (text: ?*const anyopaque, len: usize, encoding: PDStringEncoding, x: c_int, y: c_int) callconv(.C) c_int,
// LCDBitmap
newBitmap: fn (width: c_int, height: c_int, color: LCDColor) callconv(.C) ?*LCDBitmap,
freeBitmap: fn (bitmap: ?*LCDBitmap) callconv(.C) void,
loadBitmap: fn (path: [*c]const u8, outerr: ?*[*c]const u8) callconv(.C) ?*LCDBitmap,
copyBitmap: fn (bitmap: ?*LCDBitmap) callconv(.C) ?*LCDBitmap,
loadIntoBitmap: fn (path: [*c]const u8, bitmap: ?*LCDBitmap, outerr: ?*[*c]const u8) callconv(.C) void,
getBitmapData: fn (bitmap: ?*LCDBitmap, width: ?*c_int, height: ?*c_int, rowbytes: ?*c_int, hasmask: ?*c_int, data: ?*[*c]u8) callconv(.C) void,
clearBitmap: fn (bitmap: ?*LCDBitmap, bgcolor: LCDColor) callconv(.C) void,
rotatedBitmap: fn (bitmap: ?*LCDBitmap, rotation: f32, xscale: f32, yscale: f32, allocedSize: ?*c_int) callconv(.C) ?*LCDBitmap,
// LCDBitmapTable
newBitmapTable: fn (count: c_int, width: c_int, height: c_int) callconv(.C) ?*LCDBitmapTable,
freeBitmapTable: fn (table: ?*LCDBitmapTable) callconv(.C) void,
loadBitmapTable: fn (path: [*c]const u8, outerr: ?*[*c]const u8) callconv(.C) ?*LCDBitmapTable,
loadIntoBitmapTable: fn (path: [*c]const u8, table: ?*LCDBitmapTable, outerr: ?*[*c]const u8) callconv(.C) void,
getTableBitmap: fn (table: ?*LCDBitmapTable, idx: c_int) callconv(.C) ?*LCDBitmap,
// LCDFont
loadFont: fn (path: [*c]const u8, outErr: ?*[*c]const u8) callconv(.C) ?*LCDFont,
getFontPage: fn (font: ?*LCDFont, c: u32) callconv(.C) ?*LCDFontPage,
getPageGlyph: fn (page: ?*LCDFontPage, c: u32, bitmap: ?**LCDBitmap, advance: ?*c_int) callconv(.C) ?*LCDFontGlyph,
getGlyphKerning: fn (glyph: ?*LCDFontGlyph, glyphcode: u32, nextcode: u32) callconv(.C) c_int,
getTextWidth: fn (font: ?*LCDFont, text: ?*const anyopaque, len: usize, encoding: PDStringEncoding, tracking: c_int) callconv(.C) c_int,
// raw framebuffer access
getFrame: fn () callconv(.C) [*c]u8, // row stride = LCD_ROWSIZE
getDisplayFrame: fn () callconv(.C) [*c]u8, // row stride = LCD_ROWSIZE
getDebugBitmap: ?fn () callconv(.C) ?*LCDBitmap, // valid in simulator only, function is null on device
copyFrameBufferBitmap: fn () callconv(.C) ?*LCDBitmap,
markUpdatedRows: fn (start: c_int, end: c_int) callconv(.C) void,
display: fn () callconv(.C) void,
// misc util.
setColorToPattern: fn (color: ?*LCDColor, bitmap: ?*LCDBitmap, x: c_int, y: c_int) callconv(.C) void,
checkMaskCollision: fn (bitmap1: ?*LCDBitmap, x1: c_int, y1: c_int, flip1: LCDBitmapFlip, bitmap2: ?*LCDBitmap, x2: c_int, y2: c_int, flip2: LCDBitmapFlip, rect: LCDRect) callconv(.C) c_int,
// 1.1
setScreenClipRect: fn (x: c_int, y: c_int, width: c_int, height: c_int) callconv(.C) void,
// 1.1.1
fillPolygon: fn (nPoints: c_int, coords: [*c]c_int, color: LCDColor, fillRule: LCDPolygonFillRule) callconv(.C) void,
getFontHeight: fn (font: ?*LCDFont) callconv(.C) u8,
// 1.7
getDisplayBufferBitmap: fn () callconv(.C) ?*LCDBitmap,
drawRotatedBitmap: fn (bitmap: ?*LCDBitmap, x: c_int, y: c_int, rotation: f32, centerx: f32, centery: f32, xscale: f32, yscale: f32) callconv(.C) void,
setTextLeading: fn (lineHeightAdustment: c_int) callconv(.C) void,
// 1.8
setBitmapMask: fn (bitmap: ?*LCDBitmap, mask: ?*LCDBitmap) callconv(.C) c_int,
getBitmapMask: fn (bitmap: ?*LCDBitmap) callconv(.C) ?*LCDBitmap,
// 1.10
setStencilImage: fn (stencil: ?*LCDBitmap, tile: c_int) callconv(.C) void,
};
const PlaydateDisplay = struct {
getWidth: fn () callconv(.C) c_int,
getHeight: fn () callconv(.C) c_int,
setRefreshRate: fn (rate: f32) callconv(.C) void,
setInverted: fn (flag: c_int) callconv(.C) void,
setScale: fn (s: c_uint) callconv(.C) void,
setMosaic: fn (x: c_uint, y: c_uint) callconv(.C) void,
setFlipped: fn (x: c_uint, y: c_uint) callconv(.C) void,
setOffset: fn (x: c_uint, y: c_uint) callconv(.C) void,
};
const game = @import("main.zig");
const pdapi = @import("playdate_api.zig");
comptime {
asm (
\\.global _bss_start
\\.global _bss_end
\\.extern __bss_start__
\\.extern __bss_end__
\\.section .bss_start
\\_bss_start:
\\ .word __bss_start__
\\.section .bss_end
\\_bss_end:
\\ .word __bss_end__
\\
\\.section .text
\\.global eventHandler
\\.global _start
\\_start:
\\ b eventHandler //This is never exectued, but required for the linker to not optimize out the eventHandler function
);
}
export var PD_eventHandler: fn (playdate: *pdapi.PlaydateAPI, event: pdapi.PDSystemEvent, arg: u32) callconv(.C) c_int linksection(".capi_handler") = game.eventHandler;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment