TamsPalm - the Palm OS Blog

Palm OS news and opinion source

April 29th, 2008

Data encryption on Palm OS handhelds

In case anyone of you frees like adding encryption to your applications, being a palm-dev-forum subscriber definitely pays out.

The folks there currently discuss the various encryption options available to Palm OS developers - if your apps need a security improvement, click the link below to get to the first post:
Data encryption Palm OS

February 26th, 2008

Invalid Insertion Point Position via FldSetFocus - what to do

The code below has worked well on all handhelds I ever put my paws on - but failed miserably on the simulator:

case frmOpenEvent:
createLVL();
FrmDrawForm(pForm);
StrCopy(vars.msg1,"Action!!");
vars.msg1_framestolive=MSG_LIFETIME;
lasttic=TimGetTicks();
FrmSetFocus(pForm,FrmGetObjectIndex(pForm,FldShadow)); //allows GSPDA T9 keys to function
handled = true;
break;

The simulator gave an alert along the lines of “Invalid insertion point” - WTF?

The alert text above is a classic example for a completely unrelated error message - the reason for the alert is simple: the text field FldShadow is not high enough for the text it should contain. Just increase the height of the field - and the fatal alert is gone for good!

December 14th, 2007

SDL beeing ported to Palm OS

A library called SDL is at the core of many(if not most) OpenSource projects - they use the library’s functions for various tasks like graphics and sound. WikiPedia describes the library as following:

Simple DirectMedia Layer (SDL) is a cross-platform, multimedia, free software library written in C that creates an abstraction over various platforms’ graphics, sound, and input APIs, allowing a developer to write a computer game or other multimedia application once and run it on many operating systems including Linux, Windows, Mac OS X, AmigaOS and its clone MorphOS. It manages video, events, digital audio, CD-ROM, sound, threads, shared object loading, networking and timers.

Now, an user called TomB has opened a thread on Nexave, announcing that he is working on porting this very library to Palm OS. Here is a translation of his german post:

Dear Ladies and Gentlemen,

I have posted a first version of my port right here: https://sourceforge.net/project/showfiles.php?group_id=212180. I have included a few t5est programs and games that run well on a Treo 650 and a Zodiac - a Tungsten E has had issues due to low RAM.

I would be very thankful for testers!
For developers: I support all except OpenGL, CDRom and Threads. The libraries SDL_mixer, SDL_image and spritelib are included. Additionally, ARM versions of most standard C library calls are included as a bonus!

Should anyone of you feel like testing the SDL port for Palm OS, please leave a comment with your experiences here. Alexander Gratz and I will then post the URL of this post to Nexave in order to allow TomB to participate in the discussion!

October 22nd, 2007

ZLauncher Plug-In API for OnBoardC

ZLauncher is a very popular launcher replacement for Palm OS handhelds - it can easily be expanded by third party developers using the ZLauncher plug-in API. A sample for the API is contained in the distribution file - however, getting it ready for OnBoardC usage is not exactly easy.

This version of ZLPlugin.h has worked well for me with OnBoardC 2.4 and 2.6 - it allows you to use all ZLauncher functions except for ZLDrawChars(no idea why, but it kills the compile process). Additionally, the current build of ZLauncher seems to have a bug in the variable-length preference functions…the calls execute correctly, but don’t work(aka save/read data).

Anyways, here goes:
ZLPlugin.h.pdb

September 18th, 2007

Sine/Cosine lookup table

After having followed a discussion about charting in the palm-dev-forum, I felt that the following lookup tables could potentially be useful for some of you. I generated them using SmallBASIC and use them in BallZ(the Palm OS JezzBall clone).

Anyways, the input is in traditional degrees, and the output is a float value. If you are short on memory, you could also transform the input to the sine table to get cosine or vice versa…although this IMHO doesn’t pay out(a simple lookup is faster)…

Read the rest of this entry »

September 2nd, 2007

CamLibControl - the call that doesn’t work

Ever since the Palm Treo 600, Palm OS Treos contain integrated CMOS cameras that can produce decent images. Since the Treo 650, these cameras can be controlled via the so-called Camera Manager, an API that should let you control brightness, contrast and saturation comfortably…

