Open pattmax00 opened 11 months ago
Hey playdate support I just got my playdate handheld on May the 16th and then on May the 17th I was say up my playdate handheld and it was not looking too good so how can I fix my playdate handheld
I'd also like to see how doable this is. I'm not sure if tinygo should handle the creation of a .pdx
file, or if a playdate(-simulator).json
target that outputs an object file ready to be used by the playdate supplied Makefile would suffice.
This is what their standard Makefile expects:
HEAP_SIZE = 8388208
STACK_SIZE = 61800
PRODUCT = game.pdx
SDK = ${PLAYDATE_SDK_PATH}
ifeq ($(SDK),)
SDK = $(shell egrep '^\s*SDKRoot' ~/.Playdate/config | head -n 1 | cut -c9-)
endif
ifeq ($(SDK),)
$(error SDK path not found; set ENV value PLAYDATE_SDK_PATH)
endif
VPATH += Source
SRC = \
Source/main.c
UINCDIR =
UASRC =
UDEFS =
UADEFS =
ULIBDIR =
ULIBS =
include $(SDK)/C_API/buildsupport/common.mk
and common.mk
:
detected_OS := $(shell uname -s)
detected_OS := $(strip $(detected_OS))
$(info detected_OS is "$(detected_OS)")
ifeq ($(detected_OS), Linux)
GCCFLAGS = -g
SIMCOMPILER = gcc $(GCCFLAGS)
DYLIB_FLAGS = -shared -fPIC
DYLIB_EXT = so
PDCFLAGS = -sdkpath $(SDK)
endif
ifeq ($(detected_OS), Darwin)
CLANGFLAGS = -g
SIMCOMPILER = clang $(CLANGFLAGS)
DYLIB_FLAGS = -dynamiclib -rdynamic
DYLIB_EXT = dylib
PDCFLAGS=
# Uncomment to build a binary that works with Address Sanitizer
#CLANGFLAGS += -fsanitize=address
endif
TRGT = arm-none-eabi-
GCC:=$(dir $(shell which $(TRGT)gcc))
ifeq ($(GCC),)
GCC = /usr/local/bin/
endif
OJBCPY:=$(dir $(shell which $(TRGT)objcopy))
ifeq ($(OJBCPY),)
OJBCPY = /usr/local/bin/
endif
PDC = $(SDK)/bin/pdc
VPATH += $(SDK)/C_API/buildsupport
CC = $(GCC)$(TRGT)gcc -g3
CP = $(OJBCPY)$(TRGT)objcopy
AS = $(GCC)$(TRGT)gcc -x assembler-with-cpp
STRIP= $(GCC)$(TRGT)strip
BIN = $(CP) -O binary
HEX = $(CP) -O ihex
MCU = cortex-m7
# List all default C defines here, like -D_DEBUG=1
DDEFS = -DTARGET_PLAYDATE=1 -DTARGET_EXTENSION=1
# List all default directories to look for include files here
DINCDIR = . $(SDK)/C_API
# List all default ASM defines here, like -D_DEBUG=1
DADEFS =
# List the default directory to look for the libraries here
DLIBDIR =
# List all default libraries here
DLIBS =
OPT = -O2 -falign-functions=16 -fomit-frame-pointer
#
# Define linker script file here
#
LDSCRIPT = $(patsubst ~%,$(HOME)%,$(SDK)/C_API/buildsupport/link_map.ld)
#
# Define FPU settings here
#
FPU = -mfloat-abi=hard -mfpu=fpv5-sp-d16 -D__FPU_USED=1
INCDIR = $(patsubst %,-I %,$(DINCDIR) $(UINCDIR))
LIBDIR = $(patsubst %,-L %,$(DLIBDIR) $(ULIBDIR))
OBJDIR = build
DEPDIR = $(OBJDIR)/dep
DEFS = $(DDEFS) $(UDEFS)
ADEFS = $(DADEFS) $(UADEFS) -D__HEAP_SIZE=$(HEAP_SIZE) -D__STACK_SIZE=$(STACK_SIZE)
SRC += $(SDK)/C_API/buildsupport/setup.c
# Original object list
_OBJS = $(SRC:.c=.o)
# oject list in build folder
OBJS = $(addprefix $(OBJDIR)/, $(_OBJS))
LIBS = $(DLIBS) $(ULIBS)
MCFLAGS = -mthumb -mcpu=$(MCU) $(FPU)
ASFLAGS = $(MCFLAGS) $(OPT) -g3 -gdwarf-2 -Wa,-amhls=$(<:.s=.lst) $(ADEFS)
CPFLAGS = $(MCFLAGS) $(OPT) -gdwarf-2 -Wall -Wno-unused -Wstrict-prototypes -Wno-unknown-pragmas -fverbose-asm -Wdouble-promotion -mword-relocations -fno-common
CPFLAGS += -ffunction-sections -fdata-sections -Wa,-ahlms=$(OBJDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
LDFLAGS = -nostartfiles $(MCFLAGS) -T$(LDSCRIPT) -Wl,-Map=$(OBJDIR)/pdex.map,--cref,--gc-sections,--no-warn-mismatch,--emit-relocs $(LIBDIR)
# Generate dependency information
CPFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
#
# makefile rules
#
all: device_bin simulator_bin
$(PDC) $(PDCFLAGS) Source $(PRODUCT)
debug: OPT = -O0
debug: all
print-% : ; @echo $* = $($*)
MKOBJDIR:
mkdir -p $(OBJDIR)
MKDEPDIR:
mkdir -p $(DEPDIR)
device: device_bin
$(PDC) $(PDCFLAGS) Source $(PRODUCT)
simulator: simulator_bin
$(PDC) $(PDCFLAGS) Source $(PRODUCT)
device_bin: $(OBJDIR)/pdex.elf
cp $(OBJDIR)/pdex.elf Source
simulator_bin: $(OBJDIR)/pdex.${DYLIB_EXT}
cp $(OBJDIR)/pdex.${DYLIB_EXT} Source
# pdc is deprecated but in the old docs, alias to simulator
pdc: simulator
# for external builds (Xcode)
pdx:
$(PDC) $(PDCFLAGS) Source $(PRODUCT)
$(OBJDIR)/%.o : %.c | MKOBJDIR MKDEPDIR
mkdir -p `dirname $@`
$(CC) -c $(CPFLAGS) -I . $(INCDIR) $< -o $@
$(OBJDIR)/%.o : %.s | MKOBJDIR MKDEPDIR
$(AS) -c $(ASFLAGS) $< -o $@
.PRECIOUS: $(OBJDIR)/%elf
.PRECIOUS: $(OBJDIR)/%bin
.PRECIOUS: $(OBJDIR)/%hex
$(OBJDIR)/pdex.elf: $(OBJS) $(LDSCRIPT)
$(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
$(OBJDIR)/pdex.hex: $(OBJDIR)/pdex.elf
$(HEX) $< $@
$(OBJDIR)/pdex.bin: $(OBJDIR)/pdex.elf
$(BIN) $< $@
$(OBJDIR)/pdex.${DYLIB_EXT}: $(SRC) | MKOBJDIR
$(SIMCOMPILER) $(DYLIB_FLAGS) -lm -DTARGET_SIMULATOR=1 -DTARGET_EXTENSION=1 $(INCDIR) -o $(OBJDIR)/pdex.${DYLIB_EXT} $(SRC)
clean:
-rm -rf $(OBJDIR)
-rm -fR $(PRODUCT)
-rm -fR Source/pdex.bin
-rm -fR Source/pdex.dylib
-rm -fR Source/pdex.so
-rm -fR Source/pdex.dll
-rm -fR Source/pdex.elf
#
# Include the dependency files, should be the last of the makefile
#
-include $(wildcard $(DEPDIR)/*)
# *** EOF ***
link_map.ld
is their custom linker script:
ENTRY(eventHandlerShim)
GROUP(libgcc.a libc.a libm.a)
SECTIONS
{
.text :
{
*(.text)
*(.text.*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
}
.data :
{
__etext = .;
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
}
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
*(COM)
. = ALIGN(4);
__bss_end__ = .;
}
/DISCARD/ :
{
*(.ARM.exidx)
}
}
setup.c
is simple and just has a few externs and forward decls, notably eventHandlerShim
that calls into user code:
#include "pd_api.h"
typedef int (PDEventHandler)(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg);
extern PDEventHandler eventHandler;
static void* (*pdrealloc)(void* ptr, size_t size);
int eventHandlerShim(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg)
{
if ( event == kEventInit )
pdrealloc = playdate->system->realloc;
return eventHandler(playdate, event, arg);
}
#if TARGET_PLAYDATE
void* _malloc_r(struct _reent* _REENT, size_t nbytes) { return pdrealloc(NULL,nbytes); }
void* _realloc_r(struct _reent* _REENT, void* ptr, size_t nbytes) { return pdrealloc(ptr,nbytes); }
void _free_r(struct _reent* _REENT, void* ptr ) { if ( ptr != NULL ) pdrealloc(ptr,0); }
#else
void* malloc(size_t nbytes) { return pdrealloc(NULL,nbytes); }
void* realloc(void* ptr, size_t nbytes) { return pdrealloc(ptr,nbytes); }
void free(void* ptr ) { if ( ptr != NULL ) pdrealloc(ptr,0); }
#endif
I've been trying to figure out how to create a target.json
(mostly copying the cortex-m7
target and modifying where needed. Currently running into undefined references to things like mmap
, tinygo_scanCurrentStack
, _write_r
, _kill_r
, etc.
Luckily there's a free simulator created by the playdate team that would let this be tested without the need for hardware. I can also volunteer my playdate console for testing as well.
You would need to add support for the STM32F746 as well as specific board support for the Playdate. A PR you could use as an example, is this one: https://github.com/tinygo-org/tinygo/pull/4219
It would be nice to have Playdate support. It is using a Cortex M7 (ARM) processor which is already supported: https://github.com/tinygo-org/tinygo/issues/512 https://github.com/cmsis-svd/cmsis-svd/pull/82
A good example of a final C project that could maybe help as a reference would be this: https://github.com/ericlewis/playdate-tamagotchi since the final
.pdx
is quite simple. The.pdx
is basically just a folder with.pdi
filesYou can extract the latest release yourself to see.
Even if we could just compile the
pdex.bin
would be nice.Here is the C API reference
I think the GBA implementation is already performing some extra steps to build a
.gba
ROM file. So being able to compile for the Playdate and build a.pdx
shouldn't be outside the scope of this project, but if it is feel free to let me know and close the issue, but I think the Playdate would be a very good candidate for TinyGo.