My CodeWarrior Journal

By Darrin Massena (darrin@massena.com)
27 May 97

27 May 97
Well I finally got with it and placed my order for the Metrowerks CodeWarrior for PalmPilot DR2 and PalmPilot Professional bundle today. Cost $549 + $25 shipping & handling. The woman who took my order was nice, knew what the bundle was all about and told me I should expect it by the end of the week (5 days max). The claim is that the DR2 package includes everything I need to create Pilot applications on my Windows NT 4.0 workstation -- I can't wait!

28 May 97
Not here yet. Waiting.

29 May 97
Still not here. More waiting. It's raining outside.

30 May 97
After work, what's this on my doorstep? A delivery from Metrowerks! Happiness in a box! Expectations are high now that I finally have some professional development tools for my Pilot. It's already late but I can't resist a quick installation and some tinkering to get a feel for the development environment.

I open the box to find two more boxes inside: the CodeWarrior for PalmPilot DR2 box and a shrink-wrapped PalmPilot Professional. I already have a PalmPilot Pro but I went for the bundle figuring I could sell the extra Pilot for more than the $180 difference in price. Good thing it's shrink wrapped.

Installing
Inside the CodeWarrior box is a CD-ROM, a thin (32 page) "QuickStart" manual, some advertising, the registration card, and a fair amount of air. Not being one to waste time with manuals I pop the CD into my drive. Autoplay takes over and the CodeWarrior installation program automatically starts. I select a custom installation so I can see what all the options are. It lists the components, how much space they'll consume on my disk, and lets me choose which ones I want installed. I turn on everything and the total is just under 30 megs, not too bad.