However, the API’s Palm itself provides do not work on any shipping Treo. I myself have tested the MiniCamera sample from the SDK on a Palm Treo 650 and a Treo 680 and can report that changing brightness and contrast of images(!!!) via CamLibControl works on neither. A comrade from 1src has tested MiniCamera on a Treo 755p(latest Palm device) and doesn’t report any successes either.

So, to cut a long story short, you can NOT programatically change image brightness/contrast on a Palm OS Treo. You need to live with what the camera manager provides…so much for the Treo being a high-tech smartphone. As for the MiniCamera API sample … do not ask me why it is in there if it doesn’t work :-)

P.s. Sorry for the aggressive tune…but please, Palm, come on. I mean, every 100 dumb phone can do that!

August 29th, 2007

Globals in DAs

Everybody who has tried to make DAs (Desk Accessories) knows you can’t use global variables in the code. There are ways to go around that problem, of course, but all I have seen are either slow, like reading and writing to databases, or complicated to use, like using Feature Memory (I never figured out how to read from it!). The easiest way I found is to use Application-Defined Features to store pointers to variables in Dynamic Heap. It practically gives you real global variables to use in your DA! This is how it works:

1. Define your application creator
#define DACREATOR 'myDA'

2. Define a the name of your feature ID giving it a unique number. To make it real easy, give it a name reminding of the global which pointer it will contain. I put an “f” in front of it.
#define fBuffer 1

3. For ease of use, put in the following two functions already published on TamsPalm:
//------------------------------------
MemPtr malloc(UInt16 size) {
MemHandle h = MemHandleNew(size);
if (!h) {
return NULL;
}
return (MemPtr) MemHandleLock(h);
}

//------------------------------------
void free(MemPtr ptr) {
MemHandle h = MemPtrRecoverHandle(ptr);
if(!h) return;
MemHandleUnlock(h);
MemHandleFree(h);
ptr = NULL;
}

4. Put in two functions that will make it easy to set and get the App Defined Feature which will contain the pointers to the globals.
// ------------------------------------
UInt32 GetFtr(UInt16 ftrID){
UInt32 test=0;
Err e=FtrGet(DACREATOR, ftrID, &test);
if (e!=0){
FtrSet(DACREATOR, ftrID, 0);
test=0;
}
return test;
}

// ------------------------------------
void SetFtr(UInt16 ftrID, UInt32 val){
FtrSet(DACREATOR, ftrID, val);
}

5. Declare your global variable and place them in the Dynamic Heap. To use the Dynamic Heap is really cool. You can almost put as much as you like up there without affecting the stack which has a limited space already used by the app running when the DA is launched.
char *Buffer=malloc(32000);

6. Set the pointer as a feature value.
SetFtr(fBuffer, (UInt32)Buffer);

7. To access the global variable in your functions, you need to get the pointer to it. That is done like this:
char *Buffer=GetFtr(fBuffer);
StrCopy(Buffer,"Hello!");

or even use it directly as in this example:
StrCopy((char *)GetFtr(fBuffer),"Hello!");

8. When quitting the DA, you need to free the global variable. Don’t forget it! It’s more important for a DA than for normal app. Quitting a normal app releases the variables but quitting a DA does not.
free((char *)GetFtr(fBuffer));

That’s it. It’s easy, fast, powerful, and safe. It also works with structures, so you can easily have your DAappPrefs available in all functions. If you want to see how it works in a real DA, have a look at the thumbboardDA code.

August 13th, 2007

C gotchas for free: CERT C Programming Language Secure Coding Standard

While googling for something more-less unrelated, I stumbled upon this link which really is worth its price in gold:
https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Programming+Language+Secure+Coding+Standard

To cut a long story short, the CERT has posted a list of common C gotchas there. No, not the kind of gotchas you can find in a beginner’s book…but real gotchas from everyday development/porting work.

Take a look by all means…and plucker it if you feel like it!

July 15th, 2007

Implementing background music for Palm OS games

Since the release of the Palm Tungsten T, Palm Inc handhelds have the capability to play back WAV files(aka sampled sound). I have recently implemented such a sound routine and found an interesting twist(due to MemGluePtrNew not working)…and felt like sharing it with you!

Essentially, sampled sound works by repeatedly calling a function and requesting that it outs wave data into a buffer, from where it is then played. The main problem here is that the callback must execute quickly and should not loose any data(frame skipping). “Wrapping around” the end of a RAM buffer can be tedious both code and performance-wise, but the Palm OS has a little-sed but very useful feature called a file stream.

