Compiling and building Palm-OS-Applications on Ubuntu 20.04 LTS (64 Bit)
07.06.2020
Since the last article about this topic is nearly one year old and already obsolete, because it is only working on Ubuntu 18.04.2 and not working on Ubuntu 18.04.4 LTS or newer, I decided to write one about compiling and building Palm-OS-Applications on Ubuntu 20.04 LTS (64 Bit).
Shortcut
There is an easier way to build Palm OS applications - with an updated shortcut (Version 2).
And a more efficient way to do this - with an (again) updated shortcut (Version 3).
It is understandable, that not everyone wants to redo very step I did. So I put everything, what is needed for buliding a Palm OS application in a big zip-file together. Just unzip it and run make
in a terminal.
Then you get a runnable .prc file for your Palm OS device. Of course you can then edit the example as you want or replace it with your own code. Just make sure it includes this function:
UInt32 __attribute__((section(".vectors"))) __Startup__(void) { SysAppInfoPtr appInfoP; void *prevGlobalsP; void *globalsP; UInt32 ret; SysAppStartup(&appInfoP, &prevGlobalsP, &globalsP); ret = PilotMain(appInfoP->cmd, appInfoP->cmdPBP, appInfoP->launchFlags); SysAppExit(appInfoP, prevGlobalsP, globalsP); return ret; }Download the complete dev-package for Ubuntu 20.04 LTS (64 Bit) (Version 1)
If you are interested in how everything is set up, you can read the complete article.
Needed packages
There was one major change, which makes one part of the last article unnecessary: building gcc 2.x. Luckly Dmitry Grinberg was able to make some adjustments on gcc 9.1 in order to be abe to compile source code for Palm OS applications with it. Gcc 9.1 is precompiled and ready for use after a few tweaks in the Palm OS SDK.
In order to be able to compile and build Palm-OS-Applictions on Linux you will need the following packages:
- pilrc_3.2-3build1_amd64.deb from
http://old-releases.ubuntu.com/ubuntu/pool/universe/p/pilrc/pilrc_3.2-3build1_amd64.deb*1 - Palm OS SDK "sdk-5r3" from
https://github.com/jichu4n/palm-os-sdk - prc-tools-remix from
https://github.com/stevelittle/prc-tools-remix*2 - gcc 9.1 from
https://www.reddit.com/r/Palm/comments/fu5870/announce_new_gcc_or_palmos/
Notes:
- *1) There is an unofficial release of PilRC 3.3: unoffical release of PilRC 3.3
- *2) Only the "prc-tools" are needed, since we will use the precompiled gcc 9.1.
PilRC
PilRC (PILot Resource Compiler) is a compiler, which turns a textual description of Palm OS forms, bitmaps, fonts, and other resources into a binary form that can be included in an application or library.
Installation
The installation of the PilRC-package is really straight forward. Just install it in via the command line with
dpkg -i pilrc_3.2-3build1_amd64.debor with a package manager of your choice.
Palm OS SDK
The Palm OS SDK provides all needed libraries and header-files, to write Palm OS applications. It is needed for every Palm OS application.
Installation
Since there is no installation file available, just download it and unzip it in a folder of your choice. One place could be in /opt
, so the full path can look like this:
/opt/palmdev/palm-os-sdk-master/sdk-5r3/include
In order to get everything to work, there are some changes in the SDK needed. I used the SDK "5r3" for my projects, which worked the best for me. Dmitry mentioned the following changes in "sdk-5r3/include/PalmTypes.h", but I was only able to find the first three parts, so I skipped the last one, which worked - so far - perfectly fine. If you do not want to do the changes by yourself, you can use this pre-editited SDK 5r3.
find in sdk-5r3/include/PalmTypes.h, line 210-223 :
#define _OS_CALL(table, vector) \ __attribute__ ((__callseq__ ( \ "trap #" _Str(table) "; dc.w " _Str(vector)))) #define _OS_CALL_WITH_SELECTOR(table, vector, selector) \ __attribute__ ((__callseq__ ( \ "moveq #" _Str(selector) ",%%d2; " \ "trap #" _Str(table) "; dc.w " _Str(vector)))) #define _OS_CALL_WITH_16BIT_SELECTOR(table, vector, selector) \ __attribute__ ((__callseq__ ( \ "move.w #" _Str(selector) ",-(%%sp); " \ "trap #" _Str(table) "; dc.w " _Str(vector) "; " \ "addq.w #2,%%sp")))replace with:
#define _OS_CALL(table, vector) __attribute__((__raw_inline__(0x4E40 + table, vector))); #define _OS_CALL_WITH_SELECTOR(table, vector, selector) __attribute__((__raw_inline__(0x7400 + selector, 0x4E40 + table, vector))); #define _OS_CALL_WITH_16BIT_SELECTOR(table, vector, selector) __attribute__((__raw_inline__(0x3F3C, selector, 0x4E40 + table, vector, 0x544F)));
prc-tools-remix
"prc-tools-remix" is a tool-set, which is needed to create a runnable .prc-application. The most important tool in this case is "prc-builder". It transforms .bin-files from the compiler into an executable for Palm OS.
Installation
Clone or download and unzip the prc-tools-remix from github. Next we just need to build the prc-tools, without gcc, since we are going to use the newer version of gcc from Dmitry. Like mentioned in the readme.md, create a "build" directory next to the "prc-tools-2.3" directory. Then a few libraries are needed:
sudo apt-get install \ texinfo \ flex \ bison \ gperf \ libncurses5-devAfter the installation of these libraries, run this command inside of the created "build" directory:
../prc-tools-2.3/configure \ --enable-targets=m68k-palmos,arm-palmos \ --enable-languages=c,c++ \ --disable-nls \ --with-palmdev-prefix=/opt/palmdev \ --host=i686-linux-gnuWith
make toolsonly the needed prc-tools will be compiled.
If the make process is not working for some reasons, you can also use these pre-compiled prc-tools. After the make process finished, the tools directory (inside the build directory) is needed. It can also be copied to "/opt/":
cp -r tools /opt/palmdev/prc-tools2_3
gcc 9.1
ggc is the compiler and translates sourcefiles into binary-files. Thankfully Dmitry Grinberg made modern gcc 9.1 ready for compiling palm os applications.
Installation
Like Dmitry mentioned in his reddit post, we need this package: m68k-none-elf_for_palmos.tar.bz2. After unpacking and copying in in our "/opt" directory it is already ready for use.
The Makefile
A makefile is a manual for every step, which is need to get a executable Palm application from sourcefiles. The basis of this makefile was written by Dmitry Grinberg, who thankfully gave permission to use and modify it for the individual use.
TOOLCHAIN ?= /opt/palmdev/toolchain/bin/ SDK ?= /opt/palmdev/palm-os-sdk-master/sdk-5r3/include MKPRC ?= /opt/palmdev/prc-tools2_3/build-prc CC = $(TOOLCHAIN)/m68k-none-elf-gcc LD = $(TOOLCHAIN)/m68k-none-elf-gcc OBJCOPY = $(TOOLCHAIN)/m68k-none-elf-objcopy COMMON = -Wno-multichar -funsafe-math-optimizations -Os -m68000 -mno-align-int -mpcrel -fpic -fshort-enums -mshort WARN = -Wsign-compare -Wextra -Wall -Werror -Wno-unused-parameter -Wno-old-style-declaration -Wno-unused-function -Wno-unused-variable -Wno-error=cpp LKR = linker.lkr CCFLAGS = $(LTO) $(WARN) $(COMMON) -I. -ffunction-sections -fdata-sections LDFLAGS = $(LTO) $(WARN) $(COMMON) -Wl,--gc-sections -Wl,-T $(LKR) SRCS = HelloWorld.c OBJS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRCS))) TARGET = test CREATOR = test #add PalmOS SDK INCS += -isystem$(SDK) INCS += -isystem$(SDK)/Core INCS += -isystem$(SDK)/Core/Hardware INCS += -isystem$(SDK)/Core/System INCS += -isystem$(SDK)/Core/UI INCS += -isystem$(SDK)/Dynamic INCS += -isystem$(SDK)/Libraries $(TARGET).prc: code0001.bin $(MKPRC) -c $(CREATOR) -n $(TARGET) -o $(TARGET).prc $< && rm code0001.bin %.bin: %.elf $(OBJCOPY) -O binary $< $@ -j.vec -j.text -j.rodata %.elf: $(OBJS) $(LD) -o $@ $(LDFLAGS) $^ %.o : %.c Makefile $(CC) $(CCFLAGS) $(INCS) -c $< -o $@ clean: rm -rf $(OBJS) $(NAME).elf .PHONY: cleanPlease keep in mind, that you maybe need to modify the following paths / parameters:
- TOOLCHAIN
- SDK
- MKPRC
- SRCS
- TARGET
- CREATOR
MEMORY { rom : ORIGIN = 0x10000000, LENGTH = 256K ram : ORIGIN = 0x20000000, LENGTH = 64K trash : ORIGIN = 0x40000000, LENGTH = 64K } SECTIONS { .vec : { KEEP( *(.vectors) ) ; *(.vectors); } > rom /* must be before .text to properly discard function names */ .trash2 : { *(.init) *(.init.*) ; *(.fini) *(.fini.*) ; *(*.macsbug) } > trash .text : { *(.text) *(.text.*)} > rom .rodata : { *(.rodata) *(.rodata.*) ; . = ALIGN(4); __data_data = ABSOLUTE(.) ; } > rom .data : AT ( ADDR ( .rodata ) + SIZEOF ( .rodata ) ) { . = ALIGN(4); __data_start = ADDR ( .data ) + . ; *(.data) ; *(.data.*) ; . = ALIGN(4); __data_end = ADDR ( .data ) + . ; } > ram .bss : { *(.bss) *(.bss.*) *(COMMON) ; } > ram } ENTRY(__Startup__)It was also written and provided by Dmitry - thanks!
A small example
This small example allows us to test our tool chain. It just outputs "Hello World". It can be saved as "HelloWorld.c".
#include <PalmOS.h> UInt32 PilotMain(UInt16 cmd, void *cmdPBP, UInt16 launchFlags) { EventType event; char *message = "Hello World"; if (sysAppLaunchCmdNormalLaunch == cmd) { WinDrawChars(message, StrLen(message), 54, 74); do { EvtGetEvent(&event, evtWaitForever); SysHandleEvent(&event); } while (event.eType != appStopEvent); } return 0; } UInt32 __attribute__((section(".vectors"))) __Startup__(void) { SysAppInfoPtr appInfoP; void *prevGlobalsP; void *globalsP; UInt32 ret; SysAppStartup(&appInfoP, &prevGlobalsP, &globalsP); ret = PilotMain(appInfoP->cmd, appInfoP->cmdPBP, appInfoP->launchFlags); SysAppExit(appInfoP, prevGlobalsP, globalsP); return ret; }It looks like, that the function
UInt32 __attribute__((section(".vectors"))) __Startup__(void)
is needed in very application.
Building the application
You should have the following files in one workspace folder:
If the paths in the makefile are correct, you can build the application just withmakeand you should get a small "test.prc" at the end, which shows only "Hello World":
Thanks to Dmitrys work, this way to build applications is even more efficient than building an application with CodeWarrior. Of course it has to be said that CodeWarrior has other advantages, such as a decent debugger. So the next step would probably be to build a pipeline that ensures that code, managed with git, is built and the application is made available with gcc 9.1. Also it would be interesting to build a bigger project with resources like UI elements.
For this project, I want to thank the PalmDB community and Dmitry Grinberg, who helped me a lot with many problems during setting everything up.
Building a complete Palm OS application with only two tools
After publishing this article, Dmitry contacted me and told me, it would be possible to build a Palm OS application with only two tools:
Of course also the Palm OS SDK: 5r3 and the linker.lkr is needed. After a conversation with him, reading the PilRC documentation and a bit of trying out, I was able to set everything up.Second shortcut
Again, I packed everything, what is needed in a zip-package, ready for usage:
Download the complete dev-package
for Ubuntu 20.04 LTS (64 Bit) (Version 2)
Usage is easy as the last time:
Just unpack the zip-file and run make
Of course you can edit the make and source file as you need it. But do not forget to include the mentioned
function from the first shortcut, if you begin a blank project.
If you are interested in how version 2 is set up, you can read the rest of this article.
No need for prc-tools
Only Dmitrys gcc 9.1 and PilRC is needed to create a fully working tool chain for building Palm OS applications on Ubuntu 20.04. The installation for gcc 9.1 is still the same and also the installation for PilRC has not changed. Only compiling the prc-tools isn't necessary anymore. You sill need the Palm OS SDK and the linker.lkr. The alternative to the installation of "pilrc_3.2-3build1_amd64.deb", is to download and unpack the "pilrc-3.2-1.i386.rpm" from https://sourceforge.net/projects/pilrc/files/pilrc/3.2/. (Just rename the ".rpm" file to ".zip" for unpacking it). This is what I did for the dev-package in order to get an independent bundle, which can be executed without installing anything.
The makefile
Since the prc-tools dropped out of the build chain, we need to adjust the makefile a bit. It now looks like this:
TOOLCHAIN ?= buildtools/toolchain/bin/ SDK ?= buildtools/palm-os-sdk-master/sdk-5r3/include PILRC = pilrc CC = $(TOOLCHAIN)/m68k-none-elf-gcc LD = $(TOOLCHAIN)/m68k-none-elf-gcc OBJCOPY = $(TOOLCHAIN)/m68k-none-elf-objcopy COMMON = -Wno-multichar -funsafe-math-optimizations -Os -m68000 -mno-align-int -mpcrel -fpic -fshort-enums -mshort WARN = -Wsign-compare -Wextra -Wall -Werror -Wno-unused-parameter -Wno-old-style-declaration -Wno-unused-function -Wno-unused-variable -Wno-error=cpp -Wno-error=switch LKR = linker.lkr CCFLAGS = $(LTO) $(WARN) $(COMMON) -I. -ffunction-sections -fdata-sections LDFLAGS = $(LTO) $(WARN) $(COMMON) -Wl,--gc-sections -Wl,-T $(LKR) SRCS = Src/helloWorld.c RCP = Src/helloWorld.rcp RSC = Src/ OBJS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRCS))) TARGET = test CREATOR = test TYPE = appl #add PalmOS SDK INCS += -isystem$(SDK) INCS += -isystem$(SDK)/Core INCS += -isystem$(SDK)/Core/Hardware INCS += -isystem$(SDK)/Core/System INCS += -isystem$(SDK)/Core/UI INCS += -isystem$(SDK)/Dynamic INCS += -isystem$(SDK)/Libraries INCS += -isystem$(SDK)/Libraries/PalmOSGlue $(TARGET).prc: code0001.bin $(PILRC) -ro -o $(TARGET).prc -creator $(CREATOR) -type $(TYPE) -name $(TARGET) -I $(RSC) $(RCP) && rm code0001.bin %.bin: %.elf $(OBJCOPY) -O binary $< $@ -j.vec -j.text -j.rodata %.elf: $(OBJS) $(LD) -o $@ $(LDFLAGS) $^ %.o : %.c Makefile $(CC) $(CCFLAGS) $(INCS) -c $< -o $@ clean: rm -rf $(OBJS) $(NAME).elf .PHONY: clean
Please keep in mind, that you maybe need to modify the following paths / parameters:
- TOOLCHAIN
- SDK
- PILRC
- SRCS
- RCP
- RSC
- TARGET
- CREATOR
- TYPE
A small example with more possibilities
The actual example hasn't changed and can be used again. But in addition, a resource file with the extension ".rpc" is needed, with at least this content:
DATA "code" ID 1 "code0001.bin"You can also add in this rpc-file UI elements. Since we are going to build it with PilRC, it will also take care of these resources. PilRC will also look into the "Src" folder for e.g. bitmap files.
After executing the makefile with make
you will get a runnable .prc file, which can be executed on a Palm or POSE. Luckily this POSE installation guide is still valid for Ubuntu 20.04.
Besides of the already mentioned git depended build pipline, it would be also nice to have an unofficial PilRC 3.3 build and also POSE included in a standalone dev-package. Therefore a dev-package version 3 will most likely follow.
PilRC 3.3 unofficial and POSE
Right after publishing the last update of this article I tried to add
the changes from Dmitry to the PilRC source code and compiled it: with success. Also POSE (Palm OS Emulator) was added, in order to have a possibility to test the built application right on Linux. But before I explain how everything is set up, I created (again) a (nearly full) stand-alone dev-package (version 3):
Download the complete dev-package
for Ubuntu 20.04 LTS (64 Bit) (Version 3)
This package includes the same as Version 2 but with POSE and replaces PilRC with version 3.3 unofficial. Using is also the same, just run it with ./startPose.sh
, which just executes the runnable in the "addons" directory.
Sadly, POSE cannot run as a stand-alone application. "libxext6:i386" is required, what can be installed with
sudo apt-get install libxext6:i386But the other build tools are still stand-alone tools.
Patching and compiling PilRC 3.3 unofficial
First we need the PilRC 3.2 sourc files. They are available here. We also need to download Dmitrys changes and unpacking the .patch files in the same directory as the PilRC source files. In the next step, we need to apply these patch files with these commands from the inside of the PilRC directory:
patch < 0001*.patch patch < 0002*.patch patch < 0003*.patch patch < 0004*.patch patch < 0005*.patch patch < 0006*.patch patch < 0007*.patch patch < 0008*.patch patch < 0009*.patch patch < 0010*.patch patch < 0011*.patch patch < 0012*.patch patch < 0013*.patch patch < 0014*.patch patch < 0015*.patchIn order to see, that we are using a new, unofficial version of PilRC, I have created a patch file, which simply changes the version string in the
version.h
:
--- version.h 2004-01-29 09:34:43.000000000 -0800 +++ version.h 2020-06-11 04:19:39.527995655 -0700 @@ -34,6 +34,6 @@ */ #define PILRC_VERSION 3, 2, 0, 0 -#define PILRC_VERSION_STR "3.2" +#define PILRC_VERSION_STR "3.3 unofficial" #endifSince I didn't check where and how the constant
PILRC_VERSION
is used, I left it, how it was in order not to cause unwanted problems.
This patch file needs to be executed, too. Like the others:
patch < 0016*.patchAfter applying the patches, we need to compile PilRC in 32bit mode - thanks to Dmitry for this hint. Otherwise, you will get a corrupt pilrc executable, which is not able to generate runnable .prc-files. First, we need to install gcc with 32bit support, since the standard version of gcc on Ubuntu 20.04 does not support compiling in 32bit mode:
sudo apt-get install gcc-multilibNext, we need to generate a Makefile (and doing some other tasks) with
./unix/configureIn the Makefile we need to tell gcc, that it has to use the 32bit mode. The easiest way to do this, is changing in the generated Makefile line 108 from:
CC = gccto:
CC = gcc -m32The last step is not run these two commands:
sudo make sudo make installThe
sudo make install
command also copies the compiled pilrc executable to /usr/local/bin/
which make it system wide available. Of course this does not apply to the stand-alone version.
At this point, the compiled pilrc
executable is ready for usage. When you execute it, you can see, that is was built correctly with the improvements from Dmitry and the new version string:
user@ubuntu:~/pilrc_src$ pilrc PilRC v3.3 unofficial Copyright 1997-1999 Wes Cherry (wesc@ricochet.net) Copyright 2000-2004 Aaron Ardiri (aaron@ardiri.com) This program is free software; you may redistribute it under the terms of the GNU General Public License. This program has absolutely no warranty, you use it AS IS at your own risk. Usage: pilrc {} infile [outfiledir] Options: -L LANGUAGE Use the TRANSLATION section for the given language ...
POSE
Since this POSE installation guide is still working for Ubuntu 20.04, here only a short version of this guide:
First get the .rpm file from https://sourceforge.net/projects/pose/files/pose/3.5-2/pose-3.5-2.i386.rpm/download. Then installlibxext6:i386
with
sudo apt-get install libxext6:i386After this step, just rename the downloaded .rpm file into a .zip file and unpack it. The unpacked executable runs just fine:
./usr/bin/pose
Final words
After the third release of this article and all the changes, that have been made on the tool chain to develop Palm OS applications on Ubuntu 20.04, we have reached a point, where you can (for now) leave everything as it is. The tool chain is, thanks to Dmitry Grinberg, up to date and with only two tools and some libraries very compact. Hopefully it will run on future Ubuntu releases, too.
If you plan to write applications for Palm OS 2.0, use Version 2 of the dev-package, since the improvements from Dmitry are not fully supported by Palm OS 2.0.