Dorking around
Installation goes quick and I immediately dive into the CodeWarrior IDE. Hmm... just a menubar and a row of icons at the top of my screen. I can see this is going to be a bit different from my current favorite IDE (Microsoft's Visual Studio). I hold my mouse pointer over some of the toolbar icons for awhile, hoping for some tool tips to give me a clue what they're for. No luck. Checking out the menus I find "Open..." and browse around until I find some Examples under the PalmPilot SDK directory of the installation. Let's try to build HardBall.

I double-click on HardBall.mcp and in loads the project. I see lots of flashing and extra painting which does not inspire confidence and the Macintosh System 7 look of the project window (I guess that's what it is, it's not labeled) contents is foreign and unsettling. Maybe I'll get used to it but my first feeling is that Windows applications should behave like other Windows applications (and, on a Mac, Macintosh applications should behave like other Macintosh applications). I discover that by clicking on the little triangle next to AppSources I can expand a list of the HardBall sources (StartupCode.lib and HardBall.c). Clicking and double-clicking on StartupCode.lib gets me nothing but on HardBall.c brings up a source code editing window with HardBall.c in it.

Building
I want to build HardBall.c so I try one of the icons that seems like it might be the right one. It isn't and I get tons of compile errors: "Can't find header file XXX", "Can't precompile file YYY". I find a menu item "make" -- sounds good! A build status window pops up and whizzes through the make before I can even see what's happening. No errors, everything looks swell. On a program this size (HardBall.c is 3600 lines of code) building is fast! For reference, I'm running on a Dell Dimension XPS Pro200n Pentium Pro w/ 96 megs of RAM and Windows NT 4.0. I grovel around my hard disk and find the resultant HardBall.PRC file is 17,800 bytes. I remember the released HardBall.prc being smaller than that so I guess some debug options are enabled for this build. I grovel around for awhile and can't find them. Tomorrow I'll start out right, read some of the documentation, and begin a new project.

Constructor First Look
But first a quick peek at the Constructor. The Constructor is a graphical tool for visually constructing the user interface for your Pilot application. This means building menus, laying out forms, creating icons, etc. Such a tool has been sorely lacking from both the Macintosh and Windows development tool sets to date and I must say it's about time! I am a bit nervous, however, as I've already seen a number of postings from users of Constructor complaining about its bugginess and instability.

Constructor is a separate application from the CodeWarrior IDE and not integrated in any of the cool ways I would like it to be. For example, I cannot double-click on a resource inside of the IDE to launch Constructor to edit the resource. I can't find any sample Constructor projects (.plr) on my installation but it also opens .rsr files of which HardBall has a number. Even though I already have HardBall open in the IDE I have to go through a separate browsing process to open one of HardBall's resources in the Constructor.

After opening HardBallBoard.rsr I try resizing the window displaying its contents. I can resize vertically but not horizontally and after dragging the window around a bit it gets in to some sort of wacky mode where it is constantly repainting over and over (flash, flash, flash) and I can't drag it back onto the screen. I use NT's Task Manager to terminate the Constructor process (whew, I was about to go into seizures) and relaunch it to try again. Upon reloading I check Constructor's About dialog for Alpha disclaimers but find none. "Version 1.0" it says. I wonder how much time Constructor spent in internal testing.

This time around I decide to leave the resource window at its original size and placement. I click around a bit, expanding some items and collapsing others. Somehow I get into infinite repaint mode again but manage to break out by double-clicking one of the form icons which brings up a second window which shows the properties and a preview of the form. I try moving this window because it is covering the other window and I'm only able to move it about a third of the way across the screen. What are they doing? Why can't I move the windows? Argh.

The form preview is a bit screwed up. The font isn't the right size so the text of the application title and score string is clipped. Control id numbers partially cover each control (I find a way to turn this off). I can already see that I'm not going to get the 100% WYSIWYG preview I was hoping for. I switch to another application and when I switch back the preview window doesn't even repaint and goes into flashing mode again. It is depressing to run into so many severe bugs sitting right on the surface. From experience I know it will only get worse as I dive deeper. Enough for tonight.

31 May 97
Today I'll start out by reading the release notes that came with CodeWarrior. Perhaps they'll save me some pain.

Release Notes
Starting with the Constructor for PalmPilot Notes I learn that this version of Constructor (1.0a8) is an alpha release (surprise!). I also learn that the DR2 SDK is not the same as the forthcoming 2.0 SDK release (due this summer) which I will receive as a free update. Another item of interest is that this version of Constructor runs more reliably on Windows NT 4 than on Windows 95. If so, I can only pity anyone trying to make use of it on Win95. All the constructor problems I've seen so far (and many more) are reported as "Known Bugs".

The 68k Tools (C compiler, assembler, linker, etc) notes claim no known bugs (yay!). A bunch of annoying bugs are listed, mostly UI problems.

The PilotDebugger notes mention a few problems but no show stoppers. If it reliably works for source-level cross-debugging on the Pilot device itself (or Copilot, as I've seen posted) then it'll be a huge debugging improvement.

The V2 IDE Notes refer to this version of the Windows IDE as a beta release. Several bugs are mentioned, mostly annoying UI problems.

Documentation
All the documentation is in Adobe Acrobat (.PDF) format. On one hand this is cool. Acrobat files are searchable and look great when printed. On the other hand, why should I be responsible for printing the manual? Isn't $369 enough to include a manual? I remember the good old days when I opened the box of a new development tool and found a manual instead of air. In my opinion, Acrobat files are a pain as online documentation. They break up the document into pages, waste screen space on redundant margins, headers and footers for each page, and give you the choice of reading the text with crisp-but-crappily-spaced fonts or anti-aliased-and-fuzzy fonts. Oh yeah, and it's slow.

Enough of that. I begin reading the document "CodeWarrior Targeting Palm OS". This seems like the most direct way to get into using CodeWarrior to write Pilot software while getting enough training to be able to use the CodeWarrior IDE and other tools. Before long I encounter the disappointing note "This chapter currently only describes Palm OS application development using CodeWarrior tools for the Mac OS. Future versions of this chapter will also cover Palm OS software development on Windows 95/NT". I find numerous mentions of the Pilot Simulator which only runs on the Mac -- no problem, Copilot is better.

I decide to follow along with the tutorial in the "Targeting Palm OS" document. First it says, "Make a duplicate of the MemoPad 20 folder". OK, just one problem: there is no MemoPad 20 folder anywhere in my installation. Hey, I'm flexible. I make a copy of Memo instead (one of the PalmPilot SDK Examples). After this the tutorial kind of trails off and doesn't walk me through actually doing anything with the copied project. Then it starts a new tutorial that walks me through creating a project from scratch. I ditch my Memo copy and start over.

PilotHack 2.0
For my first CodeWarrior project I plan to port the very first Pilot program I wrote, PilotHack, to the new toolset. Then I'll upgrade it to support the newer PalmPilots and maybe add some enhancements. When I wrote PilotHack, almost exactly one year ago, there were no publicly available Pilot development tools and no documentation so I had to build my own as I went. I thoroughly enjoyed the challenge but hopefully things will be a bit easier this time around!

1 Jun 97
Bad news! In preparation for remote debugging my new project I have discovered that neither of my PC's serial ports are working! I can't remote debug, hotsync, or even communicate using a terminal program and a serial link between this PC and another. I'll have to get someone out to service the machine. Major stumbling block.

7 Jun 97
My serial ports are still busted. Good thing I have two computers! Today I reinstall CodeWarrior on the other machine, a Dell Dimension XPS M200s (Pentium MMX) with working serial ports. Now maybe we can make some progress.

Before going nuts on my own project I first want to make sure everything is working right. I've built the example Hardball project so I should be able to debug it.

Let's Try The Debugger
I launch the CodeWarrior Debugger (why is it separate from CodeWarrior IDE? why is the Constructor separate from the IDE?) and open Hardball.prc.psym (one of the side-effects of building the Hardball project). The debugger asks me to enter "shortcut . 2" on the Pilot and press OK, which I do, and it automatically starts downloading Hardball.prc to my Pilot. After the download completes (a few seconds) all sorts of debugger windows pop up.

One window contains a browser that lets me examine all the functions and variables of the project in source, assembly, or mixed form. I can easily examine the contents of global variables, including nested structures. Another window shows me the current line the debugger is halted on, a stack backtrace, and the local variables of the function currently being executed (PilotMain). A third window shows a log of text apparently sent by the Pilot to the debugger including a welcome string and some process creation information.

Using menu commands instead of the cryptic icons (where are the tooltips!?) I step across a couple of functions and see that everything is working swell so I hit the button that looks like 'go'. The debugger now says "Program "Hardball.prc" is executing". Great! Let's set a breakpoint for the next time the score is advanced. Hmm... I can't figure out how to set a breakpoint. Nothing on the menus and none of the icons look right. Time to try the online help.

The online help is pretty good and I learn that I cannot set breakpoints while the program is running (bummer). So, I should stop the program and then set my breakpoint. Unfortunately, the stop button and menu items are greyed out! Some text in the debugger window explains I must enter a special shortcut on the Pilot in order to stop execution. It works! After stopping the backtrace shows me deep inside the EventLoop in the Pilot API SysHandleEvent. This is cool! I set a breakpoint at IncreaseScore, hit 'go', play the game until I knock out a brick and the debugger stops execution at my breakpoint!

Sorry for all the exclaimation points but until now the Pilot debugging situation, especially on PCs, has been in the dark ages. Mac users have had the Pilot Simulator to debug under but as an imperfect simulator it can still leave you high-and-dry with a program that works great under the Simulator but crashes on the Pilot itself. PC users have been using the Copilot Pilot Emulator which is a supreme emulator but has limited debugging features, e.g., no source-level debugging.

When I exit the debugger it resets my Pilot but leaves the downloaded Hardball in memory so I can play it again and again.

16 Jun 97
It should be a trivial task to create a new CodeWarrior project, add a little Pilot code, a couple resources (e.g., form, icon, menu) and get it compiling on the PC, then executing on the Pilot. In fact, one would expect step-by-step instructions to do just this would be included with the CodeWarrior for PalmPilot package. Bzzzt! Wrong. I took a quick stab at doing this earlier in the week and wasn't able to get past some undocumented build errors. So today I'm going to try to strip down one of the Pilot SDK "Example" applications to a minimal Pilot application then see if I can make a copy of it and use that as a template for my own project. If that works I'll have worked up the courage to create my own minimal application from scratch again with the hope that I'll be able to figure out anything that doesn't work by comparing my from-scratch application with the stripped-down example application.

Stripping SubHunt
Which example should I strip down? There are six examples to choose from: Address, DateBook, HardBall, Memo, SubHunt, and ToDo. I want to steer clear of the applications that have the same creator types as the built-in Pilot applications to avoid any possible conflicts. Yeah, I'm sure this has been tested and all but I'm not going looking for trouble. That takes Address, DateBook, Memo, and ToDo out of the running and since I've already played with HardBall I think I'll move on to SubHunt.

I copy the PalmPilot SDK\Examples\SubHunt directory to the PalmPilot SDK\Apps directory and double-click Apps\SubHunt\SubHunt.mcp. Better make sure it works as-is before I start making any changes. I 'Make' (using the menu item Project...Make) my SubHunt copy. No problem, it creates a 17,422 byte .PRC file. I use instapp and hotsync it on the Pilot. I launch it and start laying down mines like crazy. "Subs cleared: 100%" -- alright! Now let's make sure the debugger works as I think it should.

I use the Memory application and delete SubHunt from my Pilot. CodeWarrior has an item under the File menu that says "Switch to MW Debugger" but it is grayed out. Bummer. I launch the CodeWarrior Debugger by hand, track down my project directory again and select the SubHunt.prc.sym file for debugging (as recommended by the debugger documentation). I put the Pilot in Console Mode (shortcut .. 2). While I'm trying to do this a "Your battery is low" message comes up. After acknowledging it I hit OK on the debugger's "put the Pilot in Console Mode and hit OK" dialog but now (very quickly) it says "Failed to connect to remote". Try again. Still fails. A light bulb flashes over my head as I realize I still have the hotsync application running! Conflicting serial ports no doubt. I close hotsync and try again -- "Transfering..." this time. The debugger could have saved me some angst by reporting the actual cause of the problem "serial port in use".

So now I'm in the debugger, halted at the first line of SubHunt's PilotMain. Looking good. I step through a few lines of code, then hit the 'run' icon. Everything is groovy. I close the debugger and my Pilot resets.

Time to start stripping things down. My number one rule when doing this sort of thing is to make a copy of whatever you have at each point of stability (as determined by an appropriately robust testing session). If I go too far I'll have something to back up to.

SubHunt is a 3,911 line program. The minimal Pilot application should be couple dozen lines of code. Everything must go! While editing the program I notice a few annoying things about the CodeWarrior IDE's editor. The worst of these is that my page-up and page-down keys have no effect! After some poking about I discover (Edit...Preferences...General...Key Bindings) that I can bind keys to whatever command I want -- hey, how about binding page-up/down to the page-up/down command?! I rebind page-up/down to the commands "Scroll page up/down" but this doesn't work the way I want. The page scrolls as I expect but the input cursor doesn't follow. As soon as I move the input cursor by using the arrow keys or typing, the editor warps back to where the cursor was before I paged up/down. No good. I try rebinding to the command "Move to top/bottom of page". This moves the cursor but not where I want it. Pressing page-down the first time moves the cursor from wherever it is to the bottom of the page. Pressing page-down again then scrolls down one page, moving the cursor with. No other commands seem appropriate. [sound of teeth gnashing]

What is the problem? It is not a big mystery how page-up/down should be handled within a text editor. Every Windows application I've ever used has handled these keys the same way. I hope Metrowerks fixes this non-standard behavior before it drives me insane.

Anyway, I rewrite SubHunt.c as a 63-line minimal Pilot application. The resulting PRC file is 5,125 bytes long (way too big, hopefully full of debug or other stuff I can disable later). Here's the code at this point:

#include <Pilot.h>
#include "SubHuntRsc.h"

DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
{
	EventType evt;
	Word err;

	if (cmd != sysAppLaunchCmdNormalLaunch)
		return 0;

	FrmGotoForm(BoardView);

	do {
		extern Boolean ApplicationHandleEvent(const EventType *pevt);
		extern Boolean MainFormHandleEvent(const EventType *pevt);

		EvtGetEvent(&evt, evtWaitForever);

		if (!SysHandleEvent(&evt)) {
			if (!MenuHandleEvent(NULL, &evt, &err)) {
				if (!ApplicationHandleEvent(&evt)) {
					FrmDispatchEvent(&evt);
				}
			}
		}
	} while (evt.eType != appStopEvent);

	return 0;
}

Boolean ApplicationHandleEvent(const EventType *pevt)
{
	extern Boolean MainFormHandleEvent(const EventType *pevt);
	FormPtr pfrm;

	if (pevt->eType == frmLoadEvent) {

		Word fid = pevt->data.frmLoad.formID;
		pfrm = FrmInitForm(fid);

		FrmSetActiveForm(pfrm);
		FrmSetEventHandler(pfrm, (FormEventHandlerPtr)&MainFormHandleEvent);
		return true;
	}

	return false;
}

Boolean MainFormHandleEvent(const EventType *pevt)
{
	switch (pevt->eType) {
	case frmOpenEvent:
		{
			FormPtr pfrm = FrmGetActiveForm();
			FrmDrawForm(pfrm);
		}
		return true;
	}

	return false;
}

It runs and I verify that the debugger still works with it. So far so good, time to make another backup.

More SubHunt Stripping
Looking at the SubHunt directory I see several more candidates for stripping. The first to go is a file named SubHunt.h. SubHunt.h is not included by any of the other SubHunt project files and only contains duplicate definitions of constants also contained in SubHuntRsc.h. How did it end up in the distrubution? I delete it.

Another file SubHuntRsc.c doesn't appear to be used anywhere in the project. Looking at its contents I think maybe it is meant for use when building for the Macintosh Pilot Simulator. What the heck, I delete it too. I start to think that maybe I'm getting carried away and should get to know what's going on with the non-code parts of the project before going much further. The remaining significant portions of the project are Resources.

Logically, the tool to use to strip unused resources from my project should be the Constructor. Constructor isn't integrated into the IDE and doesn't know anything about the current project I'm working on so I have to track it down. Constructor defaults to loading *.plr (Pilot Resource File) files but there isn't one in SubHunt so I switch to *.rsr and search around to find my resources. This is trickier than it sounds. You tell me, which directory contains the files I want to edit? Is it SubHunt\Rsc? SubHunt\Resource.frk? or SubHunt\Rsc\Resource.frk? I first find five .rsr files (SubHuntMain.rsr, SubHuntMisc.rsr, etc) in the SubHunt\Rsc directory. Trouble is, they're all zero bytes in size! SubHunt\Rsc\Resource.frk contains files with the same name but with reasonable sizes so I open SubHunt\Src\Resource.frk\SubHuntMain.rsr with Constructor.

At this point I have all sorts of nasty problems with Constructor. I try to move one of its windows because it is overlapping its own menu window and then the Constructor stops responding to any input. I'm forced to terminate Constructor with NT's Task Manager. I could go on and on about the Constructor bugs I've encountered but Metrowerks representatives have been emphasizing that this is an ALPHA release (oh, I feel MUCH better now) and a useful version is coming soon. I will mention work-arounds to various Constructor problems if I come up with any deterministic ones.

SubHuntMisc.rsr is the biggest .rsr file (5,129 bytes) and after I manage to open it with Constructor I can see why. It contains 20 bitmaps of little ships, subs, mines, torpedoes, etc as well as a few strings and menus. Although the Constructor UI is a bit weird, I manage to delete the bitmaps and strings but keep the menus for now.

I don't need three of the resource files at all (SubHuntHighScores.rsr, SubHuntInfo.rsr, SubHuntNewHighScore.rsr) and remove them from my project via the CodeWarrior IDE. Oops! I accidentally removed SubHuntMisc.rsr as well. No problem, I'll just add it back (it's just deleted from the project, not from my hard disk). I use Project...Add Files to add the Rsc\Resource.frk\SubHuntMisc.rsr (the non-zero-length version of SubHuntMisc) back into my project and then rebuild to verify that everything is cool again. It isn't! "Link Error : Error while creating/copying resource fork. Directory not found", "Link Error : Error while saving resources" (followed by some glyphs my keyboard will not allow me to reproduce) and as if that weren't enough "Error : Could not find file 'SubHunt.tmp' in search paths"! Whoa, looks like I did something wrong. The only clue these error messages give me is that the problem has something to do with the resource files I was just messing with (surprise). Wouldn't it be crazy if I was supposed to add the weird zero-length file to my project instead of the one that actually has the resource data in it? I can't think of anything else so I try it and rebuild. Incredibly, that fixes the problems.

After the strip job I have a 1,119-byte SubHunt.prc which includes the main form, menu, and icon resources.

17 Jun 97 - SubHunt Becomes Template
Now it gets more interesting. Can I remove the remaining vestiges of SubHunt to create a template application to use as a basis for future projects? Let's give it a try.

First thing is to rename the directory the SubHunt project is in from SubHunt to Template. After closing the CodeWarrior IDE I attempt to rename the directory and get the error "Cannot rename SubHunt: There has been a sharing violation. The source or destination file may be in use". Hey, I closed the IDE and closed Constructor a long time ago. I delve deeper with the NT Task Manager and discover a process suspiciously named "Constructor for" is lying around, invisible and constantly sucking up CPU cycles! Die rogue process! After killing it I can rename the directory.

I also rename the project file from SubHunt.mcp to Template.mcp and open it up. A-OK. I remove all files of the project prefixed with the name SubHunt, reprefix them with Template, and add them back in. I update Template.c to include TemplateRsc.h rather than SubHuntRsc.h. At his point I decide to do away completely with the file SubHunt.r. I see no evidence of it being used on Windows.

All the input files are named properly and the project still builds correctly so it's time to change the project settings so the output files will be named appropriately (I want Template.prc, not SubHunt.prc). I bring up the project Settings and change every SubHunt prefixed name. The first is the Target Settings, Target Name (from "Subhunt (.prc for device)"). Then 68K Target, File Name (from "SubHunt.tmp"). Then PilotRez, Mac Resource Files (from "SubHunt.tmp") and PilotRez, Output File (from "SubHunt.prc"). While I'm there I change the Creator ID to "TMPL". That's it! And it still builds.

Now let's see if I can tweak the resources a bit to 'templatize' them. The first thing I ask myself is, since a resource file can hold as many resources of as many different resources types as I like, why not keep all my resources in a single file? This should just mean moving the single Form resource from TemplateMain.rsr into the TemplateMisc.rsr file. After wrestling with the usual Constructor hellishness, I finally manage to open both .rsr files and simply drag the Form resource from the one file to the other. Easy as pie if it weren't for the bugs.

I try to edit the application icon to suit my Template better only to discover that the quality of the Constructor's icon editor is sadly consistent with the rest of Constructor. I can only set pixels, not clear them! The color and pattern-changing drop-downs don't work. Several of the tools are inactive. The window sometimes goes into a modal unresponsive state until I alt-tab away to another application and back. I cut my losses, save my mangled icon, and move on.

The TemplateMisc.rsr file has some project settings, including the "Application Icon Name" which I rename from SubHunt to Template. Now that I only have one resource file I rename it from TemplateMisc.rsr to Template.rsr. Things are moving right along.

22 Jun 97
Today I decided to take a look at the Template program under the CodeWarrior Debugger. Debugger downloaded the program but showed me a machine-code disassembly, not my source code. Oh well, maybe I need to turn on some option to force debugging information to be generated (but it was working before...).

One note about the disassembly: CodeWarrior's debugger displays TRAP instructions and the special word that follows them incorrectly. For the uninitiated, TRAP instructions are used to call PalmOS APIs and the word which follows the TRAP instruction indicates which API to call. CodeWarrior Debugger attempts to place the name of the API next to the TRAP but either fails or displays a Macintosh API name! In contrast, Copilot's debugger shows the name of the appropriate Pilot API next to the TRAP. Without this labeling, it can be rather difficult to follow code that hasn't been specifically prepared for debugging, including the PalmOS APIs themselves.

Since I can't step through the code effectively (no source, no symbols) I just hit 'go' and off it runs. Everything looks like it should (just displays what's left of the SubHunt main form) so I close the CodeWarrior Debugger in preparation for another try. This is supposed to automatically reset the Pilot. The Pilot begins to reset but then locks up with the "Welcome to PalmPilot" screen displayed. Not good. I press the reset button on the back of my Pilot. It resets back to the same screen and locks up again!

A 'feature' of the PalmOS is that when it resets it calls each application on the Pilot so they can initialize themselves. But what if one of the programs is so hosed it can't even complete its initialization without crashing or hanging? Answer: reset doesn't complete and to recover the Pilot's memory has to be completely wiped. I take off the kid gloves and press the reset button while holding down the power button. Now I get the "Erase all data?" message and press the up/YES button.

What went wrong? Did the debugger's downloader somehow corrupt my program? To eliminate the possibility, I use Hotsync to reinstall Template.prc. This time during Hotsync a dialog pops up on the Pilot saying "Form.c, Line:1198, Object not in form". Hmm... I press the Reset button on the dialog (the only option) and Pilot locks up again at the welcome screen. I wipe its memory again.

Much like at reset time, the PalmOS calls each application during Hotsync. Apparently, when it gets to Template there is a problem. I don't happen to have the source code to the PalmPilot's ROM so there's no good way to know what Form.c, line 1198 is trying to do when it hits the problem.

Copilot To The Rescue
CodeWarrior's Debugger can only debug applications it downloaded, immediately after downloading them. So how do you debug an application after you've installed it on your Pilot, say, at the point it brings up a "Form.C, Line:1198, Object not in form" dialog? Or during its handling of the hotsync or find startup command? Answer: you turn to Copilot. One of the many great things about Copilot is that its debugger is set up to debug everything executing within its virtual machine.

So I download and set up the latest version of Copilot. I won't bore you with the details here, see Greg Hewgill's Copilot page. After running Copilot and loading Template.prc into it (a process even easier than hotsyncing to a real Pilot) I selected Copilot's Reset command to see if it would hang the same way my Pilot did. I does! Easy as pie, I break into the debugger and dump a stack backtrace ('k' command). It looks like this:

>k
FramePtr Parameters                              Address
0000f33a 0004 0000 db4a 10c5 93a0 0000 0000 0001 krnl.psys!cjkserror + $118
0000f344 0000 0000 0001 0000 0004 0000 1cdc 0000 rom.rom!SysDoze + $c
0000db4a 0000 dbaa 0000 0001 10c5 70e2 0000 f062 krnl.psys!cj_kpprivr + $426
0000dbb2 0000 f93e 0000 0001 0000 0001 0000 0000 krnl.psys!cjevwait + $f4
0000dbde 0000 dc0c 0000 dc0a 0000 dc07 0000 0001 rom.rom!EvtGetPen + $30
0000dc0e 0000 dc56 0000 0018 0000 0000 0000 0000 rom.rom!SelectButton + $2a
0000dc5e 0000 dc74 3331 3931 0000 0000 0000 4d65 rom.rom!SysFatalAlert + $222
0000dd74 10c0 c50a 0c77 10c0 c4fa 0000 0000 0000 rom.rom!ErrDisplayFileLineMsg + $90
0000dd9a 0000 0000 0000 ddc2 0000 0018 0000 0000 rom.rom!MemMove + $2c
0000ddb2 0000 ddc2 0000 0000 0017 0000 0000 0000 rom.rom!EvtAddEventToQueue + $56
0000ddda 03e8 0000 ddfa 10c5 6a60 0000 f9a6 0000 rom.rom!FrmGotoForm + $4a
0000ddfe 0000 0000 0000 0000 0000 0005 10c5 6744 appl.TMPL!PilotMain + $16
0000de3e 0000 000a 014f 0000 0005 0000 dec0 0000 rom.rom!SysAppLaunch + $30c
0000de92 0005 0000 dec0 0000 0000 0000 0006 0000 rom.rom!SysBroadcastActionCode + $5a
0000def8 0000 0000 0000 0087 0000 2600 0000 d592 rom.rom!PilotMain + $da
0000df18 0000 f062 0000 df30 7073 7973 5555 5555 rom.rom!__Startup__ + $60

Starting from the bottom of the trace we can see how the system has wound its way to where we've hung. Everything starts at the Pilot ROM's __Startup__ routine, which calls its own PilotMain (not my PilotMain, that comes later), which broadcasts an action code to all installed applications. Some research reveals that the reset-time broadcast is sysAppLaunchCmdSystemReset. Each application is launched via SysAppLaunch to receive this command code. At this point in the stack backtrace we notice something suspicious. My application's PilotMain is there but my __Startup__ should also be there, called first. It's not. Then we see FrmGotoForm being called even though Template explicitly checks the startup code and only calls FrmGotoForm if the code is sysAppLaunchCmdNormalLaunch. Following the trace further we can see a failure inside of FrmGotoForm (the call to ErrDisplayFileLineMsg is the clue) and some mysterious problem is keeping the error dialog from displaying, although it looks like it is waiting for input, hence the hang.

So why isn't my __Startup__ function being called? I disassemble __Startup__ and find it is in fact present, at location $100a0850. My PilotMain function is at $100a0734. I happen to know that when an application is launched, the first function in the code 0001 resource is called to begin execution. It looks like somehow my PilotMain has been ordered before __Startup__ and is being called first! This explanation fits all the facts. I use prc2bin.exe to extract the code 0001 resource and pildis.exe to disassemble it, verifying that PilotMain is now the first function in the resource and __Startup__ is the last! Question is, what controls this ordering and how did it get screwed up?

Let's go back to the CodeWarrior online help and see if there is some way to control the ordering of object files within the executable. It doesn't take long to find out that the Segments tab of the Project window gives me exactly this capability. By creating a new segment for my application and then ordering the object files within the segment I can control the exact ordering within the executable. It looks like with all the file adding and removing I've been doing to clean Template up, the Segment ordering has been randomized.

I create a new Segment called "Application Sources" to match my source code group and order the files within it: StartupCode.lib, Template.c, then Template.rsr. I rebuild the application and verify (again with prc2bin and pildis) that I have successfully reordered the code and __Startup__ is now first. I hotsync this latest Template.prc to my Pilot. Success! No hotsync errors and Template runs great. Whew! The Important Rule learned today is always create a Segment for your project and make sure StartupCode.lib is the first object in the segment.

A Word About Resources
A helpful reader sent me some mail clarifying some perplexing resource problems I wrote about in my Journal. He said, "you seem to be somewhat confused about the resource.frk. That whole mess is an artifact of having ported from the Macintosh. On the Mac, files have 2 parts, a data fork and a resource fork. Once upon a time, when you copied to the PC, the resource fork was simply lost, and so a file that only had a resource fork was suddenly a zero k file. Nowadays, the resource part of the file is copied into a special directory called resource.frk. Thus, you should think of the zero-k files as the "real" files and always refer to them (when you open, include, etc.). The files in the resource.frk may have all the actual data in them, but they are just the shadow files, and are as useless without their facades as the facades are without the meat behind them." My own experimentation bears this out.

Finishing Touches
The Template project will be complete if I can remove the remaining SubHunt-isms and clean up some things that have been bothering me about the resources. I hold my breath and launch Constructor.

After loading Template.rsr (the zero-lengthed one) I open the form named "-", change its Form Title to "Template" (from "SubHunt") and delete the label "Lvl" found in the upper-right corner. I rename the form to "Main".

Then I open the menu bar resource. I change the menu header "Game" to "Template", change one of the subitems to "blah blah", delete a couple I won't be using, and leave "About" alone. I rename the menu bar to "Main".

I open the "Menu" resource and am surprised to see the same thing I saw when I opened the "Menu Bar" resource. What the heck? Well, since it already has my changes, I leave the contents along and rename it to "Main" as well.

One thing that has been bothering me is that Constructor apparently has the ability to generate a header file that contains #define values for every resource ID. Strangely, SubHunt was using a separate header file that also defined these values. Ideally, one file would define the resource IDs and would be kept up to date by Constructor as the resource file was edited. I change the Constructor project setting "Header file name" from "Template-123934934.h" to "TemplateRsc.h" and save all my changes. Looking in the Template\Rsc directory I find the newly generated TemplateRsc.h, complete with #defines for all the resource IDs. Cool! Now all I have to do is get Template.h to include it. This is where things get a bit strange.

To accomplish this with any of the PC-hosted C compilers I've used in the past I would simply add the line #include "..\Rsc\TemplateRsc.h" to Template.c. When I tried this I hit a compiler error indicating CodeWarrior didn't know what I was talking about. The online documentation didn't provide me with any clues so I searched around in example files and eventually found one using an alien syntax that used colons to separate path elements. Following its example I changed my statement to #include ":Rsc:TemplateRsc.h" and it worked! I deleted the old TemplateRsc.h from the Src directory and changed the code to use the new constants (actually, only MainForm is in use so far).

Complete!
Hey, I think I'm done! I have succeeded in creating a minimal template application. It includes four files: a CodeWarrior project file, a single source code file, a resource file, and a resource header file which maps symbolic names to resource ids. The resource header file is automatically regenerated when the resource file is changed.

Several people have requested that I post my template application once it is complete so here you go. Click here to download Template.zip. Extract to a new directory under CodeWarrior's PalmPilot SDK\Apps directory (I humbly suggest you name the directory "Template"). Double-click on Template.mcp to load the project. Click the Make button and a PRC file will be built and deposited at the root of your new directory.

Next time I'll give step-by-step instructions for morphing Template into your own application but it'll mostly be a distillation of information I've provided above since the process is a subset of the steps I went through to convert SubHunt into Template in the first place.

20 Jul 97
You may have noticed I haven't updated my Journal for awhile. Given the high pain-to-fun ratio I was experiencing with CodeWarrior I decided to wait for the next update before spending any more time with it. Rumor has it that an update should be available within the next couple weeks. When I get it I'll tell you what I find.

Stay tuned for our next installment...


Back to Pilot Software Development