The function below is called to start the music:

void startBGM()
{
//Check if data really is UINT8
MemHandle r0,r1,r2,r3;
void *me;

//Make buffer
r0=DmGetResource(wavRsrcType,1000);
r1=DmGetResource(wavRsrcType,1001);
r2=DmGetResource(wavRsrcType,1002);
r3=DmGetResource(wavRsrcType,1003);
sounddata.stream=FileOpen(0,BGM_STREAM_NAME,NULL,NULL,fileModeReadWrite|fileModeTemporary,NULL);

//Write to buffer
me=MemHandleLock(r0);
FileWrite(sounddata.stream,me,MemHandleSize(r0),1,NULL);
MemHandleUnlock(r0);
me=MemHandleLock(r1);
FileWrite(sounddata.stream,me,MemHandleSize(r1),1,NULL);
MemHandleUnlock(r1);
me=MemHandleLock(r2);
FileWrite(sounddata.stream,me,MemHandleSize(r2),1,NULL);
MemHandleUnlock(r2);
me=MemHandleLock(r3);
FileWrite(sounddata.stream,me,MemHandleSize(r3),1,NULL);
MemHandleUnlock(r3);

FileFlush(sounddata.stream);
FileRewind(sounddata.stream);

DmReleaseResource(r0);
DmReleaseResource(r1);
DmReleaseResource(r2);
DmReleaseResource(r3);

//Start stream
SndStreamCreate (&stream,sndOutput,BGM_SAMPLERATE,sndUInt8,sndMono,SndStreamBufferCallbackFunc,&sounddata,BGM_BUFFERSIZE_FRAMES,false);
SndStreamStart(stream);
}

Essentially, it creates a new file stream, opens each of the “bits” of sound in the application database, and puts it all together into the file stream. It then creates a new stream and starts it. BTW, FileWrite’s documentation in PODS is wrong…but more on that later.

The music gets ended by this call:

void stopBGM()
{
SndStreamStop(stream);
SndStreamDelete(stream);
//Clean up buffer
FileClose(sounddata.stream);
}

This first stops and deletes the stream, and afterwards cleans up the buffer.

Last but not least, here’s the callback and the global data struct:

typedef struct{
//Contains all data that the sound stream callback needs
UInt32 framesdone;//aka where to start copying
FileHand stream;
}sounddatat;

static Err SndStreamBufferCallbackFunc (void *userDataP, SndStreamRef stream, void *bufferP, UInt32 frameCount)
{//NO GLOBALS!!!!
//Write data from buffer
UInt32 err;
sounddatat *sounddata=userDataP;
err=FileRead(sounddata->stream,bufferP,1,frameCount,NULL);
if(err!=frameCount)
{
FileRewind(sounddata->stream);
FileRead(sounddata->stream,bufferP+err,1,frameCount-err,NULL);
}
}

The sounddatat type gets passed to the callback each time the sound manager needs data. It contains all information needed to generate the next block of data. The err!= filecount bit of code is used to determine if we “ran over the end” of the file stream…if we did, the stream is rewinded and reading commences once again from the beginning to fill the buffer up completely.

What do you think?

May 31st, 2007

OnBoardC and the glue library - changing control attributes

Getting the glue library to work together decently with PODS is pretty easy. However, users of the OnBoardC suite were out of luck so far(and still are AFAIK).

However, OnBoardC users can need glue calls, too - and a bit of tinkering and searching brought along a simple concept for creating “replacement functions” for many of the glue calls that change specific object properties like the used font. The method behind it is simple - create it using dynamic UI, and simply remove&recreate it whenever you need to.

The code below is a “replacement” for CtlGlueSetFont - I used it to create a font selector for FontBucket in a soon-to-come project!


static void createDynaCmdFont(FormPtr* pForm,FontID font, char* fName)
{
CtlNewControl(pForm,DynaCmdFont,selectorTriggerCtl,fName,30,85,0,0,font,2,true);
FrmDrawForm(*pForm);
}

OnBoardC coders, please speak up! How do you handle PalmOSGlue?

May 31st, 2007

pnoJpegLib and PODS - the tutorial - Part 2

Welcome to part 2 of the TamsPalm pnoJpegLib tutorial - in case you missed part 1, it is right here!

