; Sample.asm ; ; This sample is meant to serve as a prototype for assembly language Pilot ; applications. It uses the standard startup code and implements a typical ; message loop that handles some common events. Several resources (e.g., ; menu, icon) are included, a few inline and others from external files ; generated by PilRC. ; ; NOTE: For clarity's sake this code is not highly optimized. ; ; NOTE: Where possible this sample uses PalmOS APIs to do conversion between ; integers and strings (hex and decimal). The Palm APIs have some interesting ; limitations. StrAToI accepts signed 16-bit ints. StrIToA accepts signed ; 32-bit ints. StrIToH accepts signed 32-bit ints. My implementation of htoi ; accepts unsigned 32-bit ints. The least common denominator for all these ; routines is a signed 16-bit int so I've placed that limit on the ; conversions. ; ; Formatted for 8-space tabs. Assemble with "pila sample.asm" after creating ; the resources with "pilrc sample.rcp ." ; ; By Darrin Massena ; 29 Jul 96 ; (updated 10 Sep 96) ; The 'Appl' directive sets the application's name and four character id. Appl "Sample App", 'samp' ; Pilot.inc contains PalmOS constants, structure offsets, and API trap codes. include "Pilot.inc" ; Startup.inc contains a standard startup function. This function must be ; the first within an application and is called by the PalmOS after the app ; is loaded. The startup function in Startup.inc (__Startup__) calls the ; application-defined function PilotMain. include "Startup.inc" ; Application-defined resource ids kidbAIB equ $7FFE kidrPREF equ 1 kidrTVER equ 1 kidrTAIB equ 1000 kidfMain equ 1000 kidmMain equ 1000 kidmAbout equ 1002 kidcConvert equ 1003 kidcDecimal equ 1004 kidcHex equ 1005 kidrAboutAlert equ 1000 kidrInputErrorAlert equ 1001 kidrRangeErrorAlert equ 1002 ; Some global variables (a5-relative) data global gpfldDecimal.l ;pointer to the Decimal field global gpfldHex.l ;pointer to the Hex field code ; --------------------------------------------------------------------------- ; DWord PilotMain(Word cmd, void *cmdPBP, Word launchflags) ; PilotMain is called by the startup code and implements a simple event ; handling loop. proc PilotMain(cmd.w, cmdPBP.l, launchFlags.w) local err.w local evt.EventType beginproc tst.w cmd(a6) ;sysAppLaunchCmdNormalLaunch is 0 bne PmReturn ;not a normal launch, bag out trap #8 ;break on startup for debugging systrap FrmGotoForm(#kidfMain.w) PmEventLoop ; Doze until an event arrives systrap EvtGetEvent(&evt(a6), #evtWaitForever.w) ; System gets first chance to handle the event systrap SysHandleEvent(&evt(a6)) tst.b d0 ;handled? bne.s PmEventDone ;yep ; Menu handler gets second chance to handle the event systrap MenuHandleEvent(&0, &evt(a6), &err(a6)) tst.b d0 ;handled? bne.s PmEventDone ;yep ; Application handler gets third chance to handle the event call ApplicationHandleEvent(&evt(a6)) tst.b d0 ;handled? bne.s PmEventDone ;yep ; Form handler gets fourth chance to handle the event call MainFormHandleEvent(&evt(a6)) tst.b d0 ;handled? bne.s PmEventDone ;yep ; Still not handled. We're not interested in it anymore so let the ; default form handler take it. systrap FrmGetActiveForm() systrap FrmHandleEvent(a0.l, &evt(a6)) ; Return from PilotMain when an appStopEvent is received PmEventDone cmpi.w #appStopEvent,evt+EventType.eType(a6) ;time to stop? bne.s PmEventLoop ;nope, loop until it is PmReturn moveq #0,d0 endproc ; --------------------------------------------------------------------------- ; Boolean ApplicationHandleEvent(EventType *pevt) ; Handles these events: ; frmLoadEvent proc ApplicationHandleEvent(pevt.l) beginproc movem.l a3,-(a7) ;save registers we're going to trash movea.l pevt(a6),a0 ;a0 = pevt ; Handle frmLoadEvents cmpi.w #frmLoadEvent,EventType.eType(a0) ;frmLoadEvent? bne AHENotHandled ;no ; Initialize the form and make it active systrap FrmInitForm(EventType.data+frmLoad.formID(a0).w) move.l a0,a3 ;save a copy of FormPtr for later systrap FrmSetActiveForm(a0.l) ; Get pointers to the two fields we'll be working with (decimal, hex) systrap FrmGetObjectIndex(a3.l, #kidcDecimal.w) systrap FrmGetObjectPtr(a3.l,d0.w) move.l a0,gpfldDecimal(a5) ;save the field ptr away systrap FrmGetObjectIndex(a3.l, #kidcHex.w) systrap FrmGetObjectPtr(a3.l,d0.w) move.l a0,gpfldHex(a5) ;save the field ptr away moveq.l #1,d0 ;event handled bra.s AHEReturn AHENotHandled clr.b d0 AHEReturn movem.l (a7)+,a3 endproc ; --------------------------------------------------------------------------- ; Boolean MainFormHandleEvent(EventType *pevt) ; Handles these events: ; proc MainFormHandleEvent(pevt.l) beginproc movea.l pevt(a6),a0 ;a0 = pevt move.w EventType.eType(a0),d0 ; Handle frmOpenEvent cmp.w #frmOpenEvent,d0 bne MFH1 ; Draw the form systrap FrmGetActiveForm() systrap FrmDrawForm(a0.l) moveq.l #1,d0 bra MFHReturn ; Handle frmMenuEvent MFH1 cmp.w #menuEvent,d0 bne MFH2 cmp.w #kidmAbout,EventType.data+menu.itemID(a0) bne MFHNotHandled systrap FrmAlert(#kidrAboutAlert.w) moveq.l #1,d0 bra MFHReturn ; Handle ctlSelectEvent MFH2 cmp.w #ctlSelectEvent,d0 bne MFHNotHandled ; Is the convert button being clicked? cmp.w #kidcConvert,EventType.data+ctlEnter.controlID(a0) bne MFHNotHandled jsr Convert(pc) ;yes, convert the number bra MFHReturn MFHNotHandled clr.b d0 MFHReturn endproc ; --------------------------------------------------------------------------- ; void Convert(void) ; proc Convert() local szT.12 beginproc movem.l d1-d3/a3,-(a7) ; Yes. Convert the number ; 1. Figure out which field was changed (if any) systrap FldDirty(gpfldDecimal(a5).l) tst.w d0 bne CVT2 systrap FldDirty(gpfldHex(a5).l) tst.w d0 beq CVTReturn clr.w d0 CVT2 move.w d0,d3 ;d3 = fDecChanged ; 2. Get its text and convert it from ASCII to integer move.l gpfldHex(a5),a0 ;assume Hex changed tst.w d3 ;Decimal changed? beq CVT3 ;no move.l gpfldDecimal(a5),a0 CVT3 systrap FldGetTextPtr(a0.l) cmp.l #0,a0 ;is there any text in the field? bne CVT31 ;yes systrap FrmAlert(#kidrInputErrorAlert.w) ; a comment bra CVTReturn CVT31 tst.w d3 ;convert from decimal? beq CVT4 ;no ; PalmOS includes a function for converting from ASCII to integer systrap StrAToI(a0.l) bra CVT5 ; Must implement our own ASCII-hex to integer converter CVT4 move.l a0,a3 ;save a copy of the char * systrap StrLen(a0.l) move.w d0,d2 ;convert loop counter subq.l #1,d2 sub.l d0,d0 CVT41 lsl.l #4,d0 move.b (a3)+,d1 sub.b #'0',d1 cmp.b #9,d1 ble CVT42 sub.b #7,d1 cmp.b #$f,d1 ble CVT42 sub.b #$20,d1 CVT42 or.b d1,d0 dbra d2,CVT41 cmp.l #$10000,d0 blt CVT5 systrap FrmAlert(#kidrRangeErrorAlert.w) bra CVTReturn ; 3. Convert from integer to ASCII-hex or ASCII-decimal, as appropriate CVT5 move.l d0,-(a7) ;push integer pea.l szT(a6) ;push pointer to string buffer tst.w d3 ;convert from decimal? bne CVT6 ;yes trap #15 dc.w sysTrapStrIToA addq.l #8,a7 ;pop the args off the stack bra CVT7 CVT6 trap #15 dc.w sysTrapStrIToH addq.l #8,a7 ;pop the args off the stack CVT7 ; addq.l #8,a7 ;pop the args off the stack ; 4. Place the new ASCII string in the appropriate field move.l gpfldDecimal(a5),a3 ;assume Hex changed tst.w d3 ;Decimal changed? beq CVT8 ;no move.l gpfldHex(a5),a3 CVT8 ; erase the old string systrap FldFreeMemory(a3.l) ; insert the new string systrap StrLen(&szT(a6)) lea.l szT(a6),a0 tst.w d3 ;converting to decimal? beq CVT83 ;yes ; truncate hex numbers to 4 digits move.w d0,d1 subq.w #4,d1 blt CVT83 sub.w d1,d0 add.w d1,a0 bra CVT83 ; strip off leading zeros CVT82 cmp.b #'0',(a0) bne CVT81 addq.l #1,a0 subq.w #1,d0 CVT83 cmp.w #1,d0 bgt CVT82 CVT81 systrap FldInsert(a3.l,a0.l,d0.w) CVTReturn ; Clear the dirty bits on both fields systrap FldSetDirty(gpfldDecimal(a5).l,#0.b) systrap FldSetDirty(gpfldHex(a5).l,#0.b) movem.l (a7)+,d1-d3/a3 endproc ; ; Resources ----------------------------------------------------------------- ; ; Application Icon Bitmap resource. Is automatically converted from Windows ; format to Pilot format and written as a 'tAIB' rather than 'Tbmp' because ; kidbAIB is a special value ($7ffe) res 'WBMP', kidbAIB, "Sample.bmp" ; 'pref' resource. Defines app launch flags, stack and heap size res 'pref', kidrPREF dc.w sysAppLaunchFlagNewStack|sysAppLaunchFlagNewGlobals|sysAppLaunchFlagUIApp|sysAppLaunchFlagSubCall dc.l $1000 ; stack size dc.l $1000 ; heap size ; Form resource res 'tFRM', kidfMain, "tfrm03e8.bin" ; Version resource res 'tver', kidrTVER dc.b '1.0', 0 ; Menu resource res 'MBAR', kidmMain, "mbar03e8.bin" ; Alert resources res 'Talt', kidrAboutAlert, "talt03e8.bin" res 'Talt', kidrInputErrorAlert, "talt03e9.bin" res 'Talt', kidrRangeErrorAlert, "talt03ea.bin"