Files

4878 lines
153 KiB
Plaintext
Raw Permalink Normal View History

2026-07-06 17:27:17 +01:00
SIBO 'C' Software Development Kit
GENERAL PROGRAMMING MANUAL
Version 2.30
March 1, 1999
(C) Copyright Psion PLC 1990-98
All rights reserved. This manual and the programs referred to herein are copyrighted works of Psion PLC,
London, England. Reproduction in whole or in part, including utilization in machines capable of
reproduction or retrieval, without express written permission of Psion PLC, is prohibited. Reverse
engineering is also prohibited.
The information in this document is subject to change without notice.
Psion and the Psion logo are registered trademarks, and Psion, Psion MC, Psion HC, Psion Series 3, Psion
Series 3a, Psion Series 3c, Psion Siena and Psion Workabout are trademarks of Psion PLC.
TopSpeed is a registered trademark of Clarion Software Corporation. IBM, IBM XT and IBM AT are
registered trademarks of International Business Machines Corp. Microsoft and MS-DOS are registered
trademarks of Microsoft Corporation. Apple and Macintosh are registered trademarks of Apple Computer
Inc. VAX and VMS are registered trademarks of Digital Equipment Corporation. Brief is a registered
trademark of Underware Inc. Psion PLC acknowledges that some other names referred to are registered
trademarks.
Contents
1 Installation .............csccsssssssscssscrssssceeeeseeeseeeseesseesssesseesseesseesseesseesseesseesseesceesceesseescesscsscesoseesoeees 1-1
Installation: :: i328 Assisi Aces whe chad Oks Ahsdoke sneha saniiin 1-1
Dif CtOry StEU Chute css 259s sie, Boost eek os shsg eats tess eth clees da Dies cos thes oT Dees ous hes eb Tset vous Teeneeeaav 1-2
Reconfiguring the TopSpeed project SysteM...........cssessecssseeesneecsseecsseeceseeeesaeessaeers 1-2
Customising the redirection file... eee eeeesesccssneeceneecseecsseecsseeeesseessaeecsaeesssneeessaes 1-3
2 A Brief Overview Of The SIBO SDK...............scsscsssssssssesesssesssessscsssesssessesesssessseessesssesssessoeees 2-1
Mantlal si as tcas crest a tacit a ptiteseder chai abste bei eiea ide ahr ianohii ast 2-1
WHEE TO SCALE sis ont 0k cee sat can abet ech veits es AlN oeuviuat ses alts cavvainases Ud oetitialens Gioia oe 2-2
The terms SIBO and EPOC explained ..........ceeceeceseseecsseessseeceseeeesaeeesaeecsaeeesseeessaes 2-2
Fatal programming errors (Pamics) .........ceseeeseeceseeessceeesseecsseecsaceceeecesaeeesaeesseessneeeeseaeers 2-3
Panic NUMDers :s..s:205 iors hess devas Gales eee eek bigs vaneiens ian Ghee 2-3
C++ and Object Oriented programming ...........eesceeseeceseeceseeesseeseeecseeeseseeeesaeessaeesseeesee 2-3
3 Building An Application ...............csscccssscssssccsscsssscsssssssssscsssecsssecsssssssssssssscnssscsessesssssssesseesees 3-1
INtroduchOti sais cei eh ab de ash kd Heh ah ee lg 3-1
Equipment required: :ctics 2 otesscvsthsce soba. cosa doee nesdussceusonasuestuaccavediseseassysoansibensseussaes 3-1
Whichfilesare needed 2.5. ccsscusi.5 coves cavsciestidebeccheves iol stebeset evveieh Steee sed seveted ees etlvber 3-2
Avfirst: éxample-applCattonicsssi.ci.tsiscssteasactealasieestesisceat le doenteaietenulads. agancdelasieesascaendst 3-2
A first look at projectiles o 525; ccissckeuei Seuscbehsiengotd Seubebetsaesaoch yuh veh sdebaten ouoh evshcgubeoeh Suenee 3-2
Creating: the ime filet:4 iain ohana lan ouB asian lanl 3-3
Copying the program to the target Machine ........ eee eeeeceeneeeeeeceeesseessseeessaeeesaee 3-3
Running the program on the target COMPULET........... ee eeeeeeeeneeeeneeceneeseaeessseeeeteeeesaee 3-3
Stepping through the program with the SIBO Debugger .......... eee eeeeeeseeeeseeeeeeeeenes 3-4
A PEIB version Of Hello Wotldssssis.scccbes.ceadeseseepiessc svda deste hiss apsviebe abtbies aeessarboeeeescbaae 3-4
PEIB- and CLIB conitrasted oi. sc... 205 sicse eves cevetul sees teas caved ub steve neste. fel stevssustevbs felseeseesstyl 3-4
The-code for p hello. i drcssectssvestasscasseaiate adacteostea lareadaadenstestaseendsieasteataceenderioes eters 3-5
The epocinit statement in -pr files... eee eee eeseeesseeceseeesseeeeseeeesaeecsaeesseeesneessnaeeesaes 3-6
Housekeeping batch files and re-using project files... eee eeseeeseeceseeeeeeeeesseeesaeessneeeees 3-6
A general project file: unnamed. pF oe. eee eeeeeeeseeceseeesseesseeceseeeesaeeesaeessaeessseeeesaes 3-6
A batch file for test Compilation .......... eee eeeeeeseeesseecsneeceseeeesaeeesaeecsaeecsaeessneeeeteeeesaes 3-6
SOME COMPLICALLONS. os 2565 55h sete oks Fe heh ios Povk a gheties Soe Sivd ou gh adieba Sen usd bu gb ctuboveu dunk aubetedo tue 3-7
TSE versus ISCX i sssiostiss Mann eatin Aeniisscess teas dapbescrsp bate sapdasecesp hase aspbebs evades vundays 3-8
More complicated programming SeCtUPS ..........:.csscessseceseeceseeeceseeceaeecseecseaeeesaeecsaeessneeeees 3-9
Simple: PEIB: examples. sis.2ccasiasesetasicasagiasventaalateesbaadvestaasatessdawdoestestavesetaaateatagsgers 3-9
Moulti- file: prograinss.i sc castsisiceiiecigasl a sccbehicskpth auhcvelceeheoek Sheicvehjesbepehoigievesdestek sist 3-9
Graphics programs. ::..2.5:4 cp mstdceai Mapas dete Aeiiesicnipiensdapbeadseteti ss dngiescAeetise deeds 3-10
FAWIP progranns csc ossi0s cossccts tours cds Faveeubedevsesdsduyacad edu vse sdsdueaeevsdvetesds svneebsteesecosteensvbanes 3-10
Customised) libraries ¥s.::2)c<.t2s.ss555.92.diabateansaiste ddatpeatacisgeeleahe asibasounlastetestansendastoees 3-10
Applications containing assembler as Well aS Cu... eee eeeeceeseeceseeeesneeseeeesseersaeeseeeeees 3-11
Other advanced use of the project file SySteM..........esceesceeessceeesneeceseeceneeceseeeesaeessaeers 3-11
Greater control over the image file created... eee eeeeeseeesneessneeceeeeceeeesaeeesaeeesaeersneeenee 3-12
Priority, minimum heap, and version NUMDET............: ce eeeeeseesneeeeneeceneeceseeeseeeeneeeesaes 3-12
Use.OF Edumipiex rc. isiiit jf it ievieta Mis nhee Mi Ane oeiicciad sie eaten ile sed 3-12
Differences between .app files and .1mg files 0.0.0... eles eeeeeesneeeeneeceeeceeeeseeeeseeeesaes 3-13
Ad d=file ist si... ess Seeose ed Stbbe ous oP ysis saubease Sevseeesebsdis TeesesbeSas RIP Ivers thus nerve eres 3-13
Changing the set of add-files in an 1Mage......... eee eeeeeeeseeceseeeseecsaeecsseeeeseeeesaeeseaeers 3-14
Further uses of emake.exe ............ccccccceseeseccccccceeessseccccssseeeesseecccsssseueeseescessssueeeseeessess 3-14
GENERAL PROGRAMMING MANUAL
ii
4 Notes On CLIB.............sccssssssscssscsssesssessserssesssesssesssesseesssssssesssesssesssesssesssesseesssessesseessseessesseeeseees 4-1
Functions missing from the MS-DOS JPIC library... eee eeeeeseeesseeeeseeeeeneeeeneees 4-1
TAS OR 5s deste ces; cass nevedeepavstbs sb eeagbassdact salscesodanpdhugasasevacespdensosbi cusses sosevehes Aantensseeraion tes 4-2
DIVE eset rt MM eR el oa NN oe ah oe te eee area ones ute aa PEG cara eset hs 4-2
File handle conversion routine............ceeseseseecsscecesceesseecseecseecsseeeesaeecsaeessneessseeeesaes 4-2
Phe Console: Channel. 22. cscs ices svadesessahpscossteg egebseey ages ced evebsdes seete dns esehstnpsaubeted oses step pee 4-3
MS-DOS file names.$3:.; ac.cseiyaieentiaelecnsie aie oui are ei ayia 4-3
Floating point emulator .......... ce eeeeeeeeesseecsscecsseeceseeeesneecsaeecsseeceseecesseecsaeecseessneeeesaes 4-3
Pate 80:s3isni this talest gain dain saad Palas ote Shaina osetia. 4-3
Building the CLIB library and header objects ............eeeeeeseeseseeceseeeeeeeeesseeesaeesseeeees 4-4
Cautionary Notes sssi.c.e i etiavien it ashe aoiaaiei ota bad ieee 4-4
5 Fundamental Programming Guide-lines ................cccssccssssseccsscssecssccecsssccecesseseesssccseesssceseeens 5-1
Tin tr OG UCHIOT os ek tes el iach i at wae cate cal ced ste cand eat see canned aenteat Si steee canta 5-1
Other related docuMeNntatiOn.......... ee eeseeeseecsseecesceeesseecsseecseeceseeeesaeessaeesseeseneeessaes 5-1
The source code for the examples ............eesceesecceseeeeseecseecsceseseeeesaeecsaeesseeesneeeesaes 5-2
User Anterface:. sii 2isi8 thas ets as bee avis lensed Avid dau esi tvico bei esiteda teh 5-2
A first look at multiple event SOUTCES......... cee eeseeeseeesseeeesceceeseeesaeecsaeecsseecseecesaeeesaeecsaeers 5-3
Remarks On timers -.$:5. silts. oiel oo he Bled ea aed hie Band hao eetied 5-4
Remarks: on ke ypresses's:J.c5:33 sasiesidecvtsteAisiasihas beth Naidesddtedevid aioe dei Aenea ha 5-4
MO re Oi p1OWalt iss cos2o os sats Syceubsteus sab cdian cos vssisa Ans cous Avtsiba Aig eevadoreubs Ran eeiidawbonvs daads 5-4
Status words: the other side Of P_lOWa€It oo... eee eeeeeeseeceseeceseeeeseecseecseeseseeeesaeessaeers 5-5
Prioritisation Of CVENt SOULCES ........ eee eesecsseeesseeceseeeesseecsseecsseeceeeeesaeecsaeerseeesteeeesaes 5-5
VO devices ii ceneralicss, ateissi assess cast eA sisesiostsse Sh ssaveisndeesbesed stestoseepoasivaeensseeressi ha 5-5
The Console: device seccs2.es2.5 vege cuss sivedes Soves cuts Sesiel sake cavsebbesea savage cals cevaded Seats seitenusden Sinbely 5-6
How toCanicel::a thers ch sisiss-stssiacdticeassstacdeeledesetaatageetds tess eataosendadeasteaiagendaieaetens 5-6
Where to declare status WOrdS..........ccceescccseseessseecseecsneecsseecssaesesaeecsaeessaeeseeeessaeeesaes 5-7
A-first,look at ertorharidling 3: ).35c cenit dail endri ees eed e Baste 5-7
Brror handling in Events cin: coiscsess.basi.5 cats toons tsdhah eeisduose 0s bi bevadeesecus ds nsvetevsrDuteseiee 5-7
Fatal errors and non-fatal errors ..........eeeceeeseesseeesseecssceceececesaeeesaeecsaeessaeesseesssaeeesaes 5-8
When resources need to be tidied explicitly... eeeccesneeesneeesneeseseeseseeeesaeessaeers 5-8
Inter-Process Communication: Events2 and Subproc.........eeeeeeeseesseeeeseeceseeeeseeeesaeeesaeers 5-8
Acthird €vetit SOULCE ws c.65cistescd0s seuss eckeeebtee, Fei stvbs foibteestes stvie feb Tebslen sins Pevtdewsta ste de 5-8
How Events2 passes data to SUDPI0C........ eee eeseeeeseeeeseeceseeeesaeeesaeecsaeecsaeessneesesaeeesaes 5-9
The Code ti SUBProcis css sot cass cvs ssies Sab Lobe ewek Sheu pied Pedbewss Subd Lock Setacw es Seeeuoeh ocoenweh Sesooeh Senne 5-10
Mechanisms for inter-process COMMUNICATION .......... eee eeeeeeseeeseeeeeeeeseeeeaeessaeesseeeees 5-10
Debugging cooperating applications ........... cee eeeseecsseeeeseeeesseeesseecsaeecseecsseeeesaeeesaeers 5-11
Error Handling im Bvents2.5:.235 hss stds hcenkictessedealetentigiagsotesisceeidatsosanaaieasieatiaesneanenyiass 5-11
Socially responsible programming in Events2............:ecceesseeesseeeeseecsececeeeeeseeeeseeeesaes 5-11
Data received from:a-serial port s.s.s.5:.5 sts eiades his dacien aes eathisl asin An 5-11
Opening the:serial: Port cssis: yess ochisek saves cash cieised Stees eavlevesselstese cas ieves ced sesesw eevee aeeei ss 5-12
Active and inactive CVeNt SOUTCES 20... eeseeesseceseeeeseeeseeeesaeecsaeecsacecsseecseeeseeesnaeeesaes 5-12
Debugging applications with serial COMMS ............:esecesseceeseeeeseeeseecsneeeeseeeesaeessaeers 5-13
The tole:of: ptickles 2:8 wise aA inde iitha dade asada tshadea aes 5-13
Yielding CPU in compute-intensive programs ...........ssccseseeceseeceseceseeeeseeessaeecsaeessereeeenes 5-13
Tdl@:ObjecCtss. 2: ssesisscsscaseesteaissectagusaasd ataceas deters ncaisenndaseadeenesaat daha Moeetes etenhda Goeetdaa st cat 5-14
The meaning of calling p_1osignal......... ees eeeeeseecesneeeseeseeeesaeeceacecseeceseesseeseseeeesaes 5-14
One drawback of COMtiINUOUS ACtIVILY ...... eee eee eeeeeeeseeceeeeseeeesaeeceaeecsseecetersneeeenaeeesaes 5-14
Remarks On process PriOrities ........ ee eeseeeseecsseeeesceeesseecsaeecseeceseecesaeeesaeesseeesneeeesaes 5-14
The-call p-tOvyieldissisiss. sdasscessashassadaseteatastasiostatess tan caseendateestentassenda seasteaiaveendateastgas 5-14
Gremeral Perm ark o.ii61. 255s scis sh nahh a oest iocs disk Bevdeed Se ckbvad pes cbeesied hisheoui se sheteh el ouboe sereh erent oe 5-16
Multi-threadedness and multi-tasking... eee eeeesseeeseeeeseeeeseeeesseeseeeesaeessaeesseeeees 5-16
Subprocess or 1dlé: Object? «1.5. isseeestais bi steviesevich eistest tc ata aeons bees 5-16
Window redraws as an Vent SOUTCE....... ee eeesenecesneessneeseseeceseecsseecesaeessaecesseeesneeeesaes 5-16
The APPMAN and ACTIVE classes in OLIB .0......ceseeeeceessecesseeceneecseeeeeseeeesaeessaeers 5-16
CONTENTS
6 Copy-Protecting Softwar e...............scsscssccssscssssscssesssscscecssscesssscssesssscsssssscsscsssscssesssscssssssceseees On
Tin tO Ct Oni aps fos oe dees teg shoes eiestene tee stcga estes See sata ig stes ott slong esac seep tene eset deestene eats 6-1
The freespace method s:.icisieiia ph eit ia. pei banning es 6-1
First generation copying methods......... ec eeeeeseesscesssceesseecesseeesaeecsaeecseecsseecesaeeesaeeesaeers 6-2
Preserving checksums :..3...2.:rvidiene aie kieran eh al nna eie 6-2
What kind of change should be made «0.0.00... eeeeeeeeesseeeeseessnceceseeeesaeecsaeessaeesseeeesas 6-2
Restricting the number of copies Made .......... ees eeseeeseeeeseceesseeesseecsseecsneeceseeeesaeessaeers 6-3
Low level SSD information, « o::.06. 22st. he oes eho hk ee oe dhe eel ae eh ad ae 6-3
Copy-protection by changing the ROM 00.0... eescessecsseecsseeceseeeesaeeesaeecsaeecesaeeesaeessaeers 6-3
7 Compatibility: sccsscssccccsscsecccssssescestcsnsacsesssaassssssssssosvensseseveasdsocvansdsdevansdsentancsesssadessnosesessosnstesueseeg dL
Initroduct On ¢::::.43. nA kee ius Lis Anh Aoh lhe Mon koh aah aae 7-1
What machine am I running ON? ............ceeecceeessceceeseceeesseneecessaseecessneecensaneesessnsesessnsesenses 7-1
iii
CHAPTER 1
INSTALLATION
The Psion SIBO 'C' Software Development Kit (SDK) enables you to develop applications in 'C' for the
Psion SIBO family of hand-held and notebook computers:
e the HC range of corporate handheld computers
e the Series3 range of palmtop computers
e the MC range of laptop mobile computers.
The SDK is PC based - that is, you write and build your applications on a IBM PC or compatible and then
run (or debug) the application on a SIBO computer.
The SIBO SDK comes in three variants: Professional (Prof), Standard (Std), and Documentation (Doc).
The Prof and Std variants contain differing amounts of the TopSpeed C Package (produced by the Clarion
Software Corporation):
e the Prof variant contains the complete TopSpeed C Package
e the Std variant omits the TechKit and C Library Source Kit portions of the TopSpeed C Package.
Parts of the TopSpeed C Package are required in order to build any SIBO application. These are the parts
included in the Std variant of the SDK.
The TopSpeed C Package may be used independently of the SDK to write C programs to run on IBM PCs
and compatibles.
All three variants of the SDK contain the same three volumes of SDK documentation, comprising 14
different manuals all told, together with associated software produced by Psion. This software
incorporates libraries, header files, auxiliary programming tools, example programs, and much more
besides.
Installation
There are three phases to installing the SIBO SDK:
e installing the small code model of the TopSpeed C Package
e installing Psion software and example programs
¢ customising the TopSpeed system using special Psion files.
For information on installing the TopSpeed system, see the TopSpeed C documentation. (You may install
other code models as well as the small code model, but they will not be used by the SIBO SDK).
The Psion software consists of required parts and optional parts. For a full description of all the
available files, see the read.me files in the root directories on the supplied disks.
The files on the disks are in compressed ("zipped") form. The disks contain the pkzunzip program, which
can be used to decompress ("unzip") the other files as they are copied.
The installation procedure ensures that each group of files is copied to its correct directory. The read.me
files on the disks specify which files are present in each group.
GENERAL PROGRAMMING MANUAL
Directory structure
The TopSpeed software is usually located in a \fs\ directory tree.
The Sibosdk software is usually located in a \sibosdk\ directory tree.
There is no need for the \rs\ and \sibosdk\ directory trees to be on the same partition of your hard disk. Eg
the TopSpeed system could be on drive c:, with the Sibosdk system on drive d:.
Both the \ts\sys and \sibosdk\sys directories should be added to the MS-DOS path. Alternatively, you may
copy the contents of \sibosdk\sys (with the probable exception of the ts.red redirection file - see
Customising the redirection file below) to \ts\sys, in which case you will only need to add the \rs\sys
directory to the MS-DOS path.
Subdirectories under \sibosdk\ include:
lib the location of standard libraries, startup objects, and some loadable device drivers
(dynamic extensions to the SIBO operating system)
include the location of header files
sys the location of the SIBO Debugger and other miscellaneous programming tools
pr the location of some standard project files
demo the location of various standard demo programs
s3atool Series 3a versions of an icon editor and the Spy application
STC (not present in all versions) the location of the source code for the Clib (standard C)
library
hwdemo (optionally) the location of programs demonstrating use of the HWIF library
hwifsre (optionally) the entire, buildable, source of the HWIF library, for interest and/or to allow
the writing of extensions to HWIF
wd (optionally) the source printer scripts of some WDR printer driver files
Idd (optionally) the source code of some example device devices
hemast (optionally) software allowing alternative versions of the HC rom to be built
wkdemo (optionally) source code of example software for the Workabout
fconv (optionally) software allowing the creation of file format conversion DYLs for Word
oopdemo (optionally) the location of programs demonstrating the basic use of the Object Oriented
Programming system (other directories contain more advanced examples)
record (optionally) the source of the Object Oriented Series 3a Record application. This is
buildable, provided that the \sibosdk\oop directory has also been installed
The SIBO SDK requires between 3 and 6 Megabytes of disk space, depending on how much of it is
installed.
Reconfiguring the TopSpeed project system
The Sibosdk software contains files, including tsprj.txt and tsmain.txt, that are replacements for files of
the same name released by TopSpeed. The Sibosdk versions of the files allow the TopSpeed project system
to handle the Epoc 1Mc system type, and the Sibosdk tools generally, in addition to the systems normally
supported by TopSpeed. (See the following chapter for more details.)
The Sibosdk versions should be copied, from \sibosdk\sys, over the TopSpeed versions in \ts\sys (as guided
by read.me). Copies of the original TopSpeed files should be kept, with their extensions changed to .old
(say).
In case any specialised changes have already been applied to, say, your tsprj.txt and tsmain.txt files, you
should re-apply these changes to the Sibosdk versions.
1 INSTALLATION
In order for all these changes to have any effect, the TopSpeed tool tscfg has to be run:
type cd \ts\sys to enter the appropriate directory
type tscfg to invoke tscfg.
Note that the replacement files are not the same as those supplied with versions of the SDK earlier than
2.0. You must therefore repeat the reconfiguration process, even if you are upgrading from a previous
SDK version.
Customising the redirection file
The \sibosdk\sys directory contains the redirection file ts.red that allows the TopSpeed project system to
find the SIBO SDK header files, library files, and other required files. When you invoke the project
system to build an Epoc application it must be able to find this file. If there is no such file in the current
directory, the TopSpeed system looks for this file in the directory containing the TopSpeed software itself
(usually \ts\sys). So there are two options:
e overwrite the TopSpeed ts.red file (in the \ts\sys directory) with the Psion ts.red file (in the
\sibosdk\sys directory), and place a copy of the original TopSpeed ts.red file into the directory in
which you are writing PC C applications (if any)
¢ copy the Psion ts.red file into the directory in which you are writing a SIBO application.
The first option is more appropriate if you are writing more SIBO applications than PC applications, the
second if you are not.
The contents of the default ts.red file is basically as listed below. Again, note that the supplied file is
different from the ts.red in earlier versions of the SDK.
*.PR = .; C:\SIBOSDK\PR;
* 7H = .; C:\SIBOSDK\INCLUDE;
*,HPP = .; C:\SIBOSDK\INCLUDE;
*,RH = .; C:\SIBOSDK\INCLUDE;
ta = .; C:\SIBOSDK\INCLUDE;
*.RG = .; C:\SIBOSDK\INCLUDE;
*.XG = .; C:\SIBOSDK\INCLUDE;
*.RSG = .; C:\SIBOSDK\INCLUDE;
* INC = .; C:\SIBOSDK\INCLUDE;
ee = .; C:\SIBOSDK\SRC;
*.CPP = .; C:\SIBOSDK\SRC;
*.CAT = .; C:\SIBOSDK\SRC;
*.A = .; C:\SIBOSDK\SRC;
*.,OBJ = .; C:\SIBOSDK\LIB;
* LIB = .; C:\SIBOSDK\LIB;
* HLP = C:\TS\DOC;
For example, the meaning of the line
*.H = .; C:\SIBOSDK\INCLUDE;
is that any .h file referenced in the course of building an application should be searched for first in the
current directory, then in the c.\sibosdk\include directory.
To increase the search path for .h files, so that private .h files can be located from some other directory,
just edit the ts.red file so that the line becomes, for example:
baa! = .; ..\INCLUDE; C:\SIBOSDK\INCLUDE
Note that the contents of this file assume that you have installed the Sibosdk system on your c: drive. If
you have installed it on another drive you will have to edit ts.red to refer to the appropriate drive.
1-3
GENERAL PROGRAMMING MANUAL
1-4
CHAPTER 2
A BRIEF OVERVIEW OF THE SIBO SDK
The SIBO SDK consists of a set of floppy disks containing the SDK software and a number of manuals
describing the software and the Psion SIBO family of mobile and hand-held computers. The floppy disks
contain the various tools, header files, libraries etc that are required to produce an image (img) file that
will run on Psion SIBO machines.
Manuals
The SDK manuals supplement the TopSpeed manuals. In particular you are referred to the TopSpeed C
Library reference for the description of standard C (CLIB) library functions.
The SDK contains the following manuals:
General Programming Manual
HC Programming Guide
Series 3/3a Programming Guide
Workabout Programming Guide
EPOC OSS System Services
Additional System Information
PLIB Reference
Window Server Reference
I/O Devices Reference
The SIBO Debugger
Hardware Reference
Programming in HWIF
This manual. It describes how to install the SDK, and how to
build an application that will run on the SIBO machines. It also
contains some notes on using the TopSpeed C Library reference
manual, some discussion on how to copy protect software for
SIBO computers, and a potentially very important chapter entitled
Fundamental Programming Guidelines.
Some documentation particularly oriented around the HC
computer range.
Some documentation particularly oriented around the Series 3
range of machines.
Some documentation particularly oriented around the Workabout
computer.
Describes the software interrupt interface to the ROM-based
system services. An appendix contains a complete listing of the
EPOC service numbers. This will be of particular use to OPL and
assembly language programmers who wish to make direct access
to EPOC services.
Describes the MCLink communications software, resource files,
WDR printing, various file formats, how to write device drivers,
and other miscellaneous topics.
Describes the Psion PLIB library (this library provides the most
direct access to the ROM based system services).
Describes the window server library WLIB which implements a
range of sophisticated graphics operations.
Describes the interface to some of the Epoc device drivers,
including those which access the serial and parallel ports.
Describes how to use the SIBO Debugger to debug applications
being developed for SIBO computers.
Describes the basic hardware of SIBO computers.
Describes the HWIF library (which contains support - mainly for
the Series3 - for menus, dialogs, editors, and printing).
2-1
GENERAL PROGRAMMING MANUAL
Object Oriented Programming Describes the development of applications using Object Oriented
Guide techniques. Its introduction provides an overview of Psion's
Object Oriented programming system and of the OLIB, HWIM,
FORM and XADD object libraries.
ISAM Reference Describes the ISAM dynamic library which provides Indexed
Sequential Access management for large database files.
OLIB Reference Describes the OLIB object library.
FORM Reference Describes the FORM object library.
HWIM Reference Describes the HWIM object library.
XADD Reference Describes the XADD object library.
Where to start
There is a very large amount of information in these manuals - perhaps too much for any one person to
keep it all in their head. However, few developers will need to make detailed reference to more than
around half of the manuals.
The manuals contain many cross references to sections where various topics are discussed in more detail.
Use these cross references to help you find your way around the SDK documentation. The chapter
immediately after this one is probably the best place to start. Alternatively, start reading the HC
Programming Guide, the Series 3/3a Programming Guide, the Object Oriented Programming Guide, the
Plib Reference manual - or anything that catches your eye as you flick through the pages.
The terms SIBO and EPOC explained
A SIBO machine is a battery-powered portable computer that is based on the SIBO architecture. This
architecture is designed to minimise the size, weight and power consumption of the computer. The key
components of the architecture are:
e A sophisticated power management system that selectively powers subsystems under software
control
e Solid State Disks (SSDs) that provide fast low-power silicon-based mass storage with no moving
parts
e Asynchronous serial interface for peripherals running at high speed (Mega bit rates)
e An 8086 class of processor (or any compatible processor such as an 80286)
e Hardware protection of the system from aberrant processes (address trapping of out-of-range
writes and a watch-dog timer on interrupts being disabled)
e = Real-time clock
e ROM-resident system software
e Graphics LCD display
e A touch sensitive digitising pad that provides a pointing device (used in some models)
e ISDN combo sound system (used in some models).
The hardware architecture is primarily implemented in custom ICs called ASICs. The SIBO architecture
uses surface-mounted static CMOS ICs throughout. For further information see the Hardware Reference
manual.
The EPOC operating system, designed for the SIBO architecture, has the following features:
e preemptive multi-tasking
e MS-DOS-compatible file systems
e installable file systems, including remote file access
e asynchronous services
e support for client-server architectures (used to implement system components such as the file
server and window server)
2 A BRIEF OVERVIEW OF THE SIBO SDK
¢ acomprehensive I/O system with many built-in I/O devices
e dynamically loadable device drivers
e reentrant function library
e multiple processes of the same program share a single copy of the code
e support for object-oriented programming
e code-shared dynamic link libraries.
On SIBO machines, the system software resides on an in-built ROM. A version of the EPOC operating
system also runs on a PC.
See the Plib Reference manual for more details.
Fatal programming errors (Panics)
When the system detects a condition that it believes could only arise from a bug in a the application
program, the system terminates the process with a "panic number" in the range 0 to 255 inclusive (where
the system is said to "panic the process"). A panic is a fatal exception that causes the process to terminate
immediately. There is no way for applications to avoid being terminated when a panic has been started.
As well as protecting the system from defective applications, the panic system enforces a greater discipline
on application code by terminating a process as soon as the condition is detected.
Panic numbers
Programming errors detected within different areas of the system code give rise to different panic
numbers. The following table lists the possible panic numbers and the corresponding system code that can
give rise to them.
0 to 80, and 255 The PLIB library
81 to 129 The Window Server library
130 to 160 The OLIB object library
These panic numbers are described in more detail in the appropriate manuals.
Panic numbers in the range 160 to 254 are used by code that is not resident in the ROM (such as the
ISAM library). A given panic number may be used by more than one piece of code; such a panic may
therefore have one of a number of causes. The only definitive way to discover the origin of such a panic is
to make use of the SIBO Debugger to catch the panic and then trace it back to its source.
C++ and Object Oriented programming
This version of the SDK is compatible with TopSpeed C++ although, at the time of writing, the TopSpeed
C++ package is not supplied by Psion as part of any variant of the SDK.
Note that the kinds of classes, and the means of creating and accessing them, in C++ are quite different
from those in the Psion Object Oriented programming system.
Regardless of whether you use C or C++ to develop Object Oriented applications, if you wish to use Psion
objects you must create instances of them and send messages to them by the mechanisms that are
described in the Object Oriented Programming chapter of the PLIB Reference manual and the Object
Oriented Programming Guide.
If you intend to develop a SIBO application that uses only Psion objects, you may still use C++ as a
"better" version of C, without making use of its Object Oriented aspects.
You may, if you wish, use a mix of Psion and C++ classes, provided you make sure that you create and use
instances of classes of each kind by the appropriate means. It is quite acceptable, for example, to use Psion
classes for the application manager and user interface, but use C++ classes in the 'engine of an
application.
GENERAL PROGRAMMING MANUAL
2-4
CHAPTER 3
BUILDING AN APPLICATION
Introduction
The end result of developing a program to run on a SIBO computer is normally an image program, with
characteristic extension .img. Essentially, .img files are to Epoc what .exe files are to MS-DOS.
(Sometimes, the image file is given the extension .app instead. See later for the distinction between .img
and .app forms of images.)
Image files are actually produced via an intermediary .exe file by the operation of a tool emake.exe,
though in practice this process is automated on behalf of the developer. The point is that the development
cycle for .img files is basically the same as for .exe files in more traditional programming environments.
The same compile-link-debug cycle exists in both cases.
The program is written, compiled, and linked on the PC. These steps involve the TopSpeed compiler and
linker, and TopSpeed project (.pr) files. These steps may also involve the full TopSpeed ts development
environment, which is an Integrated Development Environment (IDE). Alternatively, developers may
prefer a more traditional approach, involving their own favoured stand-alone text editor, and a batch-file
mechanism for invoking the TopSpeed compiler and linker.
Once linked, the program is transferred to the SIBO computer in one of three ways:
e under the control of the SIBO Debugger
e via a SSD written to by a PC SSD drive and then placed into the SIBO computer
e via a serial link, using Comms software such as MCLink.
A program running on a SIBO computer (though not one in its rom) can be debugged under the control of
the SIBO Debugger running on a PC. If the program has been built under special conditions, source level
debugging will be available; otherwise just machine-code level debugging.
The remainder of this chapter gives more details on all the above points:
e it introduces some particularly relevant aspects of the TopSpeed project file system
e it describes some batch files that may be found useful when building applications
e several example applications demonstrate the points made (all the example applications and
associated files referred to in this chapter are optionally copied into \sibosdk\demo when the SDK
is installed)
Equipment required
The following equipment is required in order to create an application that runs on a SIBO computer:
e One target SIBO computer (HC, MC, or Series3)
e One PC
e The TopSpeed C development system on the PC
e The Psion SIBO SDK software on the PC
e One or other form of communication between the HC and the PC.
3-1
GENERAL PROGRAMMING MANUAL
Around 5 to 7 Mbytes of PC hard disk is required to install the TopSpeed C development system and the
Psion SIBO SDK software. There is no particular requirement for the PC to have extended memory.
Development can take place on an XT, but a 486 machine with around 4 Mbytes of extended memory
machine will obviously produce results more quickly.
Which files are needed
To build an application, the following files are required:
e source files, such as .c and .h files
e aproject file, with extension .pr
e aredirection file, with name ts.red
e libraries, with extension .lib.
At the same time, various batch files (extension .bat) may be found useful.
Additional files may be required for the development of applications with the aid of the Object Oriented
system - see the Object Oriented Programming Guide for further details.
There is no need to have a separate project file or redirection file for every single application. For
example, ordinarily there will only be one redirection file on any one PC, shared between all applications
written on that PC. One possible exception is in the case of developers who use the TopSpeed system to
write PC programs as well as SIBO programs.
A first example application
The following discussion centres around a very simple "Hello World" program.
The source C code is as follows:
/*
HELLO.C
CLIB Hello World application
bai A
#include <stdio.h>
int main(VOID)
{
printf ("Hello World");
getchar();
return (0);
}
Evidently, the program prints the message Hello World onto the screen, waits for the ENTER key to be
pressed, and then terminates.
A first look at project files
Before hello.c can be compiled and linked, a project file needs to be specified. In this case, the following
(hello.pr) suffices:
#system epoc img
#model small jpi
#compile hello
#link hello
The meanings of the last two lines of this file are obvious enough: the file hello.c should be compiled, and
then the resultant object file linked to create hello.img. Note that in any case of ambiguity, the extension .c
should be added to the name specified in the #compile statement.
3-2
3 BUILDING AN APPLICATION
The first two lines in hello.pr are less obvious. Their meanings are as follows:
#system epoc img The end outcome of the build is a .img file, as defined in the Epoc-customised
part of the TopSpeed configuration (alternative #systems include dos and win)
#model small jpi The code is to be compiled in small model (code and data segments each
restricted to 64K), with the jpi (TopSpeed C) convention of using registers to
pass parameters to subroutines.
These two lines must be present in all project files used to build applications for SIBO computers.
Other possible contents of .pr project files are discussed later in this chapter.
Creating the .img file
There are two ways a .pr file can be used to create a .img program:
e inside the TopSpeed ts programming environment (see TopSpeed documentation for full details)
¢ outside the ts environment.
For example, one reason for working outside the ts environment would be to allow the use of another text
editor, such as Brief.
The remainder of this programming manual describes use of .pr files outside of the ts environment.
For the moment, simply type:
tsc /m hello
to have hello.c compiled and linked, with the end result (among other files) being hello.img.
The significance of the /m parameter is that the project file is executed in "make" mode, with files not
being recompiled or relinked needlessly.
Copying the program to the target machine
If your PC has a set of SSD drives attached, simply copy hello.img onto an SSD in one of these drives,
and then insert the SSD into the target machine (the SIBO computer). Otherwise, you may wish to use
MCLink as follows:
¢ connect the SIBO computer to your PC using a suitable cable
e run the Link application on the target machine (type 1ink at the HC command line, click on the
Link icon on an MC, or set Remote Link on in the System Screen of a Series3)
e run MCLink on the PC (eg by typing mcurnx if \sibosdk\sys is on your path)
e adjust the MCLink serial port and baud rate parameters if required
e type copy hello.img rem::m:\hello.img to transfer the program to the m: drive of the remote
machine (or copy the file to rem: :m:\img\hello.img on a Series3)
For more details about the MCLink program, see the chapter Mclink, Mcprint, and Slink in the Additional
System Information manual. (For example, that chapter explains how the whole process of running
MCLink can be handled via time-saving batch files at the PC end of the connection.) Finally, another
way the program can be transferred from the PC to the target computer is by using the SIBO Debugger, as
discussed below.
Running the program on the target computer
The way the program is run on the target computer varies from computer to computer:
e onan HC, simply type hello at the s prompt of the Command Shell
e onan MC, use the Run menu command of the System application, and select hello.img
¢ ona Series 3 or Series 3a, the entry Hello will appear in the file list of the RunImg application
when this list is next updated (assuming that hello.img has been copied into a \img\ top-level
directory), so that hello.img can be run simply by positioning the highlight over Hello and
pressing ENTER.
3-3
GENERAL PROGRAMMING MANUAL
Stepping through the program with the SIBO Debugger
In order to debug a program, there is no special need to copy it "by hand" onto the target machine.
Just type
\sibosdk\sys\sdbg hello
(or equivalent) at the PC end, and ensure Link is running on the target computer. (These instructions
assume that hello.img is in the current directory on the PC.) In due course, the debugging screen will
appear on the PC. (When debugging a program running on an MC, the baud rate for the Debugger to use
may have to be given explicitly - eg \sibosdk\sys\sdbg -b19200 hello.)
Step through the program (use F8 or ALT+S) until it hangs (waiting for a key to be pressed on the target
computer). Or simply run the program to completion (use F9 or ALT+R).
In fact, if hello.img has been built as specified above, the debugging screen will come up in machine code
level. In order to debug at the source code level, a slight change has to be made in the way hello.img is
built:
e = either a line #pragma debug (vid=>full) has to be inserted in the project file (before any
instruction to #compile)
e alternatively, a parameter /v2 can be added to the command line invoking the project file.
Thus typing
tsc /m hello /v2
at the PC command line builds a version of hello.img suitable for source level debugging.
As before, just type
\sibosdk\sys\sdbg hello
but this time, the debugging screen by default starts in source level mode, and supports inspection of
variables, etc. See the SIBO Debugger manual for more details.
A PLIB version of Hello World
PLIB and CLIB contrasted
The above "Hello World" program uses the so-called CLIB library.
CLIB is a version of the TopSpeed C library for the EPOC operating system. As such, it is a version of the
standard ANSI C library. The functions in CLIB are described in the TopSpeed C Library Reference
manual. Additional notes, including a list of the TopSpeed C library functions that are not implemented,
may be found in the following chapter, Notes on Clib.
The EPOC version of the TopSpeed C library supports the ANSI functions and most of the portable
functions that are commonly supported by MS-DOS C libraries such as Microsoft C and Borland's Turbo
C. The less portable functions such as those that access the BIOS and graphics functions are not included.
The benefits of using CLIB are:
e portability (existing C programs can easily be converted)
e less to learn for programmers already familiar with standard C libraries.
However, for many programs, developers are strongly urged to consider using not CLIB but PLIB - Psion's
proprietary C library. Whilst PLIB differs from the ANSI standard in many places, there are good reasons
for all these differences, so as to best take advantage of the Epoc architecture. In particular:
e many of the ROM-based EPOC system services are not available from CLIB (eg asynchronous
I/O, inter-process messaging, the window server graphics functions)
e executables are larger in CLIB and the process takes a larger data segment.
The executables are larger because, although CLIB uses the ROM-based system services wherever
possible, it is still a much "thicker" library than PLIB. The data segments also tend to be larger because
the various CLIB subsystems typically require large static buffers and tables.
3-4
3 BUILDING AN APPLICATION
See the Introduction chapter of the PLIB Reference manual for more details.
In fact, unless you are using the in-built user interface object dynamic libraries (accessed using object-
oriented programming), you can freely mix PLIB calls with CLIB. Experienced C programmers can, if
they wish, initially use the more familiar CLIB functions and regard PLIB and WLIB (the window server
library) as they would regard non-portable components of any C library.
It is worth converting completely to PLIB and WLIB when the desirability of making efficient use of
memory outweighs the benefits of portability and familiarity.
The code for p_hello.c
The code for a PLIB version of the above program hello.c is contained in the file p_hello.c:
/*
P_HELLO.C
PLIB Hello World application
ef
#include <plib.h>
GLDEF_C INT main(VOID)
{
p_printf ("Hello World");
p_getch();
return (0);
}
and a corresponding project file p_hello.pr would be
#system epoc img
#set epocinit=iplib
#model small jpi
#compile p_hello
#link p_hello
The following differences will be noticed between hello and p_hello:
e the PLIB program uses a Psion-proprietary header file (plib.h in this case)
e the PLIB program uses Psion-proprietary function calls (p_xxx functions)
e the PLIB program links with a different library (this is one effect of the epocinit line in the
project file - discussed further below).
To build p_hello.img, just type either tsc /m p_hello Of tsc /m p_hello /v2 (the latter producing a
version supporting source-code debugging).
As a result of the differences between hello and p_hello, a substantially smaller .img file is produced (try it
and see).
The reason for the remarkable codesize improvement of the PLIB program is that, as mentioned earlier,
the functions in the PLIB library provide only very thin shells over functionality that is present in the
ROM of the SIBO computer. PLIB programs make better use of the SIBO ROM software than do CLIB
programs. Being tailored to the particular needs of SIBO computers, PLIB evolved with very different
constraints and objectives from standard C libraries. In many cases, PLIB functions can be claimed to
"improve" upon the specification of their nearest CLIB equivalents.
The difference in size between CLIB and PLIB programs is not always so remarkable as in the above
example - it depends on the number and types of library function calls made. Indeed, it is perfectly
possible to write some parts of an application using CLIB, and others in PLIB. This fact considerably
simplifies any process of converting a previous large programming project from one computer system to
the SIBO SDK system.
Whilst it is possible to avoid PLIB entirely, this is not recommended. Time spent gaining familiarity with
the functions in the PLIB library should prove an excellent investment, aiding the production of leaner
and more powerful applications. In any case, familiarity with PLIB is a pre-requisite for accessing many
other parts of the SIBO ROM software - such as the enhanced graphics facilities of the Window Server.
3-5
GENERAL PROGRAMMING MANUAL
The epocinit statement in .pr files
In p_hello.pr, the command
#set epocinit=iplib
sets the value of the project macro %epocinit. Note that this command must precede the #mode1 command
in any .pr file.
This command serves two purposes: it specifies whether you are using the CLIB or PLIB startup object
files, and it specifies the stack size for the .img file produced. The allowed values of sepocinit are:
iclib CLIB startup, 8k stack (recommended size when using CLIB startup)
iclib4 CLIB startup, 4k stack
iclib2 CLIB startup, 2k stack
iplib PLIB startup, 4k stack (recommended size when using PLIB startup)
iplib8 PLIB startup, 8k stack
iplib2 PLIB startup, 2k stack
If sepocinit is not set then it defaults to iclib (as in hello.pr).
You must use the CLIB startup object files if you are writing a program that includes any CLIB library I/O
functions. It is, however, possible to use many CLIB library functions (for example, the memory allocation
functions) in conjunction with the PLIB startup. If you do not use any CLIB library functions then you
should always use the PLIB startup.
See the Introduction chapter in the PLIB Reference manual for more about startup object files.
Housekeeping batch files and re-using project files
A general project file: unnamed.pr
Clearly, a project file such as p_hello.pr can be used, with only nominal changes, for a wide range of other
similar programs.
Consider the related project file, unnamed.pr:
#system epoc img
#set epocinit=iplib
#model small jpi
#compile %main
#link %Smain
in which the only difference from p_hello.pr is that references to p_hello have changed into main.
Any batch file that invokes unnamed.pr has to set the value of smain as a parameter to tsc. For example,
tsc /m unnamed.pr /smain=%1
with the TopSpeed /s construct being used to set the value of main to the variable passed into the batch
file.
A batch file for test compilation
A programmers text editor usually has some means to compile or "test compile" a source file, from inside
the editor. Many programmers find this a considerable boost to productivity.
For example, Brief supports compilation on the ALT-F10 hot key, with the way the compilation is done
being determined by an MS-DOS environment variable:
e = during autoexec.bat (or a batch file called therein), set the value of bcc, eg to !"cc.bat %s"
e the effect of ALT-F10 while editing a .c file would then be to run the batch file cc.bat, passing the
basic name of the file (ie less the path and extension) into the batch file
e the leading exclamation mark specifies that compiler warnings should be reported, as well as
errors.
3-6
3 BUILDING AN APPLICATION
The TopSpeed ts integrated development environment naturally possesses an equivalent mechanism, but
some users may prefer to use an independent text editor.
Accordingly, one suggestion is that there should be a file cc.bat in the local directory (or in the path), with
the following contents (or equivalent):
tsc %1.c /fpunnamed
The meaning of the /fp construct is that the specified project file should be used (in this case,
unnamed.pr).
Given that there is no /m in this command (nor any /1), the specified project file is invoked in so-called
"compile" mode: nominated files are compiled, without any files being linked. Further, the compilation
always takes place, without any calculation of whether an object file is already "up-to-date".
Once all the required C source files in a project have been successfully compiled, the programmer can exit
the editor, and then "make" the project in the normal way:
e no time will be wasted in recompiling files unnecessarily
e a.img file will be produced (if the make is successful).
The cc. bat file used for test compilation could be accompanied by a make.bat file that invokes the project
file in "make" mode.
Some complications
There are a couple of shortcomings with the above batch file cc. bat:
e it takes no account of whether files should be compiled with full debug information
¢ it takes no account of a possible specialised .pr file: the project file unnamed.pr is hard-wired.
It does not take too much imagination to come up with a more general scheme - as is embodied in the
batch files cc.bat and make.bat actually shipped with the demo files p_hello.c etc:
e atest should be made for the existence of a project file with name 31. pr
e attention should be paid to the value of an environment variable for whether to generate full
debugging information.
The batch files supplied assume that the required debug status is stored in an environment variable
%4pivids. This should have one of the values v2 (for full debug information) or vo (for no debug
information). However, cc.bat and make.bat each call a subsidiary batch file, checkvid.bat, which ensures
that %jpivias does indeed exist and has one of these values.
The value of s jpivids is itself expected to be set up by calling the final batch file in the suite: vid.bat.
Typing
vid on
at the MS-DOS command line has the effect of setting sjpivids to v2, whereas typing
vid off
sets $jpivids to vo. Typing via by itself echoes the current vid setting.
3-7
GENERAL PROGRAMMING MANUAL
The contents of these four batch files are as follows:
(vid.bat)
@echo off
goto X%1X
:Xv0X
:Xoff£X
set jpivid=v0
echo VID is now OFF
goto :end
:Xv2X
:XonX
set jpivid=v2
echo VID is now ON
goto :end
2XX
call checkvid
goto Sjpivid%
:v0
echo VID is OFF
goto end
:v2
echo VID is ON
send
(checkvid.bat)
@if not "Sjpivids"=="v2" set jpivid=v0
(co batt)
@echo off
call checkvid
if exist %1.pr goto custom
tsc %1.c /fpunnamed /%jpivids
goto end
:custom
tsc %l.c /fp%1 /%jpivids
send
(make.bat:)
@echo off
call checkvid
if exist %1.pr goto custom
tsc /m unnamed.pr /smain=%1 /%jpivid%
goto end
:custom
tse /m %1.pr /smain=%1 /%jpivid%
send
Naturally, there is considerable scope for further personalisation and enhancement of these batch files, if
desired.
One final refinement would be to use the MS-DOS prompt command to change the prompt to reflect the
current value of vid. For example,
prompt $p_%jpivid%s$sg
(The reason it is generally important to keep track of whether full debugging information is being
generated is that significantly larger .img programs can result in this case.)
TSC versus TSCX
All the examples of compiling and linking that have been given so far use the TopSpeed tsc command.
This command does not make use of expanded memory and may cause problems, particularly when
linking large applications.
Most of the batch files supplied with the SDK to compile, link or make executables use the tsc version. If
this causes difficulties on your PC, you may find that replacing tsc with tscx (which uses expanded
memory) in these batch files will cure the problem.
3-8
3 BUILDING AN APPLICATION
More complicated programming setups
The remainder of this chapter makes no mention of programming technique or programming concepts
within the SIBO SDK system (see the later chapter Fundamental Programming Guidelines for that).
Rather, it continues to explain more details of the mechanics of building applications of various sorts.
Simple PLIB examples
The following four programs all use the default project file, unnamed.pr, and each consist of only one
source module:
p_search searches a specified text file for a given piece of text
p_prndir prints specified directory listings to the screen
p_dlist lists all current "devices" (ie local and remote disk drives)
Pp_comp compares two specified files, to see if they match.
For example, to build a version of p_dlist.img suitable for source-level debugging, just type
vid on
make p_dlist
To exit any of these programs which repeatedly request user input, simply press ENTER on an empty
input line.
Note: these programs are all restricted to so-called console i/o:
e no attractive graphics
e limited support for the user editing data entered previously.
Additionally, they pay no attention to the actual size of the screen on individual SIBO computers. Whilst
the data they display fits well enough on the large screen of MC computers, the display is less suited to the
smaller screens of HC or Series3 computers. Simple modifications can make amends in this last regard.
But for enhanced graphics output, use of Window Server functions is needed.
Finally, these programs are all single-threaded, ie each has only one event source (the keyboard). At the
same time, they contain no asynchronous i/o. (The vital topics of multi-threaded programming and
asynchronous i/o are two of the central themes of the chapter Fundamental Programming Guidelines.)
But despite their limitations, these four programs will hopefully be found useful for the purpose of
acquiring familiarity with .pr project files and with the SIBO SDK system generally. There is no need to
worry unduly over their detailed content; however, taking the time to build them and then improve them
could well turn out a very rewarding exercise (eg in making the transition from CLIB to PLIB).
Multi-file programs
For a program with more than one source file, the corresponding .pr needs but a slight modification.
For example, suppose a program triple has three source files: triple.c itself, utils].c and utils2.c. A
suitable project file triple.pr would be
system epoc img
set epocinit=iplib
model small jpi
compile triple
compile utils1l
compile utils2
link triple
The effect of the final #1ink statement is actually as follows:
e link together all the files listed with #compile statements
e link also the relevant startup module and standard libraries
3-9
GENERAL PROGRAMMING MANUAL
e link also any object files or libraries specified by any #pragma link statements (see below for
examples)
e give the final executable the name specified in the #1ink statement.
Note in particular there is no need for the name specified by the #1ink statement to match the name of the
.pr file, nor the name of any of the individual files linked together.
Graphics programs
Programs which interact directly with the Window Server can produce a large variety of impressive
graphics effects - icons and bitmaps, shapes and areas, mixed fonts and styles, scrolling and animation,
information messages and alerts, and so on.
These programs can operate with .pr files of exactly the same form as described earlier in this chapter. For
example, the file unnamed.pr can continue to be used, unchanged, for any simple single-module Window
Server program. Parts of the Window Server library, wlib.lib, are automatically linked in as required,
without any change being required in the .pr file: there is no need to ask for wlib.lib explicitly.
The source modules will, of course, have to change in the following aspects:
e calls to Window Server functions gxxx or wxxx will be included
e the Window Server header file wlib.h will have to be #included.
For more details, including some introductory Window Server programs of the "Hello World" variety, see
the Window Server Reference manual.
HWIF programs
Developers writing for the Series3 can take advantage of the additional menu and dialog functionality
(amongst other features) of the HWIF library, to create applications very similar to those built into the rom
of the Series3.
See the Programming in HWIF manual for full details, including a suite of example programs.
Project files for these programs need to include the line
#pragma link (hwif.lib)
since the HWIF library is not one of those that are automatically searched at link time.
Customised libraries
Developers may wish to collect various utility routines, or other subsets of code, into their own libraries,
which can in due course be linked into different programs. Possibly, developers may wish to distribute
their libraries in object form (./ib files), and not in source form. In such a case, there is likely to be at least
two different .pr files: one controlling the creation of the .lib file, and one that, later, joins the ./ib file into
a required application program.
For example, suppose that modules utils/.c and utils2.c are to be compiled and linked into a library called
utils.lib. This can be accomplished by means of the following project file:
#system epoc img
#set epocinit=iplib
#model small jpi
#compile utilsl
#compile utils2
#dolink utils.lib
Note the following points:
e the command #dolink is used rather than #1ink, to stop the TopSpeed system attempting to link
in a startup object too (not to mention other standard libraries)
e the extension .1ib explicitly given overrides the default .img that would otherwise be assumed
on account of the statement #system epoc img.
3-10
3 BUILDING AN APPLICATION
A project file to produce an application tutils, say, that made use of functionality in utils.lib, could then be
as follows:
#system epoc img
#set epocinit=iplib
#model small jpi
#compile tutils
#pragma link (utils.1lib)
#link tutils
with utils.lib being searched for along the path specified in the redirection file ts.red.
Applications containing assembler as well as C
In principle, it is perfectly possible for an application to include assembler source modules, as well as
modules written in C.
For example, if an application contains two source files, cfile.c written in C and afile.a written in
assembler, the following could appear in the project file:
#compile cfile
#compile afile
The TopSpeed system will automatically run the appropriate "compiler" for each specified type of file - ie
compiling the .c file and assembling the .a file.
However, programmers should note that there are various rules that must be adhered to in writing
assembler modules for Epoc programs. See the /ntroduction chapter of the PLIB Reference manual in the
first instance.
Note: the TopSpeed system will give an error message, and terminate, if there are two possible files each
candidates as the source for of a #compile statement - for example, if the files cfile.a and cfile.c both exist
in a directory. As another example, if a directory contains files query.c and query.rc, the statement
#compile query will again result in an error - since the TopSpeed system regards the .rc file as a possible
source file too. All these cases can be circumvented by giving the extension explicitly in the #command
statement - eg #compile query.c.
Other advanced use of the project file system
The TopSpeed documentation describes many possible ways to exercise further control over the process of
building program files.
One general piece of advice should, however, be borne in mind: while learning to program within the
SIBO SDK system, please accept the default configuration proposed by Psion. Only attempt to refine this
configuration once your program is already clearly working. Otherwise, it may prove difficult to determine
whether some unexpected program behaviour is due to a coding mistake, or to some unexpected side-
effect of a proposed "optimisation" of the build configuration.
In any case, optimisations resulting from careful choices of PLIB or WLIB (etc) functions, are likely to
prove more significant than any that can easily be achieved by tweaking the SIBO version of the
TopSpeed build configuration.
It is also generally a bad idea to ignore warnings from the compiler and linker (except where explicitly
mentioned in the SDK manuals). Rather than discounting these warnings as "quirks" of the system, they
should all be analysed and dealt with. In particular, don't be too hasty to disable "inconvenient" compiler
warnings.
Note that the SIBO SDK build configuration is actually defined in two different parts:
e in the file tsprj.txt which has to be "compiled" (using tscfg) before being used
e in the file stdepoc.h which is always the first include file in any source module.
As mentioned in the chapter on /nstallation, the file tsprj.txt released as part of the SIBO SDK modifies
and extends the one released by Clarion themselves, by adding in details specific to the SIBO SDK
system.
GENERAL PROGRAMMING MANUAL
Greater control over the image file created
This section explains some of the SIBO add-ons to the TopSpeed project file build system. It also covers
standalone use of the tools edump.exe, emake.exe and eremake.exe:
e edump.exe provides key information about the contents of an image file
e emake.exe is the underlying tool which creates image files
e eremake.exe can be used to alter some of the "additional" contents of image files.
Priority, minimum heap, and version number
Three project file variables can be used to override various defaults otherwise used when a .img file is
created:
sversion sets the version number of the .img file, which otherwise defaults to 0x100f
spriority sets the initial priority of the program, which otherwise defaults to 0x80
sheapsize sets the initial and minimum heap of the application, which otherwise defaults
to 0x80.
The application version number can be read by various pieces of software, for example the Application
Info command of the System application on MC computers. For more about legal version numbers, see the
section on p_version in the PLIB Reference manual.
The initial process priority may occasionally need to be specified explicitly, eg for an application that is
part of a suite of cooperating applications. See the section on p_setpri in the PLIB Reference manual and
also the section Priority changing in the chapter General Window Server Functions in the Window Server
Reference manual.
The value of sheapsize is the one that applications are most likely to wish to alter, since this has
significance for error handling (see the chapter Fundamental Programming Guidelines later in this
manual):
e the value of sheapsize is in paragraphs, eg 0x80 means 0x800 bytes ie 2 Kbytes
e the operating system will refuse to start an instance of the application if this amount of free heap
space cannot be found for it
e once started, the application will never have its heap shrunk below this value.
The default values for these variables can be overridden in either of two ways:
e aline such as #set heapsize=0x180 can be added into the project file
e the parameter /sheapsize=0x180 can be added to the end of the tsc command invoking the
project file (this is evidently the same syntax as in the /smain=%1 in the supplied batch file
make.bat).
Use of edump.exe
The tool edump.exe can be used to verify the values of the above three variables (amongst others) for a
specified .img file. For example, typing edump p_hello results in output such as
EDump V2.02F (03/10/90) Copyright (C) Psion PLC 1989
LOC: :D:\SIBOSDK\DEMO\P_HELLO.IMG IMAGE file data
Image version = 200F
Code Segment = 01D0 (bytes)
Initial IP = 0000
Stack = 1000 (bytes)
Data = 0040 (bytes)
Heap = 0800 (bytes)
Data Segment = 1840 (bytes)
Initialized data = 0030 (bytes)
Code checksum = DA14
Data checksum = OBF7
Code Version = 100F
Priority = 0080
Header size = 0040 (bytes)
Dyl count = 0000
Dyl table offset = 00000000
Image file size = 00000240 (bytes)
where the default values of "Heap", "Code version", and "Priority" can all be seen.
3-12
3 BUILDING AN APPLICATION
Deleting p_hello.img and rebuilding it via the command
tsc /m p_hello /sversion=0x110b
before running edump again yields identical output, except that the "Code version" line changes.
Differences between .app files and .img files
Strictly speaking, there is no real difference between image files with extension .img and those with
extension .app. For example, although the System applications on the MC and on the Series3 usually
expect to install .app files, they will also, if requested, install suitable .img files.
However, by convention a .app file contains one or more extra so-called add-files embedded within it, in
addition to the core .img file itself. These files may include:
e a.pic file providing the icon for the application
e a.rsc or .rzc file providing the resource file for the application
e a.shd file providing the shell data for the application (only for Series3 applications).
As such, a .app file is simply a .img file which has some associated files conveniently built into it. A
significant advantage of a .app file is that a user cannot inadvertently sabotage the operation of the
program by copying the .img file itself from one drive to another, but neglecting to copy one of the
associated files.
Add-files can be added into the .img file automatically, via the operation of emake.exe, at the time the
.img file is itself created. What controls the set of add-files used (if any) is the presence or absence of a
suitably named add-file list (.afl) file.
Add-file lists
An add-file list (afl) file is a text file containing from one to four filenames. For example, the contents of
a file tele.afl could be:
tele.pic
tele.rsc
tele.shd
When any .pr project file is invoked that leads to the building of tele.img, the existence of a file tele.afl is
checked for. If such a file is found, the files listed therein are combined with the core .img file to form a
larger .img file as output. By convention, .img files that contain embedded add-files are renamed to .app
files (though no such renaming takes place automatically).
The inclusion of these embedded files can be confirmed by running the tool edump.exe as follows. Typing
edump tele.app might yield
EDump V2.02F (03/10/90) Copyright (C) Psion PLC 1989
LOC: :E:\SIBOSDK\HWDEMO\TELE.APP IMAGE file data
Image version = 200F
Code Segment = 1EDO (bytes)
Initial IP = 0000
Stack = 1000 (bytes)
Data = 0690 (bytes)
Heap = 0800 (bytes)
Data Segment = 1E90 (bytes)
Initialized data = 03C0 (bytes)
Code checksum = 33DF
Data checksum = 3033
Code Version = 100F
Priority = 0080
Header size = OOFO (bytes)
Add 1 offset,len = 0040 (bytes), 0074 (bytes)
Add 2 offset,len = 00C0O (bytes), 0000 (bytes)
Add 3 offset,len = 00C0O (bytes), O02E (bytes)
Dyl count = 0000
Dyl table offset = 00000000
Image file size = 00002380 (bytes)
For the moment, the interesting data here is contained in the three lines of the form:
Add n offset,len
3-13
GENERAL PROGRAMMING MANUAL
These give the offsets within the combined .app file to the embedded add-files. In this case, three of the
add-file slots are used; in general, any number from zero to four could be used.
For more discussion about various possible add-files, see the Series 3/3a Programming Guide.
A similar technique, using a DYL file list in a file with a .dfl extension, may be used to build any number
of dynamic library (DYL) files into an application. This topic is described in more detail in the Object
Oriented Programming Guide.
Changing the set of add-files in an image
The tool eremake.exe can be used to change the set of add-files built into an image file, without needing to
run the TopSpeed project system again, and without needing to have any files to hand apart from the
original image file. That is, image files can be remade with new add-file contents, without the earlier .exe,
.obj, or .c files being present.
One common use of eremake is to convert eg an English language version of an application into a
specified alternative language version. See the chapter Resource Files in the Additional System
Information manual for a general discussion of applications that can run in more than one language.
For example, suppose that an application Query has all its language text isolated in a resource file
query.rzc, which is one of the original add-files for the application. More precisely, suppose that the
original contents of guery.afl are
query.pic
query.rzc
query.shd
Suppose further that a French version of the resource file is produced: frquery.rzc, say. Then a new .afl
list should be created, frquery.afl say:
query.pic
frquery.rzc
query.shd
and eremake.exe should be invoked as follows:
eremake -afrquery -o..\french\query.app query.app
For a full list of possible parameters to eremake.exe, simply type eremake by itself. Note that eremake.exe
can be used to alter the priority, minimum heap, or version number of an image file.
In the above case, the "output" file ..\french\query.app is created by "remaking" query.app with add-files
listed in frquery.afl.
In this example, the files guery.pic and query.shd from the original version are also used for the French
version. Clearly, these could be changed too, if required.
Further uses of emake.exe
The actual conversion from .exe form into .img form is handled by the Psion-proprietary tool emake.exe,
according to the command
#run "emake —-b %af1l% -otname% -s -v%version% -p%priority% -hsheapsize% -%epoctype%
Sname%S.exe"
in the file tsprj.txt.
For a full list of possible parameters to emake.exe, just type emake by itself.
Note in particular that emake can produce other forms of final output, apart from .img files. This is
determined by the sepoctype variable in the above command, which by default takes the value t1. Other
possible values are t2 through +4:
tl makes an image file, with characteristic extension .img
t2 makes a logical device driver, with characteristic extension .ldd
t3 makes a physical device driver, with characteristic extension .pdd
t4 makes a dynamic library, with characteristic extension .dyl.
Logical and physical device drivers are further discussed in the Writing Device Drivers chapter in the
Additional System Information manual. Dynamic libraries are discussed in the Object Oriented
Programming chapter of the PLIB Reference manual, and in the Object Oriented Programming Guide.
3-14
CHAPTER 4
NOTES ON CLIB
This chapter provides some additional information about the implementation of CLIB, the version of the
TopSpeed C library for the Epoc operating system. It need be read only by developers who wish to use
CLIB (for example, to port existing code from another program). Developers who stick to PLIB can skip
this chapter entirely.
The difference between PLIB and CLIB is explained in the previous chapter.
Functions missing from the MS-DOS Jpi C library
The following functions are not included in the EPOC version of CLIB because they rely on the IBM PC
hardware, far or huge pointers, or direct MS-DOS functions calls. For many of the missing function calls
there is an equivalent function or set of functions which may be called from either PLIB or WLIB.
absread
_arc
bdos
biosdisk
biosmemory
_bios_disk
_bios_memsize
_bios_timeofday
_clearscreen
ctrlbrk
delay
_dosbeginthread
_dosfreestack
dos creat
_dos_findnext
_dos_getdiskfree
_dos_getftime
_dos_keep
_dos_setblock
_dos_setfileattr
dos. setvect
_expand
execve
farcoreleft
farrealloc
_ffree
_fheapwalk
_fmsize
_frealloc
_getbkcolor
getcurdir
getdta
_getfillmask
_getlogcoord
getpsp
abswrite
at
bdosptr
biosequip
biosprint
_bios_equiplist
_bios_printer
Jochain intr
convertcoords
_cube
_directwrite
_dosendthread
_dos_allocmem
_dos_creatnew
_dos_freemem
_dos_getdrive
_dos_gettime
_dos_open
dos_setdate
_dos_setftime
_dos_write
execle
execvpe
farfree
fcalloc
_fheapchk
_floodfill
_FP_OFF
freemem
getcbrk
_getcurrentposition
getfat
_getimage
_getphyscoord
gettime
allocmem
Awaited
bioscom
bioskey
biostime
_bios_keybrd
_bios_serialcom
change
country
Delay
_displaycursor
dosexterr
ados_close
_dos_findfirst
_dos_getdate
_dos_getfileattr
_dos_getvect
dos read
_dos_setdrive
_dos_settime
_ellipse
execlpe
farcalloc
farmalloc
_fexpand
_fheapset
_fmalloc
_FP_SEG
geninterrupt
_getcolor
getdfree
getfatd
_getlinestyle
_getpixel
gettext
4-1
GENERAL PROGRAMMING MANUAL
_gettextcolor gettextinfo _gettextposition
getvect getverify _getvideoconfig
halloc _harderr _hardresume
_hardretn hfree hide
highvideo hmemccpy hmemchr
hmemcmp hmemcpy hmemicmp
hmemset hrealloc info
Init intdos intdosx
ioctl keep _lineto
Lock locking lowvideo
mktemp MK_FP movedata
movetext _moveto ncalloc_
_ms_cursor
_ms_getpage
_ms_getsensitivity
_ms_reset
_ms_setdouble
_ms_setmickeys
_ms_setrange
_ms_driversize
_ms_getpress
_ms_getstatus
_ms_restoredriver
_ms_setgraphcursor
_ms_setpage
_ms_setsensitivity
_ms_getmotion
_ms_getrelease
_ms_lightpen
_ms_savedriver
_ms_setinterrupt
_ms_setposition
_ms_settextcursor
_ms_swapinterrupt _ms_updatescreen normvideo
nosound Notify obsucredat
_outtext palettecolor palettecolorused
paletteopen parsfnm peek
peekb _pie poke
pokeb _polygon putbeneath
_putimage putontop puttext
randbrd randbwr readbufferln
_rectangle _remapallpallete _remappallete
_selectpalette SEND _setactivepage
_stbkcolor setblock setcbrk
_setcliprgn _setcolor setdta
setftime _setfillmask setframe
_setlinestyle setlogorg setpalette
setpalettecolor _setpixel _settextcolor
_settextposition _settextwindow settitle
setvect setverify _setvideomode
_setviewport _setvsualpage snapshot
sound spawnle spawnlpe
spawnve spawnvpe StartProcess
StartScheduler StopProcess StopScheduler
tempnam textattr textbackground
textcolor textmode tmpnam
top Unlock use
used WAIT window
windowclose windowopen _wrapon
_wrbufferlin
int86x
int 86x is implemented by exactly the same code as int 86, ie the values in the segment registers struct are
ignored. This is because in the pure small model ps=zs=ss and hence there is never any need to change
the values in the segment registers.
intr
As for int86x above, the values in the segment registers are ignored.
File handle conversion routine
void *getRealHandle(int handle);
Returns a PLIB file handle, given a CLIB file handle. Returns nut if the handle is not currently
allocated.
4-2
4 NOTES ON CLIB
The console channel
Programs built with the CLIB start-up module automatically open a console channel. The channel is also
automatically assigned to stdin, stdout and stderr, unless they have been redirected.
It may prove useful to get the actual PLIB handle for the console channel. This can be achieved by either
calling getRealHandle(fileno(stderr)) or by referencing the global _winHandle as follows:
extern void *winHandle;
You can prevent the automatic opening of a console channel by defining the function p_xwind in your
code, as in the following example:
extern void *winHandle;
void p_xwind (void)
{
winHandle=(void *)1;
}
int main (void)
{
return (0);
}
You should ignore the warning, given during the linking of your program, that the symbol _p_xwind is
duplicated.
If you use this technique your program should not, of course, make any reference to stdin, stdout or
stderr, unless you have redirected them. Setting winHandle to | (an illegal value for a handle) will
guarantee that any such reference will fail with a panic.
MS-DOS file names
Applications written for the Epoc O/S should in general avoid making any assumptions about file names
(see the Files chapter in the Plib Reference manual) and should use p_fparse and p_chdir to manipulate
file names and navigate directory paths. However the Loc: : file system on all SIBO machines is totally
MS-DOS compatible. Thus CLIB supports the TopSpeed STD C library functions findfirst, findnext,
getcwd, etc which rely on MS-DOS naming conventions. However if an attempt is made to use these
functions on other filing systems, such as rem: :, the routines will return an error.
Floating point emulator
As the SIBO architecture does not allow for an 8087 maths coprocessor, all floating point is performed by
software emulation of the 8087.
Normally the emulator code would be linked in with your program for MS-DOS exe's, but under Epoc O/S
the emulator is provided by an LDD called SYS$8087.LDD in \sibosdk\lib\. Any programs requiring the
emulator will automatically load the LDD and free it again when it is no longer required. This has the
advantage of saving about 8K of code from your program and allows the LDD to be shared by multiple
processes.
The C startup module (see r_emul.a) will look for the LDD in the directory in which your program was
executed. If it is not found the it will use the environment variable ems (remember to use capitals for the
name as environment variables in Epoc O/S are case sensitive).
Panic 80
An application which terminates with a "panic 80" before it even starts has almost certainly failed to
locate SYS$8087.LDD. There are three steps that can be taken to avoid the panic:
move a copy of the LDD into the directory where the program will execute from
set the environment variable ems appropriately (eg using a short program)
rewrite the program so that it does not require the use of the LDD.
See the Floating Point chapter of the Plib Reference manual for some more details.
GENERAL PROGRAMMING MANUAL
Note that floating point instructions can easily be generated unexpectedly (eg to push or pop floating point
registers) if the recommended build configuration pragmas are "improved" in any way - resulting in panic
80s "out of the blue". If in doubt, inspect the object code using the SIBO Debugger (or use the TopSpeed
disassembler, tsda).
Building the CLIB library and header objects
To build the CLIB library you must have purchased the Professional variant of the SIBO SDK. This
version includes the C Library Source Kit and the corresponding EPOC CLIB Library Source. Since some
of the EPOC CLIB source modules are written in C++, you will also need to have separately purchased
TopSpeed C++.
Simply startup TS in the SRC directory of SIBOSDK. Select CLIB as the project file and then MAKE the
project. The libraries and objects will be generated in the SRC directory and need to be copied into the LIB
directory. There is a batch file IVST.BAT which will do this for you.
Note that, in addition to the CLIB library, there is also an RLIB component. This contains elements that
are common between CLIB and PLIB.
The source code modules for PLIB and WLIB are currently in Turbo Assembler format and are not
buildable using the TopSpeed assembler. They have not been included in this release of the SDK. The vast
majority in any case are simple shells which just juggle registers.
Cautionary note
It is advisable to tread cautiously when changing the library, and under no circumstances should the
pragmas be changed in either TSPRJ.TXT or STDEPOC.H.
CHAPTER 5
FUNDAMENTAL PROGRAMMING GUIDE-LINES
Introduction
In some ways, this chapter may be viewed as being among the most important in the whole of the SDK.
Follow the Guide-lines here and your programs have a good chance of possessing the following qualities:
user responsiveness users will not be kept waiting impatiently if they want to interact
with an application whilst it is busy - eg to cancel some operation
part-way completed
error robustness data will not suddenly be lost when run-time errors occur such as
shortage of system memory (bear in mind that such errors are
almost inevitable on a multi-tasking computer, when the system
memory can become unexpectedly used up by other applications)
architectural robustness changes in user requirements or in implementation tactics should
not lead to the whole code becoming unmaintainable.
Of course, practice of standard general programming principles - such as modular programming, data
hiding, egoless programming, designing prior to coding (not to mention adequate requirements
specification prior to design), and a structured approach to validation and testing - all have important
roles to play in the production of quality SIBO applications. But there are additional programming
principles that have particular importance within the SIBO environment, and it is these that this chapter
addresses. These principles should complement the ones good programmers from other backgrounds
already practice.
Incidentally, just as the merits of the above-mentioned "standard" programming principles are not always
immediately obvious (data hiding is a good example), but rather have to be learned, so it is with some of
the principles outlined in this chapter. Their importance has become clear to the programming team at
Psion only gradually, over several years experience. It is understandable that experienced programmers
from other backgrounds may wish to rush over this chapter, believing its contents to be inapplicable to
them, but that would almost certainly be a mistake.
Again, there is of course no substitute for a wide-ranging knowledge of which library functions are
available. Developers wishing to produce quality applications will naturally have to spend some
considerable time familiarising themselves with the contents of the reference manuals within the SDK, so
as to be able to spot the right function to use in any particular coding situation. This knowledge cannot be
acquired simply by assenting to the set of programming principles covered in this chapter. But conversely,
wide knowledge of the set of available function calls is insufficient, by itself, to produce programs with the
traits listed at the start of this chapter.
Other related documentation
Applications which are multi-lingual (eg which present English language messages on an English
language computer, French language messages on a French language computer, and so on) pose their own
set of programming problems. These are discussed in the course of the Resource Files chapter of the
Additional System Information manual. (Resource files are a tool of particular importance for multi-
lingual applications.) Note that these problems are shared between applications which are actually multi-
lingual and those that are potentially multi-lingual: it is better to design support for multi-linguality in
from the start, than trying to add it on afterwards.
GENERAL PROGRAMMING MANUAL
Graphics programming has its own particular set of do's and dont's, in order that (for example) flicker-
free redrawing and automated screen update take place. These are discussed at various places in the SDK,
for example, in the Window Server Reference manual, and also in the Programming in HWIF manual.
Avoidance of excessive RAM usage, and also of "stack windup", are also of considerable importance
within the SIBO architecture. Specific advice on these regards are scattered throughout the SDK; the
present brief note simply has the purpose of drawing attention to the topic.
Finally, the task of designing the user interface (menus, dialogs, and so on) is another that poses its own
special problems - programmers who labour under the misapprehension that user interfaces are "easy" to
design almost invariably produce poor user interfaces. Guide-lines on these matters may be found within
the object oriented documentation parts of the SDK.
The source code for the examples
The bulk of this chapter consists of a lengthy analysis of a suite of example programs. These build in four
stages - Events, Events2, Events3, and Events4 - to a program that can simultaneously process:
e keyboard input
e the expiry of a timer
e reports of the completion of a sub-process
e data received from a serial port
whilst all the time carrying on some compute-bound activity "in background"
At any given moment, the program cannot predict which of its five possible "event sources" will be the
next to require CPU. As such, the program amply demonstrates the three vital themes of multi-
threadedness, asynchronous i/o, and yielding CPU:
e = multi-threadedness means that more than one set of activity takes place simultaneously within
the program, with each different flow of activity being handled by its own "thread" of code
e¢ — asynchronous i/o means that the queuing of a read request (or write request) on an i/o channel is
separated in code from the completion of that request
e yielding CPU means that lengthy calculations are broken down into subcomponents that are
executed separately, with gaps in between so that some more urgent event source can be attended
to, if necessary.
Although the program itself has limited practical use, it demonstrates the basic architectural principles
that all sophisticated Epoc programs are bound to have to consider.
The source code for these four stages of Events can be installed from disc (SIBOSDK\DEMO), together
with that of an associated "sub-process" application, Subproc. Readers are urged to take the time to build
these applications and to experiment with them, in particular trying out some of the suggestions made in
this chapter for how these programs could be modified.
User interface
The user interface of these example programs has deliberately been kept spartan. All screen drawing is to
a "console terminal" that is 25 characters wide and 9 characters deep.
These decisions have the advantage that:
e the program works equally well on all different SIBO computers (even on the HC, where the
screen is smallest)
¢ considerations about interfacing with the Window Server - necessary in order to achieve more
graphically appealing displays - can be postponed while focusing instead on multi-threadedness,
asynchronous i/o, and yielding CPU.
Various examples of Window Server programs demonstrating multi-threadedness (et al) can be found
within the SDK. For example, the Writing Software for the HC chapter of the HC Programming Guide
discusses an application called Gauge, that will in fact run happily (with only minor adjustments) on a
Series 3. Again, the Programming in HWIF manual contains a large set of example programs, all of
which interface with the Window Server.
5-2
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
A first look at multiple event sources
The main routine in Events is as follows (the individual calls made, including the Plib calls, are discussed
below):
GLDEF_C VOID main(VOID)
{
OpenConsole();
DrawBorder() ;
OpenTimer () ;
timint=10;
QueueTimer ();
QueueKey () ;
FOREVER
{
p_iowait ();
if (keystat!=E_FILE_PENDING)
{
if (key. keycode==W_KEY_ESCAPE)
p_exit (0);
if (key.keycode>='1' && key.keycode<='9')
SetTimInt (2* (key. keycode-'0'));
QueueKey () ;
}
else if (timstat!=E_FILE_PENDING)
{
if (counter++==MAX_COUNT)
counter=1;
DisplayCount ();
QueueTimer ();
}
}
Schematically, the code is as follows:
GLDEF_C VOID main(VOID)
{
INITIALISE ();
QueueTimer () ;
QueueKey () ;
FOREVER
{
p_iowait ();
if (keystat!=E_FILE_PENDING)
{
PROCESS_KEY () ;
QueueKey () ;
}
else if (timstat!=E_FILE_PENDING)
{
PROCESS_TIMER() ;
QueueTimer();
}
}
in which it is clear that the program has two event sources - keypresses and the expiry of a timer.
What the program actually does is to update a numeric count (displayed on the screen) regularly, on a
timer. The rate at which the timer fires is determined by which keys the user presses:
e it starts off firing once every second
e if the user presses the 2 key, the timer changes to firing once every 2/5 of a second (so that the
numbers tick over more rapidly)
e if the user presses the 9 key, the timer changes to firing once every 9/5 of a second (so that the
numbers tick over more slowly)
GENERAL PROGRAMMING MANUAL
and so on. Further, every time a numeric key is pressed, the existing timer request is cancelled, and the
timer reset - so that pressing repeatedly on keys such as 8 and 9 can have the effect of "stalling" the
counter altogether.
The program exits in response to the ESC key being pressed. All other keys are ignored.
Remarks on timers
One simple approach to programming with delays is to call a function such as p_sleep, which effectively
suspends the application for a specified amount of time.
This approach could be adopted in Events, were it not for the fact that, when the application is suspended,
it cannot respond to a keypress. The keypress will only be received when the application "wakens up"
again.
Now this might not be too much of a loss for very small time delays, but it is of course unacceptable for
longer delays. For example, a program might wish to perform some housekeeping or maintenance once
every twenty four hours - or simply update the display in a dialog once every two seconds, whilst allowing
the user to cancel out of the dialog at any time. That is, whilst routines such as p_sleep certainly have a
role to play, they cannot handle all timer requirements in programs.
A next possible approach would be to design a routine which, when called, suspended the application until
the specified time elapsed or a keypress is received - whichever happens first. Indeed, there is a call with
just this specification in the Opl programming language (pause when used with a negative time delay).
Actually, this routine would satisfy the requirements of Events perfectly. However, it has the severe
drawback of lack of architectural openness. That is, suppose the application has to be modified at a later
date, to be able to respond to another sort of event source - eg the arrival of data at a serial port, or an
interprocess message from another application. Alternatively, the application may need to carry on some
continuous activity, whilst waiting for the timer to expire. In either case, a more general approach is
required.
This more general approach is the mechanism by which the queuing of a timer is separated, in code, from
the completion of the timer. In the above code, the timer is queued by the call queueTimer, whereas the
completion of the timer occurs within the p_iowait call. (See later for the details.)
This kind of code separation between the queuing of a request and the completion of the request is known
as asynchronous - because there is no automatic synchronisation of the two phases (as occurs, for
example, in a call such as p_sleep).
Remarks on keypresses
A routine such as p_getch is to keypresses what p_sleep is to timers - in both cases, the program is
effectively suspended until the request is completely satisfied.
Just as there is a place for p_sleep in programming, so also there is a place for p_getch. However, each is
generally inappropriate when there is more than one event source current - as here.
So the call p_getch is split into two parts: the request for a keypress to be delivered, inside the call
Queuekey, and the delivery of the keypress - inside p_iowait.
More on p_iowait
The call p_iowait is where the application gets suspended, while it waits for the completion of some or
other event. But whilst p_sleep only returns when the associated timer expires, and p_getch only returns
when a keypress is delivered, p_iowait returns when any known event has completed.
Of course, sometimes the application won't get suspended at all when it calls p_iowait - on account of a
queued request already having completed. For example, during the time Events is inside the code
PROCESS_TIMER, the user may have pressed a key, in which case the subsequent call to p_iowait will
return immediately (not that the application needs to worry about this, however).
The way p_iowait works is by consulting the value of the i/o semaphore for the process. Each process has
an i/o semaphore assigned to it. These semaphores are maintained in the private data space of the
operating system.
An i/o semaphore commonly has its value changed in either of two ways:
e it is decremented whenever a call to p_iowait is made
e it is incremented whenever some piece of software "signals" the application.
5-4
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
For example, whenever a timer expires, the operating system timer device signals the application which
owns the timer. Again, whenever the Window Server delivers a keypress to an application, it signals that
application. In general, the completion of any i/o request always involves the application being signalled.
The i/o semaphore of an application initially has the value zero. A call to p_iowait only returns when the
i/o semaphore is non-negative. Given that the call to p_iowait starts by decrementing the semaphore, the
call will return only when "something has happened".
For more details about p_iowait and i/o semaphores in general, see the Plib Reference manual.
Note that the SIBO Debugger has a menu command (Process Status) which displays the value of the i/o
semaphore of a process (amongst other information). The Spy application discussed in the Series 3
Programming Guide has a similar feature, which allows the i/o semaphores of all different running
processes to be viewed simultaneously.
Status words: the other side of p_iowait
When a program returns from a call to p_sleep, it knows that it is a timer that has expired. Likewise,
when a program returns from a call to p_getch, it knows that a keypress has been delivered. However,
when a call to p_iowait returns, no such information is immediately available. All the application knows
at this point is that some event has completed - not which event.
In general, the task of determining which events are indeed ready to be processed involves two factors:
¢ knowing which event sources are active - having had requests made on them
e knowing which of this subset have completed their requests.
For the moment, the first of these points can be ignored (but see later), with attention given to the notion
of the status word of an asynchronous request:
e when the request is made, an address of a status word is specified (recall that a "word" is two
adjacent bytes)
e when the request is made, the value E_rFILE_PENDING gets written to this word
e when the request completes, a value other than &_FILE_PENDING is written to this word (the
actual value varying depending on the type of asynchronous request)
Writing to the status word takes place just before the i/o semaphore for the application is signalled. Both
these steps are integral to the SIBO mechanism of p_iowait.
All this explains the code in Events immediately after the call to p_iowait: the different status words are
polled in turn, in order to find one whose value is no longer E_FILE_PENDING.
Prioritisation of event sources
Note that the order in which the status words are polled implicitly prioritises the different event sources.
For it is possible for more than one asynchronous event to have completed; in this case, the first one of the
two polled will be the one which gets the first response.
Note in particular that the order in which events are processed need bear no direct relation to the order in
which the events actually completed. An event source lower down the priority listing can be "locked out"
by rapidly firing event sources higher in the listing. In fact, code can often be written which depends on
this prioritisation - so that a lower priority event source is only serviced when all higher priority event
sources have quietened down.
I/O devices in general
In this example, keypresses are delivered by the console device. Likewise, timer expiry is handled by the
timer device. The console device and the timer device are both instances of general so-called i/o devices,
all of which possess a common interface:
e before using an i/o device, an application has to open a channel to it
© once opened, various services can be requested via the channel
e these services can all in principle be requested either synchronously or asynchronously
e if an i/o device channel is no longer needed, the resources it consumes (eg memory) can be
released by closing the channel.
GENERAL PROGRAMMING MANUAL
Channels to i/o devices are opened by means of the p_open call, in which the 1/o device has to be specified
by name. Another parameter to the p_open call also defines where the handle of the channel will be
written.
The handle returned by p_open can then be used to request other services from the i/o device. It can also
be passed as a parameter to p_close, to close the channel down again.
The way synchronous requests are made, via an i/o channel, is to use a p_iow call (or a convenience
routine that layers over this). Asynchronous requests are made using a p_ioa (or p_ioc) call.
For example, the call to position the console cursor, inside the routine write in events.c, is as follows:
P_POINT pos;
WORD func;
pOS.xX=X;
Pos.y=y;
func=P_SCR_POSA;
p_iow4 (conH, P_FSET, &func, &pos) ;
This is a synchronous call because there is no point in calling it asynchronously: the effect of this call
(setting the cursor position) is always (virtually) immediate: there is no scope for any extended delay as it
is carried out.
On the other hand, the code for queuekKey is
LOCAL_C VOID QueueKey (VOID)
{
p_ioa4 (conH, P_FREAD, &keystat, &key) ;
}
which is clearly asynchronous. (The 'a' in "p_ioa" stands for asynchronous.)
By chance, it turns out that these two calls to p_ioa and p_iow have the same number of parameters. This,
however, is only the case because the P_FREAD request requires one less parameter than the P_FSET
request. In general, an asynchronous request always has one more parameter than the corresponding
synchronous request - namely the status word, whose address has to be passed in the asynchronous case.
For more on the p_io? functions (including the significance of the numeric suffices to the function
names), see the Plib Reference manual.
The console device
The Events application uses the console device - as opposed to just making calls like p_printf - for two
reasons:
e as discussed already, the console device supports an asynchronous version of p_getch
e the console device supports repositioning of the cursor position - which fact is relied upon heavily
in the application.
For a full specification of the console device, see the corresponding chapter in the //O Devices Reference
manual.
How to cancel a timer
The code inside cancelTimer merits some attention:
LOCAL_C VOID CancelTimer (VOID)
{
p_iow2 (timH, P_FCANCEL) ;
p_waitstat (&timstat) ;
}
First, the P_FCANCEL service is requested. This is itself a synchronous request, completing at once.
However, the way the generic service P_FCANCEL works in device drivers is never to retract the earlier
request, but rather to precipitate its completion. It cannot retract it in general because it may already have
completed by the time the p_FcANCEL request is made:
e if the request has already completed, the p_rcaNncEL does precisely nothing
e if the request is still outstanding, it is completed forthwith, with the value E_FILE_caANcEL being
written to the status word, and with the application being signalled (on account of the fact that
the earlier request has now completed, albeit precipitously).
5-6
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
In either case, the application will be signalled - either before the p_rcanczg , or after it. Accordingly, this
signal has to be "processed" (or "used up"). This is the purpose of the subsequent call to p_waitstat. For
more details about p_waitstat, see the Plib Reference manual.
Omitting to call p_waitstat after making a p_FCANCEL request is a common error. The result of this error
is that the next call to p_iowait will return at once, even though none of the remaining active event
sources is ready to deliver an event.
For more details about the timer device in general, see the chapter Time, Timers and Dates in the Plib
Reference manual.
Where to declare status words
On the subject of common programming errors in conjunction with asynchronous i/o, perhaps the most
common one has yet to be mentioned. This is the mistake of declaring status words on the stack of some
routine which will have returned long before the asynchronous request completes. The status word will
now be a piece of random data - perhaps on the stack of another routine - and random damage can ensue
when it is in due course written to.
Status words should always be declared either in static data (as in Events), or in a control block allocated
from the heap.
A first look at error handling
Every time a function call is written into a SIBO program, the programmer should consider the question:
could a run-time error occur in the middle of this function? And if so, what would happen?
Chief amongst these possible errors is lack of memory. This can occur in three different ways:
e the application has reached the limit of its 64k data segment
e the application is using less than 64k itself, but there is no system memory available for it to be
given more heap space
e another program with which the application is cooperating runs out of memory.
Other errors that need to be considered include:
e resources not being available because another application is already using them (eg serial port or
sound device driver, or even a file that is currently open by another application)
e disk-based errors such as disk full, disk corrupt, or disk removed
e the unexpected disappearance of the remote filing system (rem: :)
e comms failures such as serial overrun, parity error, or line failure.
These errors cannot be dismissed with the philosophy that, in an ideal world, they will not happen.
Instead, they can and will happen, despite the best endeavours of the programmer. SSDs becoming full up,
comms cables being removed, or a file already being open by another program, are all problems that arise
naturally in the operation of a SIBO computer.
Whatever the cause of a run-time error, applications should take every care that no data entered by the
user is lost. Another requirement - to avoid parts of memory being permanently tied up for no purpose - is
that partly assembled data constructs which cannot be completely assembled, owing to a run-time error at
a later stage, should be carefully disassembled again.
Error handling in Events
Looking at the source code in events.c, it is clear that three different types of error are considered:
e failure to open the timer device
e failure to open the console device
e failure to set the size of the console screen.
GENERAL PROGRAMMING MANUAL
None of the other function calls have any possibility of run-time error, as can be verified by considering
them all individually. (In fact, considering every call individually for possibilities of run-time error has to
be the norm when developing applications.)
It is worth considering the above three possible errors in a little more detail. For example, opening a timer
can fail for two reasons:
e lack of memory for the timer control block in the application data space
e lack of memory in the operating system dataspace for the real timer entry.
Now whilst an application may be able to ensure that the first possibility never arises - by means of setting
its minimum heap appropriately - it can never be sure of preventing the second case. The number of
timers allocated in operating system dataspace depends not on circumstances within the original
application, but rather on what other applications have done. If other applications running simultaneously
happen to make heavy use of timer resources, the operating system may not be able to set aside the one
timer channel requested by Events.
Should this occur, the code in openTimer and Check ensure that a suitable error message is passed back to
the user. The user can then take action to shut down some of the other applications running
simultaneously on the computer, before trying to start Events again.
The case of the channel to the console device is similar. This time, it is resources of (for example) the
Window Server which may be unable to meet the request made. Likewise when the console window is
sized (at which time various arrays or back-up bitmaps need to be allocated).
Fatal errors and non-fatal errors
The three possible errors in Events are all treated as being fatal: the application initialisation fails, so the
application terminates.
This kind of action makes good sense for errors during the initialisation of an application, but cannot on
the whole be tolerated for errors during the main phase of an application (ie after the initialisation is
complete). By this time, the user may well have committed some data into the application, which would be
lost if the application suddenly terminated.
In these cases, a retry philosophy is much more appropriate: the application cleans up any interim semi-
allocated resources, "rolls back" to its previous good state, and presents an error message informing the
user what has happened. It is up to the user to try to correct the error condition, and then re-initiate the
previous action.
When resources need to be tidied explicitly
It may be noted that there are no calls to p_close in events.c. These calls are unnecessary in this program,
because the channels are automatically closed, by the operating system, when the application exits.
This situation must be contrasted carefully with that when a resource (such as a channel to an i/o device)
is used transiently by an application. In this case, it must be freed as soon as it is no longer needed.
Inter-Process Communication Events2 and Subproc
Events2 extends the functionality of Events by supporting the facility to launch a sub-process. A sub-
process is automatically started during program initialisation, and once it has terminated, the user can
press ENTER to re-launch it again.
The sub-process mimics the carrying out of some extended activity. When it finishes, it signals the fact of
its completion to Events2, together with an "answer", which Events2 displays on the screen. This answer
has in fact been calculated from a parameter passed by Events2 to Subproc on the command line.
Subproc and Events2 therefore carry out a restricted form of inter-process communication, and thereby
illustrate some of the multi-tasking possibilities in writing software for SIBO computers.
A third event source
Events2 remains alert to the possibility of a signal from Subproc, even though it is busy responding to
timer events and keyboard events. Events2 manages this via a straightforward extension of the
architecture in Events: one more "event source" is added into the picture.
5-8
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
Thus there is one more status word - substat - and one more test in the main loop in main:
else if (substat!=E_FILE_PENDING)
Report Sub () ;
That is, whereas main used to poll up to two status words, on returning from a call to p_iowait, it now
polls up to three status words: subst at in addition to keystat and timstat.
However, this new event source differs from the previous two in that it is not an i/o device. There is no
p_ioa call to request notification from Subproc; rather, the corresponding "queue" call is p_1ogona.
In the line of code
p_logona (pid, &ésubstat) ;
the calling application (Events2) is requesting asynchronous notification of the eventual termination of the
process identified by pia. This notification consists of two parts (now familiar):
e avalue other than &_FILE_PENDING is written into substat
e the application is signalled (so that its i/o semaphore increments).
How Events2 passes data to Subproc
Events2 passes its original data to Subproc via the command line.
In any case like this, there has to be an agreement between the two processes as to the format of the
command line. Here, the protocol is established in the shared header file subproc.h, which defines the
following struct:
typedef struct
{
HANDLE pid;
VOID *poff;
ULONG data;
} SUBPROC_CL;
The members of this struct serve the following purposes:
pid identifies the process which launched Subproc (ie Events2)
poff an address within the dataspace of Events2 where Subproc should in due course write back
the "answer" it discovers
data _ the original seed data for Subproc to operate with.
The following code sets up this struct and creates and runs Subproc:
LOCAL_C VOID LaunchSub (VOID)
{
HANDLE pid;
SUBPROC_CL cl;
TEXT subname [P_FNAMESIZE];
p_fparse ("subproc.img",DatCommandPtr, &ésubname[0],0);
cl.pid=p_getpid();
cl.poff=(&answer) ;
cl.data=p_date();
if ((pid=p_execc (&subname[0],&cl,sizeof (cl) )) <0)
{
p_notifyerr(pid,"Failed to launch subprocess",0,0,0);
return;
}
p_logona (pid, &substat) ;
p_presume (pid) ;
}
The variable answer is a static. Clearly, it would be a significant error to include it on the stack of
LaunchSub, since this stack will have unwound before answer gets written to (by Subproc).
As can be seen, in this example, the data value passed to Subproc is just the current time/date, as returned
by p_date.
GENERAL PROGRAMMING MANUAL
Note the call to p_fparse, which calculates the presumed full pathname of subproc.img, under the
assumption that this is in the same directory as events2.img. (The full path of events2.img is written to
DatCommandPtr by the operating system, when Events2 starts running.)
For more on the operation of p_logona, see the Plib Reference manual.
The code in Subproc
The code in subproc.c is very straightforward:
#include <p_std.h>
#include <p_gen.h>
#include <p_math.h>
#include <epoc.h>
#include "subproc.h"
GLREF_C TEXT *DatCommandPtr;
GLDEF_C INT main(VOID)
{
TEXT *pb;
SUBPROC_CL *pcl;
UWORD answer;
WORD logstat;
pb=DatCommandPtr+p_slen(DatCommandPtr) +1;
if (*pb!=sizeof (SUBPROC_CL) )
return (E_GEN_ARG) ;
pcl=(SUBPROC_CL *) (pbt+1);
if (!p_logona(pcl->pid, &logstat) )
{
answer=(UWORD) (p_randl (&pcl->data) % (2*60*32) );
p_sleept (answer) ;
if (logstat<0)
p_pcpyto (pcl->pid, pcl->poff, &answer, sizeof (UWORD) ) ;
}
return (0);
}
The way Subproc mimics performing a lengthy calculation is simply to call p_sleept, for some random
period up to two minutes in duration.
Note that Subproc exits at once if the command line passed to it is not of the expected type. On most SIBO
computers, the result of an application calling p_exit with a negative value is a Notifier reporting the
abnormal exit.
Note too that just as Events2 asynchronously logs onto Subproc, Subproc logs onto Events2. However, this
is for a different reason. Namely, Events2 might terminate in the meantime, while Subproc is busy
"calculating". In this case, a non-negative number will be written into logstat. If Subproc ignored this
fact and proceeded regardless to p_pcpyto data into the process currently having identifier pc1->pia, in
all probability the call would fail - process identifiers take a long time to get re-used, and the operating
system would ignore the p_pcpyto on account of a non-existent pid being specified. But there is always an
outside chance that the pia will indeed be re-used by the time Subproc has completed - in which case the
p_pepyto could cause random damage to a blameless application.
The reason there is a test on the result of the p_logona call in Subproc is to guard against the rare case of
Events2 exiting even before Subproc reaches the p_logona call.
Mechanisms for inter-process communication
The above mechanism is a very simple illustration of a form of IPC (inter-process communication). Epoc
supports a considerable range of IPC services, chief amongst them being IPC messaging.
Messaging also involves the same principles of status words, synchronous or asynchronous requests, and
signalling an application. In some cases, one process will signal another one explicitly, using the function
p_iosignalbypid; in other cases, the signalling is performed by the operating system, say in response to a
p_mfree call in an application (indicating that the message sent has been processed).
See the Plib Reference manual for more details of these different forms of IPC.
5-10
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
Debugging cooperating applications
One method of debugging the interaction between Events2 and Subproc is as follows:
e leave both image files in the same directory on the PC
e in that directory, type sdbg events2 to start debugging Events2
e place a breakpoint on the p_logona call in events2.c
e run Events2 until it reaches this breakpoint
e note incidentally that the p_fparse call in Launchsub automatically deduces that since Events2
has been launched from a remote directory (ie on the PC), Subproc should also be launched (if
possible) from this same remote directory
e when the Debugger breaks at the p_logona call, the code and data segments for Subproc will
already be created (by virtue of the prior p_execc call)
e refresh the main list of remote processes; select Subproc and break into it (use the Break Into
menu command)
e scan to the beginning of main in subproc.c and set a breakpoint there
e issue the Apply Breakpoints menu command (whence the windows will go blank)
e switch back to the window debugging Events2 and step over the p_presume call
e this will have the effect of starting the execution in Subproc - in which case the breakpoint in
main will be reached.
Debugging now continues, with two different debugging windows - one for Events2, and one for Subproc.
Error handling in Events2
The call to p_execc in Events2 can fail for a variety of reasons - chief amongst them lack of system
memory. Note that Events2 does not treat this as a fatal error; rather, the error is reported to the user, and
the program carries on (taking care to leave the internal variable subexist set correctly).
The user has the opportunity to respond to the message by freeing up some system memory, and then
pressing ENTER to make another attempt to launch Subproc.
Socially responsible programming in Events2
There is one more change between events.c and events2.c, which actually corrects a bug deliberately left
in Events. This change is the addition of a call to p_unmarka at the start of main.
If a SIBO computer is left switched on while Events is running, it will fail to auto-switch-off subsequently.
This is because of the regular timer activity in the program, which keeps resetting the inactivity counter of
the computer.
Suppose that the user turns the computer off explicitly. However, if an alarm rings at some stage, Events
will start running again, and if the user is not at hand to notice the alarm, the result will soon be flattened
batteries - regardless of the auto-switch-off setting. (Try it and see.)
However, the addition of the call to p_unmarka prevents any activity within Events2 from resetting the
inactivity counter. As a result, Events2 is much more socially responsible than its precursor.
See the Plib Reference manual for more details on p_unmarka.
Data received from a serial port
Events3 extends the functionality of Events2 by including yet another event source: data received from a
serial port. Characters are read one at a time from the serial port and, if they are printable, they are echoed
onto the screen.
For background information on the serial port, see the Serial Port chapter of the I/O Devices Reference
manual.
5-11
GENERAL PROGRAMMING MANUAL
Opening the serial port
The serial port is an i/o device: before services such as P_FREAD can be requested from it, a suitable
channel has to be opened.
The contents of the openSer routine in events3.c are as follows:
LOCAL_C VOID OpenSer ()
{
INT ret;
ret=p_open(&serH, "TTY:B",-1);
if (ret<0)
ret=p_open(&serH, "TTY:A",-1);
if (ret<0)
{
p_notifyerr(ret,"Opening serial port",0,0,0);
serH=0;
}
}
If the attempt to open "TTyv:8B" fails, an attempt is made to open "TTy:A" instead; only if both attempts fail
is this fact reported to the user.
Typical reasons for it being impossible to open a serial port are that port already being in use (eg by Link
software) or the port not being physically present.
In contrast to the retry mechanism for launching Subproc which is built into Events3, there is no
corresponding retry mechanism for opening the serial port. A trivial amendment could be made to allow
this.
Active and inactive event sources
Events3 adds this fourth event source to the bottom of the prioritised list in main, which now has the
following schematic form:
GLDEF_C VOID main(VOID)
{
INITIALISE();
QueueTimer ();
QueueKey ();
LaunchSub () ;
QueueSer();
FOREVER
{
p_iowait ();
if (keystat!=E_FILE_PENDING)
{
PROCESS_KEY ();
QueueKey ();
}
else if (timstat!=E_FILE_PENDING)
{
PROCESS_TIMER() ;
QueueTimer ();
}
else if (subexist && substat!=E_FILE_PENDING)
Report Sub ();
else if (serH && serstat!=E_FILE_PENDING)
{
p_tickle();
DisplaySerChar ();
QueueSer ();
}
5-12
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
Note however that the test for whether to call Report sub has changed its form slightly. No longer is it
sufficient just to poll substat; it is also necessary to check on the current value of subexist:
e subexist is set to TRUE When Subproc is successfully launched
e¢ subexist 1s set back to FALSE whenever it is discovered that Subproc has completed
e thus the only time the value of substat should be polled is when subexist iS TRUE.
Without this double check, a variety of bugs can be demonstrated - all of which stem from serial port
events being misinterpreted as reports of Subevent completing.
Similarly, for the sake of correctness, the value of serx should be tested before going on to poll serstat:
serH is 0 if it has proved impossible to open a serial port. (Actually, no immediate harm will ensue if the
check on serH is omitted, given that this is the last of the event sources in the priority list.)
The reason no corresponding checks are required for the keyboard and timer event sources is that these
event sources are always active:
e the program terminates at once if it proves impossible to open a channel to these devices
e every time an event is delivered from these sources, another request (for yet another event) is
issued straightaway.
The variables serx and subexist in Events3 play the role of what are sometimes called active words for
their event sources - complementing the roles of their status words:
e active words have to be set and cleared by the application itself
e status words are written to by system software; generally, application software only reads the
values of status words
¢ active words are set when a request is made; status words are set when a request completes.
One other possible advantage in maintaining active words for event sources is to avoid making the
mistake of sending a Pp_FCANCEL request to an i/o channel which has not had a read request made on it.
Some i/o devices panic the application if this happens.
Debugging applications with serial comms
Programs involving serial comms are inevitably harder to debug than without serial comms.
This is because the Debugger itself uses up one serial port on the computer. In general, Events3 will be
unable to open any serial port currently being used by Link software (such as the SIBO Debugger).
One possibility, however, is to use say port a to debug the application, and send serial data to the
application via port B.
The role of p_tickle
Whenever serial port data is received by Events3, a call is made to p_tickle to reset the inactivity
counter. This prevents the computer from auto-switching off part way through processing an incoming
stream of serial data.
Note that there is no requirement to make a corresponding call whenever a keypress is received, since the
operating system does this automatically.
Finally, it would of course be an error to make this call whenever the timer expires - since this would keep
the computer permanently switched on.
Note that some early versions of the Epoc operating system may fail to support p_tickle (versions prior
to 2.11).
Yielding CPU in compute-intensive programs
Events4 adds in yet another type of event source - one that is subtly different from all the others so far
introduced. This is an event source which is always ready to run immediately. However, it is deliberately
located in a low position in the priority listing, to ensure that other event sources are processed
preferentially.
5-13
GENERAL PROGRAMMING MANUAL
A real-life example of such an event source would be a recalculation computation in a spreadsheet, or a
reformatting calculation in a word processor. Again, a long file operation - such as building the index of a
DBF file - should also be broken up into chunks, so as to let the application to respond to other event
sources in the meantime. Finally, a game may think indefinitely until such time as it is told to stop.
In Events4, this continual "thinking" is simulated by continually adjusting the display of part of the
boundary of the console window. The constant visible change is meant to reflect constant internal activity.
Idle objects
Event sources such as just discussed are sometimes referred to as idle objects. The meaning of the name is
that they only get a chance to run when the application is otherwise idle. For example, if an application is
busy responding to keypresses, it is certainly not idle, and so any idle objects have no opportunity to run.
On the other hand, this name is of course potentially misleading, since the activity represented by the idle
object is anything but idle.
The meaning of calling p_iosignal
The contents of the "queue" routine for the idle object in Events4 is just the single line
p_iosignal();
Since there is no genuine i/o connected with an idle object, there is no system software that automatically
signals the application when the i/o has completed. That is why the "queue" routine itself calls
p_iosignal.
At the same time, it might be thought that this routine should write to a status word. Actually, however,
there is no point in doing so: what matters is simply that the event source is active; in that case, it is
automatically ready to deliver an "event" (ie to take more CPU).
Just as some event sources have no need to maintain an active word (since they are always active), others
(ie idle objects) have no need to maintain a status word, since whenever they are active, they are ready to
deliver an event.
One drawback of continuous activity
Interestingly, Events4 has re-introduced the "stay awake" bug that Events2 managed to fix from Events.
This fact can easily be verified by user experimentation.
The call make to p_unmarka is now ineffective since, as is explained in the Plib Reference manual
(section on p_unmarka), it is the sys$null process which administers the auto-switch-off, yet it will have no
opportunity to run if any other applications are continually running. The point is that the priority of
sys$null is lower than that of any other process.
One possible solution here is to call, say, p_sleept (2) every so often, to try to allow sys$null to run.
However, this too will fail in the rare case when there are two similarly anti-social applications running
simultaneously on the SIBO computer. Even if they both call p_sleept periodically, there is little chance
of them both sleeping at the same time - which would be required in order for sys$null to run.
A better solution is to call p_allowoff from time to time. By doing so an application assumes
responsibility for performing the auto-switch-off that would otherwise be done by sys$null if it had an
opportunity to run.
Remarks on process priorities
The above problem of preventing the SIBO computer from auto-switching off is not the only potentially
deleterious side-effect of continuous activity. Just as continuous activity within Events4 prevents sys$null
receiving any CPU, so too will any other lower priority processes be locked out.
As it happens, Subproc and Events4 both run at the same process priority - the default of 0x80. (See the
chapter Building an Application for details on how process priorities are initialised.) However, suppose
the process priority of Subproc were lowered to say 0x70. In that case, continuous activity within Events4
would mean that Subproc, although launched, would never receive any CPU. Thus Events4 would
perpetually display the message "Subp launched", but never the completion message "Subp slept xxx
ticks".
The solution here is that any process about to become computationally intensive over a long period of time
should consider lowering its process priority, say to 0x70 - using the call p_setpri. For some related
discussion, see the section on wStartCompute in the Window Server Reference manual.
5-14
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
The call p_ioyield
One more potentially surprising fact about continuous activity within a program ought to be mentioned.
Clearly, not every program needs to be structured with an asynchronous event processing loop as in the
Events programs. Whilst such a loop is undoubtedly the correct architecture for a larger program, other
simple programs may have alternative structures.
For example, Subproc makes no call to p_iowait - nor does it need to, being purely single-threaded.
Again, the example Plib programs discussed in the chapter Building an Application (eg p_hello, p_comp
and p_prndir) likewise survive without an asynchronous event processing loop, since they are likewise
single-threaded.
However, there may be a temptation for programs to use the following semi-asynchronous mechanism, in
order to be able to respond to keypresses (say) whilst being mainly dedicated to some continuous activity:
¢ continue processing queue an asynchronous request to receive a keypress
e start the continuous activity
e every so often, test to see if the status word is still z_F1LE_PENDING
e if it is, continue processing
In other words:
FOREVER
{
QueueSer (&keystat) ;
while (keystat==E_FILE_PENDING)
MoreProcessing();
ProcessKey();
}
However, this program may totally fail, with keystat never changing from B_FILE_PENDING.
The reason for this is rather complicated, but it is worth understanding. It has to do with what happens
when an asynchronous event completes. This completion often involves two distinct phases:
e the completion itself happens on an interrupt
¢ an interrupt service routine runs, and the i/o device changes some of its internal variables to
record this fact
e however, the i/o device generally cannot write to the associated status word during the interrupt
service routine itself
e this is because there are strict rules on what can and cannot be done within an interrupt service
routine (see the chapter Writing Device Drivers in the Additional System Information manual for
more details)
e instead, the i/o device relies upon its so-called wait handler routine to be called, so that it can
finish the job of completing the request - writing to the status word and signalling the application
e these wait handler routines only have an opportunity to run inside the call p_iowait (or
equivalent).
In other words, the description given earlier in this chapter of the functioning of p_iowait was incomplete
in one important respect: not only does this routine take note of the value of the i/o semaphore for the
application, and suspend the application so long as this remains negative; it also gives all i/o device
channels in the application an opportunity to run their wait handlers.
5-15
GENERAL PROGRAMMING MANUAL
Accordingly, the earlier code has to be changed into
FOREVER
{
QueueSer (&keystat) ;
while (keystat==E_FILE_PENDING)
{
MoreProcessing();
p_iosignal();
p_iowait ();
}
ProcessKey ();
}
which is in fact much more in line with the main routine of the Events4 application discussed.
For convenience, the single call p_ioyie1d can be used with the same effect as p_iosignal followed by
p_iowait.
Note incidentally that it is a rare application that needs to actually write a wait handler; there is of course
no need to write a wait handler routine just because an application involves asynchronous i/o.
General remarks
Multi-threadedness and multi-tasking
For the sake of clarity, the two different notions of multi-tasking and multi-threadedness ought to be
compared and contrasted:
e multi-tasking involves two (or more) different processes; multi-threadedness involves two (or
more) event sources within one process
e the operating system takes care of multi-tasking automatically, on behalf of applications; multi-
threadedness requires conscious effort from an application
e §=multi-tasking is pre-emptive in that a process with a higher priority that is ready to run will
always displace a lower priority process that is running
e multi-threadedness is non pre-emptive in that an event source with a higher priority has to wait
until a lower priority event source voluntarily gives up CPU, before being able to run.
Subprocess or idle object?
In the design of large systems, there is considerable scope for decision-making on whether to assign
compute-intensive tasks to idle objects within an application, or to a subprocess of the application proper.
Some factors that may be considered in making such a decision are:
e having two different processes automatically allows a total combined dataspace greater than 64k
e asubprocess need not worry unduly about creating "holes" ("fragmentation") in its allocator
heap, since these will all vanish when the subprocess terminates (when its entire heap vanishes);
however, if an idle object is transient and terminates well before the overall application finishes,
any fragmentation it creates in the allocator heap may have a more damaging long-term effect
(see the chapter Memory Allocation in the Plib Reference manual)
e an idle object is much more tightly bound to the main program than is a subprocess
¢ communications between a subprocess and the main program have to be much more formalised
than is the case with an idle object
e an idle object can draw to the same windows on the screen as the main application, but not so for
a subprocess (except in the case of the MC - see the function wAttachToclient in the Window
Server Reference manual).
5-16
5 FUNDAMENTAL PROGRAMMING GUIDE-LINES
Window redraws as an event source
Up till now, one very important event source has not been mentioned in this chapter. This is the event of a
window requesting itself to be redrawn. (In fact, the request originates from the Window Server.)
These events do not occur when using console i/o, nor when using windows with back-up bitmaps:
windows are automatically redrawn by the Window Server in these cases. However, high quality
applications undertake window redrawing by themselves, so as to avoid the large ram overheads of the
back-up bitmaps. (See the Introduction chapter of the Window Server Reference manual.)
Such applications must remain responsive to redraw events at all times - otherwise their screen will
remain blank if they are suddenly task switched into foreground, or if an overlapping menu or dialog
window is removed. This is all the more reason for these applications to adopt the sort of general event
processing architecture outlined in this chapter.
The APPMAN and ACTIVE classes in OLIB
The appman and active classes in olib.dyl provide system support for object-oriented applications
e representing their event sources (each event source is represented by an "active object")
e prioritising these event sources
¢ maintaining active and status words for each event source
e calling p_iowait at appropriate times
e ensuring that all event sources are properly polled.
At the same time, the appman class ("appman" is short for "application manager") provides an automated
mechanism for error handling, as well as handling the interface to resource files (see the Resource Files
chapter in the Additional System Information manual).
These topics are further discussed in the Object Oriented Programming Guide. In addition, the appman
and active classes are documented in the OLIB Reference manual.
5-17
GENERAL PROGRAMMING MANUAL
5-18
CHAPTER 6
CoPyY-PROTECTING SOFTWARE
Introduction
This chapter considers various mechanisms to "copy-protect" software written for SIBO computers.
Possible goals of copy-protection include:
e software should be able to run, only from the original SSD it is supplied in
e — software should be able to run, only on one particular computer
e first generation copies should be allowed, but not second generation copies (ie direct copies make
from the original SSD would run, but not copies of these copies)
e possibly, the number of first generation copies allowed could be limited.
These different goals vary in their applicability to the different computers in the SIBO range. For
example, software that disallowed even first generation copies would be very unwelcome on the Series 3,
because it prevents consolidation - the process whereby users copy more than one different application
onto the same SSD. It is unlikely that such software would sell at all well. On the other hand, this kind of
strict copy protection makes more sense for the HC, and for corporate ("Vertical") programs generally.
At the same time, software developers may wish to apply differing amounts of sophistication in their copy
protection schemes - some being willing merely to frustrate the casual would-be copier, and some being
determined not to allow copying at all (if possible).
This chapter does not favour one copy protection method over all others. Rather, it simply hints at various
different possibilities. Software developers may find it convenient to mix and match the different
proposals made, as well as others (along the same lines) that they can think of themselves.
By the very nature of the subject, too much documentation would be self-defeating. Once any algorithm to
implement copy protection becomes widely known, methods to defeat this algorithm may be developed
and circulated.
| ic I a
The free space method
This method aims at strict copy protection: the software will only run if it is on the original SSD.
This simple yet effective method turns one of the commonly debated disadvantages of using Flash storage
into an advantage.
The method is based around the fact that when a file is deleted from a Flash SSD it remains on the pack
taking up space but is no longer practically accessible. Assuming that an application master pack contains
a deleted file, if someone were to copy this pack using the usual copy from the root including
subdirectories, the resulting copy of the master pack will differ fundamentally: the deleted file no longer
exists. This in turn means, rather conveniently, that the amount of free space on the pack will be different.
Given the above you can then hard-code into your application a check to see if the figure for space on the
pack matches the figure you expect: if it does then all well and good; else, do not allow the software to
run.
GENERAL PROGRAMMING MANUAL
The way to find the amount of free space on an SSD is to call p_dinfo. For example, a program that prints
the amount of free space on the disk the program was launched from:
#include <p_std.h>
#include <p_file.h>
#include <p_sys.h>
GLREF_D TEXT *DatCommandPtr;
GLDEF_C INT main(VOID)
{
P_DINFO dinfo;
p_dinfo(DatCommandPtr, &édinfo) ;
p_printf ("Free space is %lu",dinfo.free);
p_getch ();
return (0);
}
First generation copying methods
Methods that allow first generation copies to run, but not second generation copies, rely on a separate
"AppCopy" program being provided on the master SSD, in addition to the program itself.
First generation copies can only be made using the AppCopy program. Copies made using ordinary Copy
commands will fail. Further, AppCopy will refuse to copy first generation copies into second generation
copies.
Essentially, AppCopy does not make an exact copy, but changes some of the bytes in the application
program. This can be done, even on Flash SSDs, provided:
e the original values of the bytes are all oxrft's
e the bytes are adjusted one at a time (assuming that a complete copy has already been made, and
that this complete copy has to be altered).
The last point is most important; the Flash filing system tests for the special case of only one byte being
written, and in this case, alters the physical byte on the SSD. In other cases, the physical structure of the
file is significantly changed.
Preserving checksums
Note that in adjusting bytes in a program file, care has to be taken not to disturb the code or data
checksums (as reported eg by the tool edump.exe). Otherwise, the operating system will refuse to run the
program, believing it to be corrupt.
The checksums can be preserved in either of two ways:
e provided enough bytes are changed, the checksum can be left the same as it was originally
e rather than changing the program part of the image file, one of the add-files inside the image file
should be changed (see the chapter Building an Application for details of add-files).
In general, the second method is preferable.
What kind of change should be made
The change made to the program file has two purposes:
e the file is now recognisably a first generation copy
e the change contains data somehow allowing this first generation copy to run, in a way preventing
a straight copy of this file from running on another computer.
Possible ideas on this second point include:
e information from an environment variable specially created on the target computer (secretly and
with a random value), by the AppCopy program
e the date the copy was made (so that the copy will "expire" after a certain length of time)
e details about the low-level structure of the SSD (see below).
6 COPY-PROTECTING SOFTWARE
To make the mechanism less obvious to a casual browser, any information from say an environment
variable ought to be stored in the file encrypted in some way.
Restricting the number of copies made
In order to restrict the number of first generation copies ever made to eight, say (which would not be
unreasonable), certain bytes in the master copy of the program could be changed. As above, these bytes
would start with the value oxf£, and would have to be written one at a time.
The documentation for the product would have to state clearly that AppCopy could only be used eight
times. This would have the effect of making the owner of the software most wary against making cavalier
bootleg copies.
This method will of course only work if the SSD containing the original copy can be written to. This will
be impossible for OTP (One Time Programmable) or masked ROM SSDs. In this case, information about
the number of first generation copies made could be stored in another environment variable, though of
course this method would be easier to subvert.
Low level SSD information
Each SSD contains a so-called "unique ID" which can be used to identify it.
Another potentially very useful piece of information would be the physical pack offset of the start of a
nominated file on an SSD. An AppCopy program could create a small file on the target SSD, and then
delete it, before copying the program file across. The physical pack offset of the start of the program file
could then be written into the program file (possibly in encrypted form), for the program to check when it
starts to run.
Alternatively, information could be read from the deleted file.
These types of information can be read by use of the p_locreadpda function, described in the Files
chapter of the PLIB Reference manual.
Copy-protection by changing the ROM
In the case of the HC, it is possible to use the tool romwrite.exe to overwrite portions of a file custom$.dat
in the ROM of the HC. See the chapter Introduction to the HC in the HC Programming Guide for details
of the operation of romwrite.exe.
Programs can then check that they are running on a given specified HC.
To read the contents of custom$.dat, just open the file as normal, specifying the full path name
rom: :custom$.dat.
One other possibility is to change the contents of the ROM more radically, eg placing certain software into
the ROM, with a program on an SSD refusing to run unless this software is present in the ROM. For more
details, again see the HC Programming Guide.
GENERAL PROGRAMMING MANUAL
6-4
CHAPTER 7
COMPATIBILITY
Introduction
The vast majority of existing software will, in principle, run on all machines in the SIBO range, provided
that the display can accommodate itself to the different screen sizes.
For details of the differences between SIBO machines see Writing Software for the HC in the HC
Programming Guide and the Series 3 family compatibility section of the Series 3 Programming Overview
chapter in the Series 3/3a Programming Guide manual.
What machine am I running on?
Most SIBO machines can be distinguished by their screen sizes, as determined by the return value from a
call to p_geticda. The possible return values for existing SIBO machines are as follows:
E_LCD_640_400 (0)
E_LCD_640_200_SMALL (1)
E_LCD_160_80 (4)
E_LCD_240_80 (5)
E_LCD_480_160 (11)
E_LCD_240_100 (12)
E_LCD_240_160 (14)
a 640x400 pixel display as on the MC 400
a 640x200 pixel display as on the MC 200
a 160x80 pixel display as on the HC
a 240x80 pixel display as on the Series 3
a 480x160 pixel display as on the Series 3a and Series 3c
a 240x100 pixel display as on the Workabout
a 240x160 pixel display, as on the Siena
This will distinguish all machines except the Series 3a and Series 3c, which have screens of the same size.
These two machines can be distinguished by means of a call to the function p_returnexpansionportinfo,
present in machines with EPOC version 3.90F or later, as in the following example code fragment.
GENERAL PROGRAMMING MANUAL
UINT lcdtype;
UINT version;
UINT port;
lcdtype=p_getlcd();
if (lcdtype==E_LCD_480_160)
{ /* S3a or S3c */
version=p_version();
if (version>=0x390F)
{ /* safe to call p_returnexpansionportinfo */
port=p_returnexpansionportinfo()
if ((port & 0x0700)==0x0300)
{
/* must be S3c */
}
else
{
/* must be S3a */
}
}
else
{
/* EPOC version less than 3.90,
}
else
{
/* machine determined by LCD type */
}
so must be S3a */
INDEX
.afl files
add file lists, 3-13
add file lists - changing, 3-14
.app files
versus .img files, 3-13
.dfl files
add file lists for DYLs, 3-14
.dyl files
building with emake.exe, 3-14
.img files
applications, 3-1
control over, 3-12
creating, 3-3
versus .app files, 3-13
Idd files
building with emake.exe, 3-14
.pdd files
building with emake.exe, 3-14
.pic files
application icons, 3-13
.pr files
application project files, 3-1
project files - a first look, 3-2
sc files
resource files - application, 3-13
zc files
resource files compressed, 3-13
.shd files
shell data files, 3-13
ACTIVE class
remarks on OLIB, 5-16
add file list
application, 3-13
application - changing, 3-14
application DYLs, 3-14
application
a first look at .img files, 3-3
add file lists, 3-13
add file lists - changing, 3-14
add file lists for DYLs, 3-14
app files vs img files, 3-13
batch files - housekeeping, 3-6
building, 3-1
building - introduction, 3-1
building - more complex example, 3-9
building - more complex example PLIB, 3-9
building - multi-file, 3-9
building - with assembler, 3-11
building emake.exe, 3-14
building eremake.exe, 3-14
copy protection see copy protection, 6-1
debugging on SIBO system, 3-4
file - control over, 3-12
file transfer to SIBO system, 3-1, 3-3
graphics and, 3-10
heap size - minimum, 3-12
Hwif - building, 3-10
icon files, 3-13
information from edump.exe, 3-12
multi-tasking - remarks on, 5-16
multi-threaded - remarks on, 5-16
priority - control over, 3-12
resource .rsc files, 3-13
resource files .rzc compressed, 3-13
running on SIBO system, 3-3
shell data files, 3-13
version number - control over, 3-12
application development
C SDK equipment required, 3-1
C SDK files for oop, 3-2
C SDK files required, 3-2
first example, 3-2
fundamental guide-lines, 5-1
applications
.img files, 3-1
APPMAN class
remarks on OLIB, 5-16
assembler
applications - containing, 3-11
asynchronous I/O
programming, 5-2
auto-switch-off
p_unmarka, 5-14
SYS$NULL - chance to run, 5-14
background processing
programming example, 5-2
batch files
application housekeeping, 3-6
compilation, 3-6
compilation complications, 3-7
build
C SDK configuration files, 3-11
GENERAL PROGRAMMING MANUAL
building
C
applications, 3-1
applications - control over, 3-12
applications - more complex example, 3-9
applications - more complex example PLIB,
3-9
applications - multi-file, 3-9
applications - with assembler, 3-11
applications introduction, 3-1
applications with graphics, 3-10
applications with Hwif, 3-10
manuals - Topspeed C, 2-1
C SDK
C++
build configuration files, 3-11
configuration file tscfg compiler, 3-11
configuration file tsprj.txt, 3-11
configuring the redirection file, 1-3
configuring the Topspeed project system, 1-
2
directory structure, 1-2
documentation version, 1-1
equipment required, 3-1
files required, 3-2
files required - oop, 3-2
installation, 1-1
installation phases, 1-1
manuals, 2-1
manuals - where to start, 2-2
overview SIBO system, 2-1
professional version, 1-1
SIBO software, 1-2
small model code, 1-1
standard version, 1-1
Topspeed C, 1-1
Topspeed software, 1-2
variants of, 1-1
object oriented programming and, 2-3
cancelling timers
in general, 5-6
Clarion Software
Topspeed C, 1-1
CLIB
console device I/O, 4-3
DOS file names, 4-3
file handle conversion, 4-2
floating point emulator, 4-3
floating point emulator - panic 80, 4-3
int86x implementation, 4-2
intr implementation, 4-2
library - building, 4-4
missing DOS functions, 4-1
notes on, 4-1
CLIB & PLIB
contrasted, 3-4
code size
application CLIB, 3-5
application PLIB, 3-5
compatibility
software on SIBO systems, 7-1
compilation
batch file complications, 3-7
batch files, 3-6
optimisation warning, 3-11
TSC vs TSCX, 3-8
compute intensive application
CPU yielding, 5-13
configuration file
C SDK tscfg compiler, 3-11
C SDK tsprj.txt, 3-11
configuration files
C SDK build, 3-11
console device
implementation in CLIB, 4-3
in general, 5-6
cooperating applications
debugging, 5-11
copy protection
first generation copy method, 6-2
free space method, 6-1
introduction, 6-1
low level SSD method, 6-3
mechanisms, 6-1
ROM changing method, 6-3
CPU intensive
yielding in applications, 5-13
CPU yielding
compute intensive applications, 5-13
programming, 5-2
customised
libraries, 3-10
debugging
applications - on SIBO system, 3-1, 3-4
cooperating applications, 5-11
serial port comms applications, 5-13
device driver
LDD - building with emake.exe, 3-14
PDD - building with emake.exe, 3-14
devices
I/O in general, 5-5
directory structure
C SDK, 1-2
documentation
C SDK - where to start, 2-2
documentation sources
programming, 5-1
DOS functions
CLIB - missing functions, 4-1
DYL
add file lists into application, 3-14
building with emake.exe, 3-14
dynamic library
DYL - building with emake.exe, 3-14
edump.exe
application information, 3-12
utility program, 3-12
emake.exe
application building, 3-14
application conversion, 3-1
utility program, 3-14
EPOC
explained, 2-2
epocinit
project file statement, 3-6
eremake.exe
application building, 3-14
utility program, 3-14
error handling
a first look, 5-7
events and, 5-7
resource tidying, 5-8
errors
panic number ranges, 2-3
panics explained, 2-3
events
active and inactive sources, 5-12
ACTIVE class - remarks on, 5-16
APPMAN class - remarks on, 5-16
idle objects, 5-14
multiple source examples, 5-3
p_iosignal - function of, 5-14
prioritisation of sources, 5-5
window redraw - remarks on, 5-16
example code
detecting which SIBO system, 7-1
fatal program errors
panics explained, 2-3
file handle
conversion in CLIB, 4-2
file names
DOS implementation in CLIB, 4-3
file transfer
applications - to SIBO system, 3-1
applications to SIBO system, 3-3
floating point
emulator - panic 80 in CLIB, 4-3
emulator in CLIB, 4-3
fundamental guide-lines
programming, 5-1
graphics
applications and, 3-10
heap size
minimum, 3-12
hello world
application - PLIB first example, 3-4
application first example, 3-2
Hwif
application building, 3-10
I/O devices
in general, 5-5
INDEX
icon files
application, 3-13
IDE
Topspeed Integrated Development
Environment, 3-1
idle object
contrasted with sub-process, 5-16
idle objects
events, 5-14
p_iosignal - function of, 5-14
image file
control over, 3-12
include file
stdepoc.h, 3-11
installation
C SDK, 1-1
int86x
implementation in CLIB, 4-2
inter-process communications
in Events2 - and Subproc, 5-8
mechanisms, 5-10
intr
implementation in CLIB, 4-2
IPCS
in Events2 - and Subproc, 5-8
mechanisms, 5-10
key presses
remarks on, 5-4
keyboard input
programming example, 5-2
LDD
building with emake.exe, 3-14
libraries
customised, 3-10
library
building CLIB, 4-4
CLIB missing DOS functions, 4-1
CLIB notes on, 4-1
machine
detecting which SIBO system, 7-1
manuals
C SDK, 2-1
Topspeed, 2-1
multi-tasking
applications - remarks on, 5-16
multi-threaded
applications - remarks on, 5-16
programming, 5-2
object oriented programming
C++ and, 2-3
Psion C approach, 2-3
optimisation
compilation warning, 3-11
p_hello.c
source code, 3-5
p_iosignal
function of, 5-14
iii
GENERAL PROGRAMMING MANUAL
p_iowait
remarks on, 5-4
status words - declaring, 5-7
status words - remarks on, 5-5
p_ioyield
remarks on, 5-14
p_tickle
function of, 5-13
p_unmarka
auto-switch-off, 5-14
panic 80
floating point emulator - CLIB, 4-3
panics
explained, 2-3
number ranges, 2-3
PC
C programs, 1-1
PC based
development, 1-1
PDD
building with emake.exe, 3-14
PLIB
hello world application example, 3-4
PLIB & CLIB
contrasted, 3-4
priorities
processes - remarks on, 5-14
priority
application - control over, 3-12
process priorities
remarks on, 5-14
program
file transfer to SIBO system, 3-3
program errors
panics explained, 2-3
program size
application CLIB, 3-5
application PLIB, 3-5
programming
asynchronous I/O, 5-2
console device I/O in general, 5-6
CPU yielding, 5-2
documentation sources, 5-1
error handling - a first look, 5-7
error handling - in events, 5-7
error handling - resource tidying, 5-8
events - prioritisation of sources, 5-5
events multiple source examples, 5-3
example of background processing, 5-2
example of keyboard input, 5-2
example of serial port data input, 5-2
example of sub-process completion, 5-2
example of timer expiry, 5-2
fundamental guide-lines, 5-1
I/O devices in general, 5-5
introduction - example source, 5-2
introduction to, 5-1
introduction to events - example apps, 5-2
key presses - remarks on, 5-4
multi-threaded, 5-2
p_iowait - remarks on, 5-4
p_iowait remarks on, 5-4
p_iowait status words - declaring, 5-7
p_iowait status words - remarks on, 5-5
p_ioyield - remarks on, 5-14
PC based development, 1-1
semaphore I/O, 5-4
timers cancelling in general, 5-6
timers remarks on, 5-4
user interface - simple examples, 5-2
programs
.img files, 3-1
project file
a first look at .pr files, 3-2
advanced use, 3-11
application project .pr files, 3-1
epocinit statement, 3-6
reusing - general, 3-6
resource files
application .rsc files, 3-13
application .rzc compressed, 3-13
screen sizes
detecting which SIBO system, 7-1
table of for SIBO systems, 7-1
segment registers
small code model, 4-2
semaphore
I/O remarks on, 5-4
serial port
comms debugging, 5-13
data reception of, 5-11
opening, 5-12
serial port data input
programming example, 5-2
shell data files
application, 3-13
SIBO
explained, 2-2
systems family, 1-1
SIBO SDK
see C SDK, 2-1
SIBO systems
screen size table, 7-1
software compatibility, 7-1
what machine, 7-1
small code model
segment registers, 4-2
small model code
C SDK, 1-1
software
compatibility across SIBO systems, 7-1
copy protection introduction, 6-1
copy protection mechanism, 6-1
stack size
default, 3-6
specifying, 3-6
INDEX
status words
declaring - p_iowait, 5-7
stdepoc.h
include file, 3-11
sub-process
contrasted with idle object, 5-16
sub-process completion
programming example, 5-2
SYS$NULL
chance to run auto-switch-off, 5-14
timer expiry
programming example, 5-2
timers
cancelling in general, 5-6
remarks on, 5-4
Topspeed
Integrated Development Environment, 3-1
Topspeed C
Clarion Software, 1-1
library reference, 2-1
package, 1-1
ts.red file
C SDK redirection file, 1-3
TSC vs TSCX
contrasted, 3-8
tscfg
configuration file compiler, 3-11
tsprj.txt
configuration file, 3-11
user interface
programming examples, 5-2
utility program
edump.exe, 3-12
emake.exe, 3-14
eremake.exe, 3-14
version number
application - control over, 3-12
versions
C SDK, 1-1
what machine
detecting the SIBO system, 7-1
window redraw
event source - remarks on, 5-16
window server
WLIB library introduction, 3-5
WLIB
introduction, 3-5
yielding CPU
programming, 5-2