Step 3: include JPEG resources
pilrc users can include JPEG resources via the data keyword - for us PODS users, this is a bit more difficult. First, create a subdirectory in the /rsc folder of your project. Then, open AppResources.xrd and add a resource. Uncheck the Show only common resources checkbox, and create a resource of any of the ” types. A window will pop up - you can enter a custom creator ID and the target file there(via Windows Open File dialog - choose All Files and click the JPEG file).

The PODS will then bind the file(it must be smaller than 64k) into the PRC at compile time!

For all resource HTML junkies, here is a sample of the resulting code. The HTML delimeters were replaced with () to make the post compatible with WordPress:

(RAW_RESOURCE RESOURCE_ID="1010")
(RES_TYPE) 'tmgn' (/RES_TYPE)
(DATA_FILE) "./jpegs/lvl10.jpg" (/DATA_FILE)
(/RAW_RESOURCE)

Step 4: move JPEG data to a PalmOS bitmap
Now that the raw JPEG data is waiting in a resource, its time to decompress it. This code shows how to do it - the work happens in the read call:

//Prepare JPG lib
BitmapPtr jpgData=NULL;
BitmapPtrV3 jpgV3;
if(jpgenable)
{
pnoJpeg2LoadFromHandle(jpgrefnum,jpgp,h);
pnoJpeg2SetGrayscale(jpgrefnum,jpgp,false);
pnoJpeg2SetScaleFactor(jpgrefnum,jpgp,1);
pnoJpeg2Read(jpgrefnum,jpgp,&jpgData);
pnoJpeg2Bmp2DoubleDensity(jpgrefnum,jpgData,&jpgV3); //For HiRes only

}

h is a handle to a resource which can easily be obtained with DmGetResource - don’t forget to free it after use. The Bmp2DoubleDensity code is needed only on HiRes handhelds - leaving it out/drawing the jpegData bitmap creates weird results. The pointer can then be reused with a different resource or can be left in memory for reuse when you need to decompress the image once again.

On my Treo 680, decompressing a small 320×320 image takes next to no time - excessive buffering probably wont pay out here. Also, your monitor’s display is no assessment of quality for setting the correct compression factor - use your handheld’s screen and an application like RescoViewer.

Step 5: draw the bitmap
Now, we’re basically done. You have your (V3) bitmap - so do what you want with it!

The steps outlined above took me quite some time to figure out - feel free to benefit from my experiences! If you have any comments, just post them here. Commenting on TamsPalm is free and anonymous!

May 29th, 2007

pnoJpegLib and PODS - the tutorial - Part 1

Decompressing JPEG images on Palm OS handhelds is easy if you are a user - just get RescoViewer. Developers who want to benefit from JPEG compression(great for backgrounds in games,…) on the other hand need to fight pnoJpegLib. I now have a program working - here’s what I did:

Step 1: make pnoJpegLib compile
After downloading the library from its homepage and including it into your PODS project(move both into the projects path and refresh the project by right-clicking onto the file tree list and clicking refresh), include the header file into all files that need to access the pnoJpegLib. I use the code below, the library resides in a subdirectory:

#include "pnojpeglib/pnoJpeg.h"

Then, open pnoJpeg.c and pnoJpeg.h and remove the inline statements to make the function definitions look like this:

Err pnoJpeg_OpenLibrary(UInt16 *refNumP)

After that, the project should compile. In case it still doesn’t, my files will be at the bottom of the second part of this article!

Step 2: prepare pnoJpegLib
Now, in the app opening code, include the following:

if((err=pnoJpeg_OpenLibrary(&jpgrefnum))!=errNone)
{//die
FrmCustomAlert(AltNotification,"JPEG library not found. Please install it from the distribution file!\n","Background images disbled!","");
jpgenable=false;
return;
}
//Create JPEG ref
jpgenable=true;
pnoJpeg2Create(jpgrefnum,&jpgp);

jpgenable is a Boolean value that lets you determine if the library is installed onto the Palm OS device where your app currently runs. jpgrefnum is a global UInt16, and jpgp is a global pnoJpeg2Ptr.
!!!There is NO NEED to allocate memory - the library handles this on its own. All you need to do is define the pointer!!!

Closing the library is easy, too - use the code below:

if(jpgenable)
{
pnoJpeg2Free(jpgrefnum,&jpgp);
pnoJpeg_CloseLibrary(jpgrefnum);
}

pnoJpeg2Free must be used once for each pointer you define. You can have multiple pointers in your app. Such a “pointer” essentially stores source and conversion information about a jpeg image and can be passed to the reader in order to generate bitmap data!

Congratulations - we now have pnoJpegLibrary ready to convert images. The second part of this article will look at adding jpeg files to your project and drawing them…tune in soon!

February 27th, 2007

Creating Multi-Segment applications with PODS

Palm OS has a nasty little “habit” of forcing code resources to have a defined maximum size - if that size gets exceeded, the code needs to be “swapped out” into another resource(called segmenting). Creating such multi-segment applications in projects that have Managed Make enabled is difficult - but a reader sent me this tutorial some time ago(which works really well):

In case you need it, here is a copy of my notes on going multisegmented
(including some quoted comments from other list subscribers and things
I found on the net — thanks guys, and sorry I didn’t include credits).
My comments are in square brackets.

================== Multisection/Multisegmented Applications =======

1 - Create a “Managed Make 68 C/C++ Project” (only managed project works
with me)
2 - Create a file named “Sections.def” in the root of your project
3 - In the top of “AppMain.c” or equivalent, include the file “Section.h”
4 - Now, edit the file “Sections.def” and “Sections.h” to define what
sections your project will have.

Sample: “Sections.def”
=======================
application { “_temp_” TEMP }
multiple code { “code1″ “code2″ }
=======================
[You must have at least one segment in the 'multiple code' definition.
The names must match those in Sections.h. Try to minimize the number
of sections you define and use, while making sure none of them grow
too big. In place of "_temp_", use your application's name. In place
of "TEMP", use your Creator ID.]

Sample: “Sections.h”
=======================
#ifndef _SECTIONS_H
#define _SECTIONS_H
#define EXTRA_SECTION_ONE __attribute__ ((section
(”code1″)))
#define EXTRA_SECTION_TWO __attribute__ ((section
(”code2″)))
#endif
=======================
[The names (here code1 and code2) can be whatever you want, but must
match those in Sections.def. You can use whatever you want as the
symbol defined. Here, it's EXTRA_SECTION_*, but could be anything.
You will use it again in #5, just below.]

5 - On the function definition specify what section will be used, the non
specified functions will be redirect to default section code.
[Try to group functions together to minimize the jumps between sections.
Be careful not to miss any, because they will default to your first
section, and possibly make it too big.]
Sample:
=======================
// [Here's where the compiler learns where to put the function:]
static void myfunc() EXTRA_SECTION_ONE;
// [Remember to add the macro every time you add a new function to your
// application!]

static void myfunc() {
// `the code`
}
=======================
If your project have a section defined and don’t use it anywhere, you got a
error. So, you need use the sections defined one time at least, or don’t
define it.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

For a managed project, in your project properties, you need to go to the
build panel and choose the prc-tools-68k-compiler->Symbols section and
add a line:

MULTISECTION_BUILD=true

to make the managed project look for your .def file. If you do everything else
in the prior posting it should then work. (The stock Sections.h file said to use
MULTIPLE_CODE_SECTIONS, but that didn’t work. I found the definition above
by looking at the generated objects.mk file.)
[I tried this and it worked; I didn't try MULTIPLE_CODE_SECTIONS - JT]

NB It also seems to require that some function be in each section or it will
complain about the section not existing at link time.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[Also, it might help after adding the files to the project, right click
on the project's name in the Navigation window and select Refresh,
before building the project.]

Jay Ts

Thank you very much for sending this in(a few months ago…whew, some things take a LOOONG time). All I can add is that you should clean the project whenever you get ld issues at compile time - there seems to be some kind of weird segmenting cache somewhere in PODS!

January 4th, 2007

HiRes+, DIA and PenInputManager.h for OnBoardC

Creating DIA aware applications(applications that can compact the Grafitti area on handhelds like the Palm Tungsten T3) with OnBoardC has been a difficult task for beginners, as OnBoardC’s header lacks the necessary support information for PenInputManager.h.

I created an OnBoardC-Compatible version of PenInputManager.h that just needs to be installed into the Palm handheld’s RAM and needs to be included like this:

#include "PenInputManager.h"

Download the header here.