<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- generator="FeedCreator 1.7.2" -->
<rss version="2.0">
    <channel>
        <title>AAS: Articles and Features: Devloper OPL Full </title>
        <description>Recent articles and features from All About Symbian Forums in Devloper OPL Full </description>
        <link>http://www.allaboutsymbian.com/features/</link>
        <lastBuildDate>Sat, 11 Feb 2012 06:39:01 +0100</lastBuildDate>
        <generator>FeedCreator 1.7.2</generator>
        <item>
            <title>Tutorial - Installing the Nokia 9200 SDK and OPL SDK</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=15</link>
            <description>&lt;p&gt;Developing in OPL for the Nokia 92x0 can be done in two different ways:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Firstly using the PC based SDK (software development kit), with an extra OPL Devkit installed in addition to the C++ / Java SDK. This method uses the 92x0 emulator. Code is written within the OPL program in the emulator and programs can be translated and tested in the emulator. This method is entirely PC based. &lt;/li&gt;&lt;li&gt;Secondly using either a Nokia 9210, 9290 or 9210i device itself. In this case the OPL editor and OPL runtime must be installed on to the phone. Programs are written in the editor on the phone, translated via the editor in the phone and can be run on the phone using the OPL runtime. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This tutorial guides you through firstly PC based development (obtaining and installing the SDK and configuring it for OPL development use) and Device based development (installing the OPL editor and runtime). It is recommended that you have both option available when developing as both have their own advantages and disadvantages:&lt;/p&gt;&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;80%&quot; align=&quot;center&quot; border=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width=&quot;15%&quot; bgcolor=&quot;#cccccc&quot;&gt; &lt;/td&gt;&lt;td width=&quot;47%&quot; bgcolor=&quot;#cccccc&quot;&gt;&lt;b&gt;Advantages&lt;/b&gt;&lt;/td&gt;&lt;td width=&quot;38%&quot; bgcolor=&quot;#cccccc&quot;&gt;&lt;b&gt;Disadvantages&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width=&quot;15%&quot; bgcolor=&quot;#cccccc&quot;&gt;&lt;i&gt;Device based&lt;/i&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot; width=&quot;47%&quot;&gt;Feeling for how program will work on actual target device, mobile development solution (program on the way to work)&lt;/td&gt;&lt;td valign=&quot;top&quot; width=&quot;38%&quot;&gt;Small keyboard means inputting lots of code can be tricky, smaller screen is harder on the eyes.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width=&quot;15%&quot; bgcolor=&quot;#cccccc&quot;&gt;&lt;i&gt;PC based&lt;/i&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot; width=&quot;47%&quot;&gt;Large keyboard and screen allow for easy inputting of code and is easier on the eyes. Emulator (depending on speed of computer) is often faster than 92x0. &lt;/td&gt;&lt;td valign=&quot;top&quot; width=&quot;38%&quot;&gt;Not as mobile as the 92x0, not the actual device so difficult to get a feel for how things will actually work. The computer which the emulator is installed on must be sufficiently powerful to run the emulator (Pentium 200 64MB Ram minimum). Emulator is a Windows only program (despite being intended for NT it will generally run on any Windows Installation of 96 and above).&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;b&gt;Obtaining the SDK and Devkit&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The Nokia 9200 SDK can be obtained from Forum Nokia. You must be a member of Forum Nokia in order to obtain the SDK. Joining Forum Nokia is free (some personal information is collected), and is worthwhile as it give you access to documentation and other useful tools for all Nokia Symbian devices.&lt;/p&gt;&lt;p&gt;The SDK can be ordered on a CD (allow upto 3 weeks for it to arrive), or it is available as a download within the Symbian section. The download is large and is therefore recommended only for people who have a fast internet connection. This SDK is for C++ and Java development. In order to use it for OPL development and OPL Devkit must be obtained.&lt;/p&gt;&lt;p&gt;The OPL Devkit contains the files necessary to add OPL to the C++/Java SDK and the files to allow for OPL development on the Nokia 92x0. The OPL Devkit is available from the Developer section of the Symbian website. There is a download for both the OPL runtime and the OPL Devkit. The second of these is for developers, but the first will be needed by users to run your OPL program on their machine. In addition Symbian have also made available on this page some updated OPX's, it is recommended you also download this file. &lt;/p&gt;&lt;p&gt;It should be noted that Symbian expressly warn you that installation is at your own risk and that OPL is unsupported (but we're here to help!). However there have been no reported problems from anyone installing the SDKs. You should download the SDK from the page above as it allows Symbian to track interest in OPL development.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Installing the SDK and Devkit on a PC&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Full documentation comes with the Nokia C++/ Java SDK including installation instructions. You should follow these. In summary it as simple as installing any other program. (To install run setup.exe). After installation you will have a working Nokia 92x0 Emulator. In order to use this emulator for OPL development the OPL Devkit must be installed.&lt;/p&gt;&lt;p&gt;Once you have downloaded the ZIP file containing the OPL Devkit you should unzip it and read the readme.txt file. This contains instructions for installing the OPL Devkit. They may look long and complicated, but they are in fact very clear. Following the instructions takes around 10 minutes and adds the OPL runtime and OPL Editor to the Emulator.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img height=&quot;151&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/Project/oplprogram.gif&quot; width=&quot;481&quot; border=&quot;1&quot; /&gt;&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;It will also add the DemoOPL Program which is a Symbian version of the FreEPOC Event Core (although more complex and less easy to understand). DemoOPL is written in OPL and as can be seen from the screenshot below it demonstrates that OPL programs look and feel like the inbuilt applications and can used to create both complex and useful programs.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img height=&quot;151&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/Project/demoopl.gif&quot; width=&quot;480&quot; border=&quot;1&quot; /&gt; &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;The OPL Devkit Zip file also contains some useful documents such as the OPL Porting Guide and OPL Documentation. The OPL Devkit ZIP file contains another ZIP file which contains documentation on OPL from Epoc Release 5 (the previous OPL release to that for the Nokia 92x0) and is very useful in understanding OPL as changes between the two versions are &lt;i&gt;relatively&lt;/i&gt; minor.&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;&lt;b&gt;Installing the Devkit on the 92x0 device&lt;/b&gt;&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;To be able to develop OPL on the Nokia 92x0 device both the OPL runtime and the OPL Editor and associated files must be installed. The instructions for doing this are in the same readme.txt file referenced above. If you have installed a previous version of the OPL runtime please pay careful attention to the note in the readme.txt file (just above the installation instruction for OPL on the 92x0 device) otherwise the OPL Devkit may not work.&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;One stage that may not be clear is the following: '&lt;i&gt;Install any of the OPX files in \Binaries\SIS Files\Target\OPX\ which you require&lt;/i&gt;'. OPX files are extension of the OPL language. It is recommended that you install all such files available (including the ones available in the updated ZIP file available from the Symbian site). &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;Once you have successfully installed the files you should be able see the OPL Editor (called Program) which will enable you to write and translate files on the 92x0 itself.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img height=&quot;150&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/Project/opleditor.gif&quot; width=&quot;480&quot; border=&quot;1&quot; /&gt;&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;So now you are all set to get going? If you need more help you can follow Ewan's OPL tutorials which will take you though every step of learning about OPL and teach you how to use the OPL Event Core to write your own program...&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;</description>
            <pubDate>Mon, 25 Aug 2003 22:10:13 +0100</pubDate>
        </item>
        <item>
            <title>Part 7: Thinking about thinking</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=14</link>
            <description>&lt;p&gt;&lt;b&gt;Abstract Concepts&lt;/b&gt;&lt;br /&gt;One of the main things that people have problems with when programming is begin able to take an idea in their head, and turn that idea into computer code that does exactly what they want it to do. What I want to show you in this chapter is how we take one concept and turn it into code.&lt;/p&gt;&lt;p&gt;The key (as always) is being able to break your idea into smaller and smaller rules. If you break it down far enough, then you'll have something that can easily be written in OPL. What you must remember is when writing these rules, you must mention everything you do. You can't say &quot;compare this ball to those four,&quot; you need to say what you're comparing, to which ball, and what to do depending on the result.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Checking The Guess&lt;/b&gt;&lt;br /&gt;&lt;i&gt;Breaking It Down&lt;/i&gt;&lt;br /&gt;Before we can tell the computer what to do, we need to have a clear understanding on the thought processes that that our brain goes through. If we were making a cup of tea, it's no good having a rule that goes:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;Boil Kettle&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;You need something like:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;Take kettle to tap
Remove lid
Put kettle under tap
Turn on tap
DO&lt;br /&gt;   wait a bit
UNTIL kettle is full
Put lid on kettle
Put kettle on table
Plug in power cable to kettle (it's an old fashioned one)
Switch on power at mains
Switch on kettle
DO
   wait a bit
UNTIL kettle switch moves to off position&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Of course, there's nothing to stop you calling the above PROC boil_kettle: is there.&lt;/p&gt;&lt;p&gt;Right, so this is the level of detail we'll need to break down any computer action. Let's now look at MASTER and how I've broken it down, although you might want to have a go yourself before having a look at my solution.&lt;/p&gt;&lt;p&gt;Again, remember there is no right or wrong way when doing routines like this. If your way works, great! Just because it's slightly different from mine, you understand it and the user gets the same end result.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Checking Those Balls&lt;/i&gt;&lt;br /&gt;The routine in Master checks to see how many balls are the right colour in the right place, and how many are the right colour but in the wrong place. These two numbers will be used to display the 'hint' to the player so he or she can make another guess to try and logically work out the solution. &lt;/p&gt;&lt;p&gt;Always keep your overall goal of a procedure in mind. It helps immensely. Now…&lt;/p&gt;&lt;p&gt;&lt;b&gt;Code Breakdown&lt;/b&gt;&lt;br /&gt;So what we'll do here is break down exactly the thought processes that you go through when comparing a guess in Master to the correct four colour solution.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Some Counters&lt;/i&gt;&lt;br /&gt;To keep track of things, we'll start with two 'counters' in our heads.. the number of balls that are the right colour in the right place, and the right colour but in the wrong place. So the first thing to do is&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;(Right Place)=0
(Wrong Place)=0&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;i&gt;Check all balls are guessed (if not, return)&lt;/i&gt;&lt;br /&gt;The guess button can be pressed at any time so we should check to see everything is in order before we process the guess.&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;(Counter)=0
DO
   (Counter) is increased by one
   IF guess position (counter) does not have a colour (ie it has a value of zero)
      Go back into game loop, print up warning message
   ENDIF
UNTIL (counter) equals four&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;i&gt;Have we won?&lt;/i&gt;&lt;br /&gt;This check is obvious. Have we got the solution correct? And as we're already thinking like a computer, we'll use a DO... UNTIL loop&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;(Counter)=0
DO
   (Counter) is increased by one
   IF guess position (counter) EQUALS colour in solution position (counter)
         (Right Place) is increased by one
   ENDIF
UNTIL (counter) equals four
IF (Right Place) equals four
   Then the guess is 100% correct, do the victory routine
ENDIF&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;All the above should be pretty obvious, and easy to code (now we've bbroken it down into the small logical steps computer programming requires). &lt;/p&gt;&lt;p&gt;&lt;i&gt;How many balls are the right colour in the right place?&lt;/i&gt;&lt;br /&gt;Well, we have the steps already don't we? We can use the code above because the (Right Place variable is going to carry the number of balls we need.&lt;/p&gt;&lt;p&gt;&lt;i&gt;How many balls are the right colour, but in the wrong place?&lt;/i&gt;&lt;br /&gt;Stop and think how you do this before we break it into steps. You take the first ball, and see if it matches anything in the solution (ignoring a ball if it is in the same postion (ioe the second guess compared to the second ball in the solution is something you don't do).&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;(Wrong Place)=0
(Counter One)=0
DO
   (Counter One) is increased by one
   (Counter Two)=0
   DO
      (Counter Two) is increased by one
      IF (Counter One) and (Counter Two) are different
         IF guess position (Counter One) equals solution position (Counter Two)
            Add one to (Wrong Place)
         ENDIF
      ENDIF
   UNTIL (Counter Two) equals four
UNTIL (Counter One) equals four&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;So now (Wrong Place) holds the number of balls that are the right colour, but in the wrong place.&lt;br /&gt;Or does it? &lt;/p&gt;&lt;p&gt;&lt;i&gt;The 'Gotcha'&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img height=&quot;144&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/1234.gif&quot; width=&quot;36&quot; /&gt; PICTURE 1-2-3-4 Guess &lt;img height=&quot;144&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/1551.gif&quot; width=&quot;36&quot; /&gt; PICTURE 1-5-5-1 Solution&lt;br /&gt;&lt;br /&gt;Have a look at this example. In your head, you know the correct solution is &quot;one in the right place.&quot; But if you follow through the steps above, you 'll get &quot;one in the right place and one in the wrong place.&quot; Why?&lt;/p&gt;&lt;p&gt;Because the red ball guessed in first place is not only counted in the 'right place' code, it is also counted in the 'wrong place' code by being matched up with forth ball in the solution.&lt;/p&gt;&lt;p&gt;One way to get round this is this simple rule that each guess ball can only be used once, as can each ball in the solution. So to facilitate this, we copy the guess and the solution into temporary arrays. When we match up balls in either the right place or the wrong place, we change the value in the array to something that wouldn't normally be there - we change a guess ball to 0, and a solution ball to 99. This way they cannot be counted again.&lt;/p&gt;&lt;p&gt;This is one example in how 'pseudo-code' can help you pick up bugs and logical flaws before you actually sit in front of the keyboard and start typing.&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;i&gt;The Completed Code&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;So, here we have all the above in OPL.&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;LOCAL foo%, gnu%,right_place%,wrong_place%
LOCAL foobar%(4),guessbar%(4)
rem *** Create a copy of the solution so we can remove balls
rem *** as there position is noted. Ditto with guess array
foo%=0
DO
   foo%=foo%+1
   foobar%(foo%)=solution%(foo%)
   guessbar%(foo%)=guess%(foo%)
UNTIL foo%=4
                     
rem *** check all balls are guessed
foo%=0
DO
   foo%=foo%+1
   IF guessbar%(foo%)=0 : giPRINT &quot;Not all spaces filled...&quot; : RETURN : ENDIF
UNTIL foo%=4
breakout%=99 : rem *** Eventull incdrement turn counter
                     
rem *** right pieces in right place
foo%=0
DO
   foo%=foo%+1
   IF guessbar%(foo%)=foobar%(foo%)
      right_place%=right_place%+1
      foobar%(foo%)=0 : rem remove from stemp solution
      guessbar%(foo%)=99 : rem remove from guess
   ENDIF
UNTIL foo%=4
IF right_place%=4 : rem Victory
   m_victory:
   RETURN
ENDIF
                     
foo%=0
DO
   foo%=foo%+1
   gnu%=0
   DO
      gnu%=gnu%+1
      IF guessbar%(foo%)=foobar%(gnu%)
         wrong_place%=wrong_place%+1
         foobar%(gnu%)=0
         gnu%=4
      ENDIF
   UNTIL gnu%=4
UNTIL foo%=4&lt;/pre&gt;&lt;pre&gt;giPRINT NUM$(right_place%,1)+&quot; in the right place, &quot;+NUM$(wrong_place%,1)+&quot; in the wrong place&quot;
                     
m_showguess:(right_place%,wrong_place%,turn%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;It's not called from the event loop yet (but it shouldn't be that hard to figure out how), and we haven't yet got around to displaying the generated result. All that will be covered in Part 8.&lt;/p&gt;&lt;p&gt;But as with everything, you should be able to get down and do it yourself, so if you want a little challenge over the next fortnight... away you go!&lt;/p&gt;&lt;p /&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:56:00 +0100</pubDate>
        </item>
        <item>
            <title>Part 6: Cursor Control</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=13</link>
            <description>&lt;p&gt;&lt;b&gt;Principles of Movement&lt;br /&gt;&lt;/b&gt;&lt;i&gt;How It Works, Part One, Playing in the Sand&lt;/i&gt;&lt;br /&gt;Picture a children's play pit full of sand. It is perfectly smooth. Now, assuming you were invisible how would you make a small hole appear to run from one side of the pit to the other?&lt;/p&gt;&lt;p&gt;One way to do it would be this. Use your finger to make a hole and let everyone see it. Then, as quickly as possible, fill the hole in and make another one just to the side of where the first one was. If you do this over and over again, really quickly, what will someone watching the sand see?&lt;/p&gt;&lt;p&gt;A hole moving across the sand.&lt;/p&gt;&lt;p&gt;And that's exactly how movement and animation work in a computer program&lt;/p&gt;&lt;p&gt;&lt;i&gt;How It Works, Part Two, Pixelating the Play Pit&lt;/i&gt;&lt;br /&gt;So, if we have a blank (white) screen, how do we move a black spot around the screen? Have a look at this snippet of code...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt; gUSE id%(9)
 foo%=0
 DO
    gAT 200,foo%
    gCOPY id%(1),0,0,20,20,1 : rem clear the 'older' spot
    foo%=foo%+5
    gAT 200,foo%
    gCOPY id%(1),0,0,20,20,0 : rem copy the 'new' spot
 UNTIL foo%=200&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This code uses the basic building block of the DO... UNTIL... loop that increases a foo% counter. The first gAT... gCOPY clears away the old picture we've copied in (the picture being whatever mbm was gLOADED with id%(1) previously), and the second gCOPYs the mbm into the new location.&lt;/p&gt;&lt;p&gt;And that, in a nutshell, is how things move!&lt;/p&gt;&lt;p&gt;(I'll leave the relatively trivial exercise of how you'd adapt this to using a Mask and a Background Image to your imagination - it's not difficult to work out if you read Tutorial 5 closely).&lt;/p&gt;&lt;p&gt;&lt;i&gt;What sort of things can move?&lt;/i&gt;&lt;br /&gt;Have a think through the applications and you'll see movement in many different places. As with many of the principles you're seeing in this course, the above can be used in many different places.&lt;/p&gt;&lt;p&gt;Think of the tile blocks moving in Vexed. Think of the moving hand choosing cards in Card Deck. Think of the cursor moving through names and addresses in Contacts. All these use movements and masks - it's not difficult and it looks good. Which always key in a good application.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Displaying the Cursor in Master&lt;/b&gt;&lt;br /&gt;As you'll remember, we've broken the writing of our application into small areas to work on. You'll remember that on the game grid, up and down will move an on-screen cursor in the corresponding direction, selecting where to place a colour.&lt;/p&gt;&lt;p&gt;So in essence, we're going to write a small routine to move the cursor!&lt;/p&gt;&lt;p&gt;&lt;i&gt;Where are We Going to Go?&lt;/i&gt;&lt;br /&gt;Firstly, we need to know if the up and down cursor keys have been pressed. As this is reading a keyboard event, we look in PROC g_kbddrv:(.........). At the end of the procedure, add in the following code...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt; ELSEIF Key&amp;amp;=63593 : rem Cursor Up
    cursor%=cursor%-1
    IF cursor%=0 : cursor%=4 : ENDIF
    m_show_cursor:
ELSEIF Key&amp;amp;=63594 : rem Cursor Down
    cursor%=cursor%+1
    IF cursor%=5 : cursor%=1 : ENDIF
    m_show_cursor:&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Okay, so we've introduced a new variable here. cursor% (which we set in PROC init_game: to be equal to 1) keeps track of which row the cursor is currently in (the top row is 1, the bottom row is 4). When we move the cursor up or down, we change the value of cursor% to represent the new row, and then call the procedure that will display the cursor.&lt;/p&gt;&lt;p&gt;The IF... ENDIF statement in the middle checks to see if we have moved down while on the bottom row, or moved up when on the top row. If we have, the value of cursor% is set to the opposite end, so the cursor effectively wraps round the rows.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Showing The Cursor&lt;/i&gt;&lt;br /&gt;Once we move the cursor, we call this procedure...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC m_showcursor:
   gUSE id%(1) : rem Make sure we are using the main window
      rem *** clear the old cursor away by blanking the square, and
      rem *** copying the ball back into the square.
   m_showball:(turn%,old_cursor%,0)
   m_showball:(turn%,old_cursor%,guess%(old_cursor%))
      rem *** Now copy the cursor mask, and the cursor itself.
   gAT (turn%*36)+5,((cursor%-1)*36)+5
   gCOPY id%(11),36,0,36,36,1 : rem *** Copy the Mask, clearing pixels
   gCOPY id%(11),72,0,36,36,0 : rem *** Copy the cursor into the pixels
   old_cursor%=cursor%
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;i&gt;Time to Test!&lt;/i&gt;&lt;br /&gt;If you were writing Master yourself, then now is a good time to translate and see if the cursor moves up and down. If you're keeping up with Master, have a look at the code at the end of the tutorial and you'll see where the above fits in.&lt;/p&gt;&lt;p&gt;The tutorials cannot explain everything, but I'm aiming to cover the broad principles here, and then hope you look at the downloadable source code at the end of the tutorials to see how it all fits together.&lt;/p&gt;&lt;p&gt;What we are doing in Master is creating a 'toolbox' of techniques that you'll hopefully be able to apply to your own programs.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Making a Guess&lt;/b&gt;&lt;br /&gt;For each turn, we are going to hold the temporary guess an array called guess%(4). Once we've guess the four balls, we'll hit enter and see how good our guess is. At the start of the turn, we'll set the four array elements to zero. This is so we can check that the player actually puts 4 colours into the guess (i.e. all four values are non zero).&lt;/p&gt;&lt;p&gt;&lt;i&gt;Left and Right, Red or White?&lt;/i&gt;&lt;br /&gt;We've already got our cursor moving up and down, so now we add in the left and right cursors into the PROC g_kbddrv:...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;ELSEIF Key&amp;amp;=63591 : rem Cursor Left
   guess%(cursor%)=guess%(cursor%)-1
   IF guess%(cursor%)&amp;lt;1 : guess%(cursor%)=(skill_level%*2)+2 : ENDIF
   m_showball:(turn%,cursor%,guess%(cursor%))
ELSEIF Key&amp;amp;=63594 : rem Cursor Down
   guess%(cursor%)=guess%(cursor%)+1
   IF guess%(cursor%)&amp;gt;(skill_level%*2)+2 : guess%(cursor%)=1 : ENDIF
   m_showball:(turn%,cursor%,guess%(cursor%))&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This is going to look pretty familiar to the movement code. You'll see you increase or decrease the value of the guess%() depending on the current cursor% value (1 through 4). Where the value of guess% is more than the number of balls to choose from, it loops back to one, and if it drops below one, then it loops to the highest value.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Remember those Skill Levels&lt;/i&gt;&lt;br /&gt;Yes, this highest value is determined by the skill level. The easy skill level (skill%=1) gives you 4 balls to choose from. Medium skill% (2) gives 6 balls, and Hard skill% (3) gives 8 balls.&lt;/p&gt;&lt;p&gt;In the same way we called the show cursor routine, we do the same here with the show ball routine, which we detailed off in the last tutorial. See, it's all falling into place now.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;So, &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/images/5/master.opl&quot;&gt;&lt;font color=&quot;#000000&quot;&gt;here's&lt;/font&gt;&lt;/a&gt; the OPL code as it stands just now. Copy this onto your Communicator (or into the emulator) and see how exactly we're doing everything.&lt;/p&gt;&lt;p&gt;MASTER is starting to look more and more like the finished product, isn't it? When you get to this part of your own future projects, you'll get a lovely thrill, because it's all working, and on the screen. If you've followed the course up to here, well done.&lt;/p&gt;&lt;p&gt;We're not stopping though. The next part is going to show us how to interpret the guess we've made, and then let the user have another guess.. and another... and another...&lt;/p&gt;&lt;hr size=&quot;1&quot; /&gt;&lt;b&gt;&lt;img height=&quot;48&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/oplicon.gif&quot; width=&quot;48&quot; align=&quot;left&quot; /&gt;Source Code&lt;/b&gt;&lt;br /&gt;You can download the OPL source code for Master as it is at the end of tutorial 5 &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/images/5/master.opl&quot;&gt;here&lt;/a&gt;. You can download the opo program (the runtime file) as it is at the end of tutorial 6 &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/images/5/master.opo&quot;&gt;here&lt;/a&gt;. &lt;hr size=&quot;1&quot; /&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:44:21 +0100</pubDate>
        </item>
        <item>
            <title>Part 5: Changing the Core</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=12</link>
            <description>&lt;p&gt;In which we'll make the first changes to Event Core and see the app starting to come together on our Communciators.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;First Steps with the Event Core&lt;/b&gt;&lt;br /&gt;Right, time to actually do some honest to goodness, real life coding. Either power up the emulator, or switch your phone on and set up the following using the File Manager.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Copy the master.mbm you created earlier into &amp;quot;\System\Apps\Master\&amp;quot; directory&lt;/i&gt;&lt;br /&gt;You may need to make this directory. The System\Apps folder is like the &amp;quot;Program Files&amp;quot; folder on a PC - each app has it's own directory (which must be the same name as the files the translated application will have; in this case &amp;quot;master&amp;quot; ). In the File Manager application you may need to change the preferences so you can see the System directory.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Create a top level directory called &amp;quot;Programming&amp;quot;&lt;/i&gt;&lt;br /&gt;Given time, you'll build your own programming practices and habits. In the meantime you'll be using a version of my own (with the arcane and obscure stuff removed). All my application work takes place in a Programming folder that is separate from the Documents folder.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Go into &amp;quot;Programming&amp;quot; and create a directory called &amp;quot;Master&amp;quot;&lt;/i&gt;&lt;br /&gt;Each application or project gets its own folder to keep everything organised.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Copy core.opl into this directory and rename it &amp;quot;master.opl&amp;quot;&lt;/i&gt;&lt;br /&gt;Now, you don't need to put that .opl at the back of the filename, but it means that code is easily recognisable from translated modules when you look at a directory. It is personal preference, and seeing as you're following me, you're stuck with it for a bit!&lt;br /&gt;Oh and if you've forgotten, the core.opl is available from &lt;a href=&quot;http://www.freepoc.org/core.htm&quot;&gt;&lt;font color=&quot;#000000&quot;&gt;http://www.freepoc.org/core.htm&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Editing core.opl to Make master.opl&lt;br /&gt;&lt;/b&gt;&lt;i&gt;Changing the identifiers&lt;/i&gt;&lt;br /&gt;Thanks to the use of constants, it's actually quite easy to alter the core.opl into your application. Open up the (now renamed to) master.opl and look at the constants listed at the start of the app. AT the moment they read as follows...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;CONST K_Author_Email$=&amp;quot;ewan@freepoc.org&amp;quot;
CONST K_Author_Name$=&amp;quot;Ewan Spence&amp;quot;
CONST K_App_Name$=&amp;quot;Core OPL&amp;quot;
CONST K_App_Ver$=&amp;quot;1.00&amp;quot;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;These four are all pretty self explanatory. Your email and name are used in any copyright notices and in the About This Application box. The App name is used in the Menus, title bars, about boxes, and anywhere else.&lt;/p&gt;&lt;p&gt;Put in whatever you feel appropriate here - and don't forget they are easy to change!&lt;/p&gt;&lt;p&gt;A quick word about version numbers here, when developing it is always a good idea to start off with 0.01, and leave version 1.00 for your first release. Before releasing an app, I just increment the numbers (0.01 is the first, 0.07 is the seventh major revision, 0.23 is the twenty third, etc.).&lt;/p&gt;&lt;p&gt;On release of any bug fixes increment by 0.01, so 1.01 is the first version, but with one bug fix release. Any small improvements that don't change the main points of the app (e.g. adding in more tile sets in Vexed, or a new batch of colours in Clock6) would take the version up to the next tenth (i.e. 1.01 would jump to 1.1, not 1.11. 1.11 is for the first big fix!).&lt;/p&gt;&lt;p&gt;Right, translate that by hitting the translate CBA button. Have a look round all the menu system and suchlike and you'll see all the relevant names, numbers, and emails are in place!&lt;/p&gt;&lt;p&gt;&lt;i&gt;Setting Toolbars and Titlebars.&lt;/i&gt;&lt;br /&gt;As discussed before, these are set (and stored) in the .ini file. If you don't alter them from those set in the Event Core, then you'll get an app with the CBA always visible,The title bar on, and the large status bar on the left.&lt;/p&gt;&lt;p&gt;Having a look through the PROC init: you'll find this line...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;AfSetTitle:(K_App_Name$,KAfTitleTypeMainTitle%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;...and because you've set K_App_Name$ in the constants section, you don't need to alter this either.&lt;/p&gt;&lt;p&gt;We'll get around to renaming the CBA's later on, but again you can see where they are set in PROC init: In the opl code at the end of the tutorial, you'll find the CBA's are working (so you can close the app) but I'll explain how in the next part. In the meantime, you can have a look at it yourself and see if you can work it out.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Loading Graphics&lt;/i&gt;&lt;br /&gt;If you have a look back to Part 3, you'll recall how we gCREATE'd and gOPEN'd graphical windows and bitmaps. Any global graphics (windows or bitmaps) are created at the end of PROC init:. When I program, I usually use the GLOBAL id%(16) to hold all my graphical elements. I also tend to use id%(1) to id%(8) for windows and id%(9) to id%(16) for bitmaps.&lt;/p&gt;&lt;p&gt;It's always a good idea to use REM statements, but I think it doubly important here, because the graphical elements are something you may constantly use and need a ready reference for.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Translate and Check&lt;/i&gt;&lt;br /&gt;Once you've edited PROC init: of the core, this is usually a good time to translate the OPL code and see that yo haven't made any mistakes. While you could write your whole app before translating, if you build up the app logically (remember the story analogy) you should be able to check it after each major section for change. Then if you do have problems, it's likely to be in the most recently typed in code.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Working With The Main Screen&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Master has one main screen, displaying the ten guesses, the solution, and the winning pattern on the far right. What we'll do now is lay out these grids, ready to start playing in Part 6. &lt;br /&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img height=&quot;200&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/desktop.jpg&quot; width=&quot;640&quot; border=&quot;1&quot; /&gt; &lt;/p&gt;&lt;p&gt;&lt;i&gt;Showing balls&lt;/i&gt;&lt;/p&gt;&lt;p&gt;This section here is damm important. I've had a quick look back at my older Series 5mx apps, and a variant of this procedure features in the last 5 applications I've programmed, so in my mind it's an important principle, and the foundations have already been laid.&lt;/p&gt;&lt;p&gt;One key in computer code is being able to re-use code whenever possible, especially if you end up doing the same thing over and over again. In Master, you're going to be showing a lot of balls, all over the screen. How do we do this? Like this:&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC m_showball:(foo_turn%,pos%,ball%)
   gUSE id%(1)
   gAT (foo_turn%*36)+5,((pos%-1)*36)+5
   gCOPY id%(10),36,0,36,36,1 : rem * Mask
   gCOPY id%(10),(ball%+1)*36,0,36,36,0 : rem * Ball
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Now whenever we need to print a ball, we call this procedure, and pass it three values.&lt;/p&gt;&lt;p&gt;The first is foo_turn%, which lets the procedure know what column of the grid to use (from 1 to 10), depending on what turn of the game it is. We don't use the main turn variable as we may want to print out of position at somepoint.&lt;/p&gt;&lt;p&gt;Value two (pos%) gives the row in which we should print the ball (1 to 4).&lt;/p&gt;&lt;p&gt;Ball% gives the number of the ball which is 1 to four (on easy skill) up to 8 (on hard skill). Ball%. Can also take the value of zero, which will display a blank square.&lt;/p&gt;&lt;p&gt;We then use those numbers in the gAT ( coordinate, y coordinate) to move the cursor to the correct starting pixel for our two gCOPY commands.&lt;/p&gt;&lt;p&gt;Why have we not used one gCOPY command? It's because we have a background. If you copy the square that contains the ball directly into the grid, (gCOPY with a (3) the in the white spaces around the ball are copied as well, obscuring the background.&lt;/p&gt;&lt;p&gt;If you use the gCOPY flag (0) that only sets the pixel, you'll fin the background image interferes with the colours.&lt;/p&gt;&lt;p&gt;The solution is in two steps - one per gCOPY command. Have a glance at the single mbm graphic that holds all the coloured balls. The first square is a ball that is all black, with no shading on markings. This is a mask. If you look at this next to one of the true ball icons, you'll see that every black pixel in the mask corresponds with a black or coloured pixel in the real graphic.&lt;/p&gt;&lt;p&gt;If we now use gCOPY flag (1) - which is 'clear pixels' all the pixels that are black in the mask will be cleared from the main window. This is our first gCOPY command above.&lt;/p&gt;&lt;p&gt;We can now safely use the gCOPY flag (0) that only sets the pixels, because the pixels that are being set, are all being set on cleared white pixels! And voila! We can now copy our coloured ball into place, and leave the rest of the background intact.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Showing Spaces&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Hold on though. In the application the procedure looks like this.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC m_showball:(foo_turn%,pos%,ball%)
   gUSE id%(1)
   gAT (foo_turn%*36)+5,((pos%-1)*36)+5
   IF ball%=0
      gCOPY id%(9),foo_turn%*36)+5,((pos%-1)*36)+5,36,36,0
      gCOPY id%(10),0,0,36,36,0
   ELSE
      gCOPY id%(10),36,0,36,36,1 : rem * Mask
      gCOPY id%(10),(ball%+1)*36,0,36,36,0 : rem * Ball
   ENDIF
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This is because we need to do something slightly different when we want to clear a ball. We don't want to punch a hold in the background image (or overwrite a ball already there). What we want to do is restore a portion of the background image (the first gCOPY line) and then copy the grid line from the mbm (the second gCOPY).&lt;/p&gt;&lt;p&gt;&lt;i&gt;Laying out all the Boxes&lt;/i&gt;&lt;/p&gt;&lt;p&gt;So, now we have all the elements to draw the grid on the screen. Almost. Two new commands for you to look at.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;gBOX width,height&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This draws a box, with the top left corner where your cursor is at (remember this is changed by gAT x,y).&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;gLINEBY x_distance,y_distance&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This draws a line from the cursor to a point that is x_distance to the right, and y_distance down. If you use negative numbers, then it is to the left and up respectively.&lt;/p&gt;&lt;p&gt;Lets look at the procedure...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC init_display:
   LOCAL foo%
   rem *** Copy the background into the main window.
   gUSE id%(1)
   gAT 0,0
   gCOPY id%(9),0,0,548,200,3
   rem *** Draw the squares of the grid using supplied bitmap
   foo%=-1
   DO
      foo%=foo%+1
      m_showball:(foo%,1,0)
      m_showball:(foo%,2,0)
      m_showball:(foo%,3,0)
      m_showball:(foo%,4,0)
      m_showguess:(0,0,foo%)
   UNTIL foo%=9
   rem *** Draw the outside of the grid and the solution boxes
   gAT 5,5 : gBOX 360,145 : gAT 5,157 : gBOX 360,37
   gAT 398,5 : gBOX 37,145
   gAT 398,41 : gLINEBY 36,0
   gAT 398,77 : gLINEBY 36,0
   gAT 398,113 : gLINEBY 36,0
   gAT 398,157 : gBOX 37,37
   gVISIBLE ON
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The rem statements show what's happening in each section. Note the use of a DO... UNTIL... loop to make our life easier for the largest grid. In the loop, we draw both the guessing grid (on the top) and the how well we did grid (on the bottom). Because of how our mbm is laid out, we need to draw in manually the right hand edge and bottom edge.&lt;/p&gt;&lt;p&gt;Finally, we draw the column on the far right that we will use to show the correct solution when our ten guesses are up, or when we correctly guess the solution.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Showing Guesses&lt;/i&gt;&lt;br /&gt;Have a quick look at PROC m_showguess%:(right_place%,wrong_place%,foo_turn%). When we come around to doing the part of the program that needs to show how accurate the guess is, we'll use this procedure.&lt;/p&gt;&lt;p&gt;But we'll also use it to show a blank space, and this is the only part of the procedure currently listed. It's the same theory as showing a blank space in the PROC m_showball:&lt;/p&gt;&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt;&lt;p&gt;So, if you run Master now, you should see the main grid. Okay we can't see any balls, even though we've discussed how we're going to do it in this part, but relax. Next week you'll see how to put a cursor onto the screen, move it around, and use it to select your four coloured balls to make a guess!&lt;/p&gt;&lt;hr size=&quot;1&quot; /&gt;&lt;b&gt;&lt;img height=&quot;48&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/oplicon.gif&quot; width=&quot;48&quot; align=&quot;left&quot; /&gt;Source Code&lt;/b&gt;&lt;br /&gt;You can download the OPL source code for Master as it is at the end of tutorial 5 &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/images/master.opl&quot;&gt;here&lt;/a&gt;. You can download the opo program (the runtime file) as it is at the end of tutorial 5 &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/images/master.opo&quot;&gt;here&lt;/a&gt;. &lt;hr size=&quot;1&quot; /&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:42:58 +0100</pubDate>
        </item>
        <item>
            <title>Part 4: Creating the MBM's</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=11</link>
            <description>&lt;p&gt;&lt;b&gt;Creating MBM's&lt;/b&gt;&lt;/p&gt;&lt;p&gt;If you go back to our sketch of what we wanted Master to look like, then you should be able to break it down into windows and bitmaps. The window part is the easiest. The outside status bars, titles and CBA bars are something controlled from code, and do not need graphical windows. Our main display can be represented by one window (in fact, it needs to be as it will have the background).&lt;/p&gt;&lt;p&gt;Looking at the bitmaps we'll need, we find the following...&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;The FreEPOC Logo&lt;/i&gt;&lt;br /&gt;Standard FreEPOC practice is to have the FreEPOC logo available as the first bitmap in any mbm, even if it is not shown in the program. If you have your own logo, this is a good place to put it.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;The Program Icon&lt;/i&gt;&lt;br /&gt;Used in the About box, this will be the same as the icon we eventually use to represent the program in the Extras screen. we'll do that later in the course, but for the meantime, we still need the large size available as a bitmap. This is it.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;The Balls&lt;/i&gt;&lt;br /&gt;Cunningly, we store all our balls in one strip, along with an initial blank grid square in the first space, and a 'mask' in the second space we can use to punch out a hole in the background wallpaper so the balls can be copied over to preserve the background. This technique will be discussed later in it's own section, because it's really important and something you can use in pretty much any application.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;The Clues&lt;/i&gt;&lt;br /&gt;In a similar way to the Balls bitmaps, this is the bitmap that gives the user the clues to what is in the right place and in the wrong place.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;The Cursor&lt;/i&gt;&lt;br /&gt;used to move up and down the grid so the user can see what ball they will change.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Background Wallpaper&lt;/i&gt;&lt;br /&gt;Pretty self explanatory. The wallpaper here is a simple blue sheet of paper, but you can substitute whatever you want. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Create your bitmaps in any graphics application (personally I use Windows Paint, it gives you pixel perfect control - but anything will do). Save them as Windows/OS2 bitmaps into an easily findable folder. To get you started, &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/images/master-balls-source.zip&quot;&gt;here's a download of the bitmaps&lt;/a&gt; we'll use in Master, although you're free to design your own!&lt;/p&gt;&lt;p&gt;&lt;b&gt;Using MBM Whizard&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Dazler has programmed a GUI for the Symbian utility bmpconv.exe which is normally used for creating and opening mbm files on the PC. You can download MBM Wizard from &lt;a href=&quot;http://nokia.warlocks.be/&quot;&gt;&lt;font color=&quot;#000000&quot;&gt;Dazler's Nokia&lt;/font&gt;&lt;/a&gt; site. On this site there is the program itself as well as a very useful tutorial on how to use both bmpconv and MBM Whizard.&lt;/p&gt;&lt;p&gt;Using MBMWhizard is very straight forward. MBM Whizard is a Windows GUI for Bmconv. It allows you to quickly create/update archives and even browse them. All the functions of MBM Whizard are a combination of bmconv commands. Only the converting of images from Jpg,Gif and Bmp to bmp is done by MBM Whizard.&lt;/p&gt;&lt;p&gt;When you open MBM Whizard you will be presented with a new project. You can now include files in the project and specify their colour. After this you can use Save/Save as to make the mbm file. You can start a new project at all time by selecting New in the File menu.&lt;/p&gt;&lt;p&gt;Go and have a play with MBMWhizard - it should be obvious how everything works, and if it is now - then there is some great documentation with the program.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt;&lt;p&gt;It's hard to belive, but you've now coded almost everything you will see in Master. Planning the program before starting to code means that all we have left is to change the Event Core to reflect the new app, add in the subroutines for key presses and events and we'll have the app running to a good standard. That should take us over the next two or three lessons!&lt;/p&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:41:17 +0100</pubDate>
        </item>
        <item>
            <title>Part 3: Designing the Application</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=10</link>
            <description>&lt;strong&gt;Fail to Plan, Plan to Fail&lt;br /&gt;&lt;/strong&gt;It's an old adage, but it holds true in program design more than anywhere.&lt;p&gt;One of the aims of this tutorial series is to show you how to create your own OPL application that you can distribute yourself. To do this, we're going to design a game from scratch, and using the Event Core, build it up into a full application before your very eyes.&lt;/p&gt;&lt;p&gt;We're going to build a logic game called &lt;b&gt;Master&lt;/b&gt;. Based on the board game Mastermind, there is a 4 colour code that you need to guess. When you make a guess, you are told how many colours are right in the right place, how many are in the wrong place (but are in the final code) and how many are colours are not in the final code. You get 10 guess and if you don't work out the code, then you loose!&lt;/p&gt;&lt;p&gt;Just to reiterate, there is no right or wrong way to go about designing and coding an application. This way is the way that I have found to be best for me. If you want to change anything, or do things in a different order, then feel free. &lt;/p&gt;&lt;p&gt;&lt;b&gt;How to Play Master&lt;/b&gt;&lt;br /&gt;What you need to do now is break down the application into smaller sections - each section will consist of a few procedures, and individual steps in these sections will probably be the individual Procedures.&lt;/p&gt;&lt;p&gt;If we go back to our story metaphor, you're breaking the application down into chapters and paragraphs so that the translation into OPL code is easier then if you tried to write it straight down onto a blank sheet of paper.&lt;/p&gt;&lt;p&gt;&lt;i&gt;User Interface&lt;/i&gt;&lt;br /&gt;Put simply, what does it look like? Take a few seconds to sketch some ideas out on some paper. Don't worry that you don't know how to work the graphics yet, what you want is a flavour of your aim. We can improve it later.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img height=&quot;273&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/sketch.jpg&quot; width=&quot;430&quot; border=&quot;1&quot; /&gt;&lt;br /&gt;&lt;i&gt;Master's initial UI sketch&lt;/i&gt;&lt;/p&gt;&lt;p&gt;One other thing you need to decide is what information bars will be permanently on screen. You can choose from the CBA side buttons (on the right), the Title bar (along the top), and the Status bar (on the left). For Master, we'll show all three, and these will be specified in the initial .ini file settings in the code (PROC LoadINIFile:)&lt;/p&gt;&lt;p&gt;Note that many applications allow you to change the toolbars being on or off from within the program. We will look at this at a later date, but for the moment, let's leave them fixed. Once you've worked on a few of your own applications, it will become a lot clearer.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Background Wallpaper&lt;/i&gt;&lt;br /&gt;One thing that will make &lt;b&gt;Master&lt;/b&gt; stand out is the program will not be played out on a white screen, but will have a background 'desktop' style image. Not only will this teach you different graphics techniques, but it also adds to the appeal of the application.&lt;/p&gt;&lt;p&gt;Never underestimate the power of something simple to improve an application in the eyes of the user. In the game &lt;b&gt;Quad&lt;/b&gt;, at the last minute I added a small routine that showed (over 4 windows that displayed a simple graphics and a few lines of text) the basic principles of the game. It was only shown the first time the game was opened (although it could be called from the menu at any point). While all this information was in the help file (as it should be) almost every review highlighted this tutorial as an amazingly helpful feature. For the small amount of effort, the rewards to the user and the programmer were immense. Take note.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Controls&lt;/i&gt;&lt;br /&gt;The user will have five controls, the cursor keys and space to select a colour. On the game grid, up and down will move an on-screen cursor up and down, selecting where to place a colour. Using left and right will cycle through the colours. Pressing space will make a guess with the listed colours.&lt;br /&gt;As well as this, the menu will the basic menu entries that the Event Core has. In addition to this, it will also have options to select the difficulty level of the the game&lt;/p&gt;&lt;p&gt;&lt;i&gt;Difficulty Levels&lt;/i&gt;&lt;br /&gt;The easiest way to increase the difficulty of the game is to increase the number of coloured balls. So the easy skill level will have 4 colour, the medium will have 6, and difficult will have 8. &lt;/p&gt;&lt;p&gt;&lt;b&gt;Using Graphics in OPL&lt;/b&gt;&lt;br /&gt;It's been a long time since computers only had text characters to display on the screen. Now you can create and manipulate small pictures to create a much clearer display for the user. It has also made computers easier to use (although Command Line Interfaces like DOS and the Linux Console still have their place).&lt;/p&gt;&lt;p&gt;Anyway, you have two basic graphical elements in OPL. When you initialise them, each item is given a reference number by the computer. Rather than remember these arcane numbers (and they can change each time a program is run), you can hold them in an array. In the Event Core, the array id%() is used, so you can use id%(1), up to whatever the maximum number you defined in the GLOBAL id%(x). 16 is probably more than enough.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Windows&lt;/i&gt;&lt;br /&gt;A window is where you will place your graphics. Consider it the sheet of paper you're going to work with. One of the great things about windows is you can have more than one of them, so if your screen is split into two views then you could have this made up by a window on the left, and a window on the right.&lt;/p&gt;&lt;p&gt;You must create a window before using it. When you create it, the window number is RETURNED from the command, and it is this number you store in the id%() array...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;id%(1)=gCREATE 0,0,640,200,K_Const_256Colours,1&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;How it works. The first pair of numbers (0,0 in the example) represent the top left corner of the window. In the case of (0,0) this means the window starts at the very top left of the Communicator screen. These co-ordinates are in (x,y) format, so (320,20) is halfway across the screen, 20 pixels from the top of the screen.&lt;/p&gt;&lt;p&gt;The next pair of numbers (640,200) represent the width of the window (here 640 pixels) and the height of the window (200 pixels).&lt;/p&gt;&lt;p&gt;The second last number isn't a number at all! Here it's part of the default Constants. This number decides how many individual colours a window can show. While the Communicator can support up to 4096 colours, for all practical purposes 256 colours will be more than enough. There may even be circumstances where you want to allow less colour in a window, dropping to 16 colours, or even black and white monochrome if it is a text only window. The main reason for this is that the less colours required in a window, the less memory it takes up.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Bitmaps&lt;/i&gt;&lt;br /&gt;Your bitmap is the graphic that you make up in a graphics package and include with your application. You can have lots of little pictures, or one big one and copy over only the part you need onto the paper (the window). The first thing you need to do is load the bitmap into the memory of the machine. Just because it has been copied onto the disk, that doesn't mean the program can see it.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;id%(9)=gLOADBIT(&amp;quot;D:\System\Apps\Master\Master.mbm&amp;quot;,0,3)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This will load the bitmap from the file master.mbm in the directory D:\System\Apps\Master\ . The two numbers at the end are very important, and will change depending on the file.&lt;/p&gt;&lt;p&gt;The second number (3), tells the computer what bitmap to use from the MBM file. MBM files can hold Multiple Bitmaps (hence .mbm). The first bitmap is bitmap 0, the second is bitmap 1, and so on.&lt;/p&gt;&lt;p&gt;The first number determines if you can alter or edit the bitmap within the program. Unless you are doing an art package, or need to manipulate the mbm for some reason, you would leaves this as &lt;b&gt;read only&lt;/b&gt;, which is 0. (to be able to edit, put a 1 here).&lt;/p&gt;&lt;p&gt;&lt;i&gt;Closing Graphical Elements&lt;/i&gt;&lt;br /&gt;Whenever you finish with a graphical Window or Bitmap, you should close it. This makes sure that memory is reclaimed by the computer, and your application is more effective. This is done simply by&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;gCLOSE id%(foo%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Where foo% is the array index number. A good idea at the end of every application (in PROC exit:) is to double check all the elements are closed.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;foo%=0
DO
   foo%=foo%+1
   TRAP gCLOSE id%(foo%)
UNTIL foo%=16
REM *** Where 16 is the number of elements defined in the id%() array.&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;TRAP will, of course, make sure an error is not raised if the graphical element isn't opened.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Copying MBM's To Windows&lt;/b&gt;&lt;br /&gt;Let's break down the command that allows you to copy bitmaps to windows.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;gUSE id%(1)
gCOPY id%(9),100,0,40,50,3&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The first command (gUSE) tells the computer what graphical window is to be made the current window. When you gCREATE a new window, it is automatically made the current (or active) window, but it is always best to use the gUSE command before any graphical operation.&lt;/p&gt;&lt;p&gt;Now the gCOPY command. The first number, id%(9) tells the computer which bitmap is to be copied from, into the current window. You now specify an area of that bitmap to copy. The next two numbers (100,0) say where the top left corner is (in pixels), measured from the top left corner of the bitmap.&lt;/p&gt;&lt;p&gt;&lt;img height=&quot;100&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/3-01%20gCopy%20Example.gif&quot; width=&quot;160&quot; align=&quot;left&quot; /&gt;The next two numbers (40,50) specify the width and the height of the portion of the bitmap which is to be copied.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;The image to the left shows an example of the gCOPY process described above.&lt;/i&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;The final number determines how the bitmap is to be copied. Here's the different ways you can copy images. The checkerbboard is being gCOPY'ed in these examples onto the straight lines, and only the final number is changed to show you what you can do.&lt;/p&gt;&lt;table cellspacing=&quot;2&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; align=&quot;center&quot; border=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr align=&quot;center&quot;&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;i&gt;Mode 0 (Set)&lt;/i&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;i&gt;Mode 1 (Clear)&lt;/i&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;i&gt;Mode 2 (Invert)&lt;/i&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;i&gt;Mode 3 (Replace)&lt;/i&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr align=&quot;center&quot;&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;img height=&quot;50&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/3-02%20Mode%200%20Set.gif&quot; width=&quot;165&quot; /&gt;   &lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;img height=&quot;50&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/3-02%20Mode%201%20Clear.gif&quot; width=&quot;160&quot; /&gt;   &lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;img height=&quot;50&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/3-02%20Mode%202%20Invert.gif&quot; width=&quot;169&quot; /&gt;   &lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div align=&quot;center&quot;&gt;&lt;img height=&quot;50&quot; src=&quot;http://www.allaboutsymbian.com/develop/opl/images/3-02%20Mode%203%20Replace.gif&quot; width=&quot;160&quot; /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;b&gt;Time To Rest&lt;/b&gt;&lt;br /&gt;It may seem like that for the last three lessons, you've been reading and there is very little practical examples of what I promised. Well, in the next lesson, we're going to construct the mbm file for Master, and start the coding in earnest!&lt;/p&gt;&lt;p&gt; &lt;/p&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:39:25 +0100</pubDate>
        </item>
        <item>
            <title>Part 2: Understanding the Event Core</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=9</link>
            <description>&lt;strong&gt;Where to get the Event Core&lt;br /&gt;&lt;/strong&gt;The Event Core we're using is provided by FreEPOC. It can be downloaded from their website (&lt;a href=&quot;http://www.freepoc.oeg/core.htm&quot;&gt;www.freepoc.org/core.htm&lt;/a&gt;). You should download this so you can look through the OPL code as we discuss it here. Intallation instructions (for OPL) are in &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/oplsdk.php&quot;&gt;this tutorial&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;&lt;b&gt;Building Blocks: Procedures (Again)&lt;/b&gt;&lt;br /&gt;Right then, in the last lesson, you got to grips with procedures. Before we move on to look at the Event Core, I'm going to show you how to make Procedure a bit more efficient. Have a look at this.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC addition:(one%,two%)
   LOCAL foo%
   foo%=one%+two%
   RETURN foo%
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Now this is a silly simple procedure that doesn't do much that couldn't be done in a single line of code, but it shows you two more principles. And you should be able to see how more complicated work can be done inside the procedure.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Passing Variables to Procedures: Local Constants.&lt;/i&gt;&lt;br /&gt;Where we've named the procedure we've added two integers inside some brackets. When you call the Procedure you need to supply these two numbers like this...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;addition:(200,100)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;or...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;addition:(number%,300)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;one% and two% don't need to defined as variables, because they aren't variables. They're constants that only exisit inside a single procedure. Think of them as the LOCAL variant of a constant. After you leave the procedure, their value is lost - and this is why you need to pass a number to the procedure every time you call it (although obviously it can be different every time!)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Returning Variables from Procedures&lt;/i&gt;&lt;br /&gt;Here's something handy. If instead of calling our addition subroutine by a simple line, if we call it like this...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;gnu%=addition:(100,200)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;...we can make gnu% equal the number that we RETURN from the addition procedure. When you work through a procedure and come across the RETURN statement, the program does not read the rest of the lines in the procedure, but returns immediatly, as if the ENDP line had been ready.&lt;/p&gt;&lt;p&gt;If you don't give a RETURN and ENDP is reached, then ENDP will return the number 0.&lt;/p&gt;&lt;p&gt;&lt;b&gt;How The Program Story Unfolds&lt;/b&gt;&lt;br /&gt;In part one I asked you to think of OPL as a language. I want to continue this analogy and ask you to think of your program as a story. Like any good fictional construction, you need three parts to any story. The beginning, the middle and the end.&lt;/p&gt;&lt;p&gt;The begining of your OPL Program will gather information about the computer and about the personal preferences that the user is using in the program. It will then go on to set up any graphics the program needs. Finally, it will draw the main screen, and have everything ready for the middle.&lt;/p&gt;&lt;p&gt;The middle of the program is where all the fun happens. It's based round running a simple looping routine which checks for keypress and messages from the computer, processng these keypresses, checking the results, and going around the loop again until the program has to stop&lt;/p&gt;&lt;p&gt;The end of the program cleans up things that shouldn't be left behind, saves any changes to the preferences, saves any data that may need saved, and exits the program.&lt;/p&gt;&lt;p&gt;So, you'll get something like this in the main procedure...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC main:
   GLOBAL exit%
   initialise:
   exit%=0
   DO
      main_loop:
   UNTIL exit%=1
   clean_up:
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Notice how we use a variable that can be set anywhere within the main_loop: to exit the program. This is so that the computer can always finish what it needs to do, come back to the main procedure, and then move to the clean_up: procedure to make sure everything is saved.&lt;/p&gt;&lt;p&gt;Let's look at what happens in each section in more detail. It might be an idea to open the event core OPL code (core.opl) so you can follow the code through, we'll only brush on the highlights here.&lt;/p&gt;&lt;p&gt;&lt;b&gt;The Begining&lt;/b&gt;&lt;br /&gt;The majority of the work is carried in the Event Core's initialise: routine in the following order.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Where Are All The Files&lt;/i&gt;&lt;br /&gt;First we check to see if we can locate the 'support' files for the running app. As almost every app you'll program will have some graphics, this section is dedicated to looking for the graphics .mbm file. Using the name of the applicaction specified in one of the constants (look at the very top of the code for these), we look through first the C: (internal disk) and then D: (the MMC card). If we find it, then we save the location in both path$ and data$. Path$ includes the drive the .mbm file is on, and data$ stores it without the drive information (you'll see why in a second).&lt;/p&gt;&lt;p&gt;You'll notice that this check uses the IF... ELSE... ENDIF... loop we discussed in part one, but we add in an extra IF check using ELSEIF. In this way you can have as many decisions as needed in an IF statement.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Personal Preferences - .ini Files&lt;/i&gt;&lt;br /&gt;Now we load in the users personal preferences. These are stored in core.ini (or whatever the application's name is). We goto PROC LoadINIFile:. If the file exists, we open the file. If it doesn't exist, we enter some default values, and then immediatly save them.&lt;/p&gt;&lt;p&gt;This is where we use data$, as .ini files should always be stored on the internal disk (hence &amp;quot;C:&amp;quot;+data$). In the core, we only have one preference, which is the sound volume. The .ini file is in fact a small database. Each of these databases is allocated a letter when opened, and then each field is given a temporary label...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;OPEN &amp;quot;C:&amp;quot;+data$,A,label%&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;So we're opening our applications .ini file on the c drive, we'll refer to it as database &amp;quot;A&amp;quot; and the only field is going to be temporarily refered to as sound_vol%.&lt;/p&gt;&lt;p&gt;We can now set the application variable to that in the database with the line...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;sound_vol%=A.sound_vol%&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Note how we use the database letter and the label. It's good practice to give the labels the same name as the variable in the application, but it is not a requirement.&lt;/p&gt;&lt;p&gt;And when we're finished, we CLOSE the database. You should always close things when you're finished with them. It means you use less memory, and your application will run faster.&lt;/p&gt;&lt;p&gt;Saving the preferences is a very similar process. Firstly we ake sure the directory exisits on the C drive. Once we're sure this is made, we DELETE the old (un-needed) .ini file, CREATE a new one and set the values.&lt;/p&gt;&lt;p&gt;Once all the values are set, we must save the changes into the database by using the APPEND function. This adds the information to the end of the database. As it is a new database (we deleted the old one) then it will always be the first record. We then CLOSE in the same way as before.&lt;/p&gt;&lt;p&gt;You'll notice the use of TRAP as a keyword. TRAP simply suppresses any error messages that may occur from the command on the rest of the line. This way, if the directory we are trying to create already exists, our program won't panic and stop, but will carry on.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Setting Screen Sizes and Toolbars&lt;/i&gt;&lt;br /&gt;Whenever an OPL program is started, it will immediatly create for itself a blank window taking up the full size of the screen. Now, some programmers will use this window, others will leave it sitting in the background, and some will change its size so it hides anything behind it, but isn't actually used for anything. This is the approach our Event Core uses...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;gDEFAULTWIN x,y,width,height&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;is where we alter the default window. (x,y) determines where the top left corner of the default window is (in relation to the top left of the screen), and width and height change the dimensions of the window.&lt;/p&gt;&lt;p&gt;The width of the whole screen is 640 pixels. Looking at the left hand toolbar, this can either be off (0) or on (1). The size is set by the type, small (1, which is 32 pixels wide) or standard (0, which is 96 pixels wide)...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;AfSetStatus%:(AfStatusType%)
AfSetstatusVisible%:(AfStatusOn%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The right hand CBA button can be either always visible (1), or only show up when a CBA button is pressed (0). The width is between 80 and 130 pixels, depending on how long the text labels for the buttons are.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;AfSetCBAVisible%:(AfCVA%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The title bar is the blue title that stretches along the top. It is XX pixels high. Set is as being visible (1) or hidden (0) with...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;AfTitleVisible%:(AfTitleOn%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;You can also specify what text is shown in the title bar with the folowing command, Note that you would normally have the program's name in the title bar. Note the Constant used from the standard external file to say it is the main title.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;AfSetTitle:(&amp;quot;Title Here&amp;quot;,KAfTitleTypeMainTitle%)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;All the above values for these bars are held by Event Core in the .ini file. At the moment, you decide what bars are shown by your app when you code it, and they do not change. Later on, you may want the user to be able to decide what they want to see or not see, so you will need those values stored in the .ini. This is a good example of thinking ahead when programming, even if (in the end) it is something you never use.&lt;/p&gt;&lt;p&gt;Now, to start our display, we create one window that fits within the the tree bars (status, title, cba) if they are open or not. This is the primary screen and we'll do most of our work in here. Just to prove that it is working, we also copy the FreEPOC logo into the window from an external graphics file. We're taking a detailed look at graphics commands in the next part, so for the meantime I'll leave these unexplained. See if you can work out what's going on!&lt;/p&gt;&lt;p&gt;&lt;b&gt;The Middle&lt;/b&gt;&lt;br /&gt;Rather than the simple loop shown at the start of this part, our Event Core has two DO... UNTIL loops, one within the other (this is called a nested loop). This is to help with applications that are on a 'level by level' design (eg Vexed). What happens is the 'outside loop' reads something like this...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;exit%=0
DO
   load_the_next_level:
   initialise_level:
   level_completed%=0
   DO
      play_the_game:
   UNTIL level_completed%=1
UNTIL exit%=1&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;From this, you'll see that this makes a lot more sense, is easier to read, and keeps your app as small and easy to follow (and program) as possible.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;The Main Event Loop&lt;/i&gt;&lt;br /&gt;This is scary stuff, and there is no simple way to ease you into it. The best you can do is understand what is going on, and leave it at that.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Commands From The System&lt;/i&gt;&lt;br /&gt;Firstly, the program checks to see if it has been told to do anything by the computer. The computer sends messages in a text string, and you retrieve this with...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;c$=GETCMD$&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Three options concern you...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;IF LEFT$(c$,1)=KGetCmdLetterExit$
   Exit:&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;This is self explanatory, and tells the app that it is to close immediatly. We could use the OPL command STOP here which closes everything, but we want to save our preferencesand exit gracefully. So we jump to our exit: procedure (which we talk about in a few paragraphs.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;ELSEIF LEFT$(c$,1)=KGetCmdLetterBackup$
   Exit:&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Pretty much the same as before. here the Communicator is being backed up. Again we want to gracefully exit, saving changes as we go, so the most recent version of the information has been saved.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;ELSEIF LEFT$(c$,1)=KGetCmdLetterBroughtToFGround$&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The program has been jumped to. Now in some programs, you'll need to update screens and variables, in others you won't need to alter anyting due to being in the background for some time. It depends on the application. If you needed to have a procedure when called back, you'd jump to it from here.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Reading Keypresses&lt;/i&gt;&lt;br /&gt;Next the system decides if it has been sent a keypress to act on. If it has, it jumps to a procedure (PROC g_kbddrv: for keyboard driver) to process this key.&lt;/p&gt;&lt;p&gt;(If ER6 OPL is ever installed on devices such as the P800 or 7860, then a further check would be made here for pen taps. If this ever happens, I'll gladly write another tutorial on pen events!)&lt;/p&gt;&lt;p&gt;&lt;i&gt;Acting on CBA Buttons&lt;/i&gt;&lt;br /&gt;If a CBA button is pressed, then the application jumps to the XXXXX-CBA routines and decides what button was pressed (1, 2, 3, or 4), and jumps to the relative procedure. This is a call-back function and because of this, you cannot exit an application from within a call-back function. This is a problem if you press CLOSE. So rather than jump to the exit, we simply set the level_completed% flag (or whatever variable we are using to scan for &amp;quot;I want to exit now&amp;quot;) and let the main loop routine exit that application gracefully.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Processing the Keypress (g_kbddrv:)&lt;/b&gt;&lt;br /&gt;You'll spend a lot of time in this procedure. Here is the meat of your app. If a user presses a key, it's this bit of code (with a very long IF statement) that will call the correct procedures and carry out the relevant actions.&lt;/p&gt;&lt;p&gt;The first few sections of this procedure concern themselves with the modifier keys, such as Shift, Ctrl, Fn, and their various combinations.&lt;br /&gt;The next line detects the menu key. If the menu key is pressed, then we jump to the g_menu: procedure, which will RETURN the equivalent keypress. (ie if we select Save-ctrl-s from a menu, then the procedure returns the letter s).&lt;/p&gt;&lt;p&gt;Now we look for two special events, the Infrared being switched on or off, or a request to add a shortcut to the application onto the desktop. You need to add these in the Menu subsystem (that's coming up!). Now, you'll see that the two procedures called are not in core.opl. Where are they?&lt;/p&gt;&lt;p&gt;The answer is hiding at the very top of the code in the lines...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;INCLUDE &amp;quot;AppFrame.oxh&amp;quot;
INCLUDE &amp;quot;System.oxh&amp;quot;
INCLUDE &amp;quot;DBase.oxh&amp;quot;
INCLUDE &amp;quot;SendAs.oxh&amp;quot;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;These OPL Extension Header files refer to things called OPX's. OPX's are small items of C++ machine code that can be called from OPL by a procedure call. OPX's usually deal with calls directly to the CPU to do specialist jobs - in this case the infrared and Desk screen. Any OPX's INCLUDED can be called at any time in the same way as normal.&lt;/p&gt;&lt;p&gt;We'll look at OPX's in a later tutorial.&lt;/p&gt;&lt;p&gt;And now we're at the part that actually does something...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;ELSEIF Key&amp;amp;=%A
   g_About:&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;...and so on. This part of the statement checks if shift-a has been pressed. Two things to note. The first is the % in front of the letter. This is a bit of OPL shorthand that says (the computer code for the following letter). 'A' is represneted by the number 97, so %A=97. This makes your code easier to read, and still understandable to the computer.&lt;/p&gt;&lt;p&gt;The second is that %a is different to %A. The second is shifted, the first isn't.&lt;/p&gt;&lt;p&gt;&lt;i&gt;The Menu Procedure - Showing What You Can Do&lt;/i&gt;&lt;br /&gt;The menu procedure is a piece of cake. First you initialise the menu system with the command mINIT. You then define each top level menu (eg File... Edit...) in an mCARD command like this...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;mCARD &amp;quot;File&amp;quot;,&amp;quot;Create new file...&amp;quot;,%n,&amp;quot;Open File&amp;quot;,%o&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The first string is &amp;quot;File&amp;quot; and this is what appears in the top menu bar. The next pair of string and number is the first line, with the text of the option (&amp;quot;Create New File...&amp;quot;) as the first, and the hotkey that this command represents the second.&lt;/p&gt;&lt;p&gt;You'll notice that these numbers (%n for New file) are the same numbers that we look for in the g_kdbdrv:. So you program once and get two outputs (hotkey and menu). This is what all the modifications are for. &lt;/p&gt;&lt;p&gt;We then use a temporary variable to store the result of the MENU command (which displays the menu and returns the simulated hot key).&lt;br /&gt;Having a second menu come off one menu option (eg any menu with &amp;quot;More &amp;gt;&amp;quot;) is something you may want to use. Fistly define the second menu (the one that is sprouting from the first) using mCASC. Then using a &amp;quot;&amp;gt;&amp;quot; symbol, refer to it in any mCARD line after the mCASC.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;mCASC &amp;quot;Databases&amp;quot;,&amp;quot;Create&amp;quot;,%c,&amp;quot;Query...&amp;quot;,%u
mCARD &amp;quot;File&amp;quot;,&amp;quot;Databases&amp;gt;&amp;quot;,16&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The number 16 puts up the little arrow symbol where the hotkey definition would normally appear.&lt;/p&gt;&lt;p&gt;&lt;b&gt;The End&lt;/b&gt;&lt;br /&gt;At some point our application will need to stop. Those looking through an OPL command list will find the useful STOP command. But you need to do a few things first. This is why when our Event Core needs to stop, it calls PROC exit:&lt;/p&gt;&lt;p&gt;This routine does a few vital housekeeping tasks. Firstly it saves the current preferences. It then closes all the graphical windows (so the computer can reclaim the memory efficiently).&lt;/p&gt;&lt;p&gt;Only then can we safely STOP the application.&lt;/p&gt;&lt;p&gt;&lt;b&gt;The First Preview!&lt;br /&gt;&lt;/b&gt;Phew! There's a lot going on there. Hopefully you've been able to read through the code at the same time as this part. It does make it easier to understand, trust me.&lt;/p&gt;&lt;p&gt;Now you know what's going on, it's time to press the compile button. After a few moments, you'll be asked if you want to run the compiled program (if you get an error message, check carefully what you've typed and make sure everything is correct. even a stray comma can upset the translation). After a few moments you'll be presented with the FreEPOC logo on the screen, and the menu and Command Buttons at the side should response. Have a play around and see what happens.&lt;/p&gt;&lt;p&gt;You've just compiled the OPL code of the Event Core! Don't be afraid to change the code and experiment. You &lt;b&gt;can't&lt;/b&gt; damage your Communicator doing this, so don't worry.&lt;/p&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:35:14 +0100</pubDate>
        </item>
        <item>
            <title>Part 1: A Crash Course in OPL</title>
            <link>http://www.allaboutsymbian.com/features/viewarticle.php?id=8</link>
            <description>&lt;strong&gt;Where to Start&lt;br /&gt;&lt;/strong&gt;To begin, you should obtain a copy of the OPL manual for the Psion Series 5mx range. This is available in a ZIP file in the &lt;a href=&quot;http://www.allaboutsymbian.com/develop/opl/oplsdk.php&quot;&gt;OPL Devkit&lt;/a&gt;. The majority of the language is unchanged from ER5 to ER6, major exceptions are noted in the Porting Guide supplied with the OPL ER6 SDK.&lt;p&gt;The important chapter is Chapter 15. This gives you the structure of each command, and a short explanation of what it does. You'll use this as a reference a lot during coding, keep it close at hand.&lt;/p&gt;&lt;p&gt;&lt;b&gt;First Steps&lt;br /&gt;&lt;/b&gt;Think of OPL as a story in a language that is almost, but not quite, English. It's easily readable by you, and if you translate this OPL code, it is easily read by your Communicator. Think of it as a halfway house between you and the computer.&lt;/p&gt;&lt;p&gt;As with any language, there are ways of speaking, and different elements. English has sentences, paragraphs, nouns, verbs and so on. OPL has it's own elements.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Procedures: Where you hang your Code.&lt;/b&gt;&lt;br /&gt;When an OPL program is run, the frst procedure (here called PROC main:) is opened. The lines are then read and processed in the order they are listed, until ENDP is reached, at which point the program ends.&lt;/p&gt;&lt;p&gt;Now within a procedure, you can call another procedure. Do this by simply typing the name of the procedure you want to run next. All procedure names must have a colon after them (that's the two dots above each other).&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC main:
setup_app:
do_something_nice:
save_status:
ENDP
PROC setup_app:
REM Do something interesting here
ENDP
etc...&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;So main: is opened, it calls three procedures in order, then reaches ENDP, and the program closes. Note that each procedure must start with PROC &amp;lt;a name&amp;gt;: and end with ENDP on seperate lines. When the end of the first procedure is reached, your OPL program stops. The only way t run other procedures is to call them.&lt;/p&gt;&lt;p&gt;Procedure names cannot have spaces, hence the use of the underscore. You'll see that underscore used a lot as a seperator!&lt;/p&gt;&lt;p&gt;&lt;b&gt;Constants&lt;/b&gt;&lt;br /&gt;Constants are exactly that. They are things that never change. You can use them so code is easier to read, for example rather than having to type the number 103782376892 every time you need to use it (assuming it is something that appears a lot in your app) you could put...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;K_Big_Number%=103782376892&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;...at the start of your code, and then each time you need to use the number, use K_Big_Number% instead. By convention, you shuld prefix K_ in front of any contant name.&lt;/p&gt;&lt;p&gt;Once you see some example code, constants should be a lot clearer. One thing to point out now is that there are a lot of default constants. If you have the line...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;INCLUDE &amp;quot;Const.oph&amp;quot;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;...then these default constanst can all be used. They are detailed in the documentation provided with the OPL Development Kit from Symbian. You should print this out and keep it to hand. it will be useful later!&lt;/p&gt;&lt;p&gt;&lt;b&gt;Variables&lt;/b&gt;&lt;br /&gt;A variable is somewhere where you can tell your computer to remember a piece of information. This is normally a small number, a big number, or a string of letters and numbers. Each of these variables is given a name, and a small sign to indicate what type of information it is. You should also remember these names cannot have a space in them, which is why you'll see so many names with the underscore character in them!&lt;/p&gt;&lt;p&gt;&lt;i&gt;Types of Variables&lt;/i&gt;&lt;br /&gt;A small number (called an integer) is followed by a % sign. For example, high_score% is an integer that stores a number referred to as high_score. An integer has to be a whole number (ie you can't have high_score%=2.5, but you can have high_score%=2 or high_score%=3).&lt;/p&gt;&lt;p&gt;A large number is followed by a &amp;amp; sign. For example, big_number&amp;amp; is a large integer that stores a number referred to as big_number. Large integers can be fractions (so you could have high_score&amp;amp;=2.5).&lt;/p&gt;&lt;p&gt;A string of letters and numbers is called (funnilly enough) a string, and is followed by a $ symbol, For example, name$ cold be &amp;quot;ewanspence&amp;quot;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Defining a Variable&lt;/i&gt;&lt;br /&gt;Before you can use a variable, you need to have told your program that you are going to use it. Think of it as making a little space to store the number. There are two ways of defining a variable.&lt;/p&gt;&lt;p&gt;A GLOBAL variable is a variable that ANY procedure can use.&lt;/p&gt;&lt;p&gt;A LOCAL procedures is a variable that only that specific procedure can use. When you leave the procedure, the little space for the number is reclaimed. Local variables are good for temporary counters and bits of info that are only needed for a few moments.&lt;/p&gt;&lt;p&gt;The command to set a variable needs to be the first lines of a procedure. Global definitions must be the first lines in your first procedure, and local procedure mus be the first lines in the relevant procedure.&lt;/p&gt;&lt;p&gt;You can put more than one definition on a line. Seperate them with a comma.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC main:
GLOBAL high_score%,big_number&amp;amp;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;And...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC local:
LOCAL name$(20)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;You'll note that after defining name$ we have a bracketed number. This tells the computer the maximum length (in characters) the string is going to be. You need to define the length of a string or when you translate the program for your computer, you'll get an error message.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Setting Variables&lt;/i&gt;&lt;br /&gt;Variables are easy to set. Simply use the equals sign. For example &lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;high_score%=56
big_number&amp;amp;=1383512467
name$=&amp;quot;rafe blandford&amp;quot;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Setting a variable should be done on a seperate line for each command. Note that when setting a string, you have to use quotation marks. These don't appear as part of the string.&lt;/p&gt;&lt;p&gt;&lt;i&gt;Arrays - Making a bigger Variable&lt;/i&gt;&lt;br /&gt;One other tool you have in variables is an array. An array is a 'list of things. For example, if we wanted to have a table of 10 numbers, then instead of&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;GLOBAL table1%,table2%,table3%&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Which would work (but will cause problems later), you can use&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;GLOBAL table%(10)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Which will create a table of 10 items. The first is called table%(1), then table%(2) and so on.&lt;/p&gt;&lt;p&gt;If you have a string table, then do &lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;GLOBAL name_table$(10,20)&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Which is a table of 10 strings, each a maximum of 20 characters long.&lt;/p&gt;&lt;p&gt;So why use name_table%(10) and not table1%,table2%, and so on? Because if you have another variable (eg lookupthisnumber%) then you can refer to name_table%(lookupthisnumber%). This is very useful if you think about it, as we're about to show you.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Loops&lt;/b&gt;&lt;br /&gt;Loops are a great way to make your program do something over and over again, maybe with a few changes. Look at this code.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;PROC loop:
LOCAL foo%
foo%=0
DO
foo%=foo%+1
table%(foo%)=foo%
UNTIL foo%=10
ENDP&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Make sure you understand this code. The DO... UNTIL loop is a primary building block of code. Firstly we create a variable to act as a counter. In this case foo%. You'll see me use foo% (and gnu% and zsu%) as a temporary variable name a lot. If you do see it, you can assume it's a counter or another local variable.&lt;/p&gt;&lt;p&gt;Each time round the loop we add one to foo%, then make an entry in an array called table (which must be a Global variable as it's not listed as a local variable).&lt;/p&gt;&lt;p&gt;When foo% reaches ten, then the UNTIL stops the loop, and carries on with the procedure. As there is nothing left to do, ENDP will return the program back to wherever loop: was called.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Decisions&lt;/b&gt;&lt;br /&gt;At many points in your program, you'll have to check something and do seperate commands depending on the outcome. To check things you use the IF command.&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;IF guess%=1
guess_right:
ELSEIF guess%=2
guess_close:
ELSE
guess_wrong%
ENDIF&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;Again, this is pretty easy to read. If the variable guess%=1, then goto a procedure called guess_right:. If guess%=2, then goto a procedure called guess_close: If guess% is anything else (a sort of catch all for any other condition, which is good programming practice to get into), then goto a procedure called guess_wrong:&lt;/p&gt;&lt;p&gt;The IF... ELSE... ENDIF is the second great building block of computing languages.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Making Sure You Don't Forget&lt;/b&gt;&lt;br /&gt;Througout code you'll see lines like this...&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;pre&gt;REM This routine calculates the cursor position
or...
REM foo_x% represents the temporary x co-ordinate
REM foo_y% represents the temporary y co-ordinate&lt;/pre&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;The power of the REM statement is in the fact it does absolutely nothing! Everything after the REM statement (until the next line of code) is ignored by the computer.&lt;/p&gt;&lt;p&gt;This means you can use it to leave notes for yourself, or to explain a bit of code to someone else who is going to read it. And if you come back to some code 6 months after writing it, wondering what PROC xyz_transposition: does, the REM statement you added will prove invaluable.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;So, pretty easy? Of course it is! Although it is a lot to get around, so don't worry if it takes a few weeks to get to grips with it. In the next part, we'll have a look at the Event Core OPL code and see how it works. There's nothing to stop you having a look at it at the moment, and you can't break your machine by experimenting with the code. You'll find you can read and understand quite a bit of it. Some of it, especially the stuff dealing with getting keypresses and events from the keyboard, can be quite daunting... but this is the advantage of having a Core Framework to begin with, rather than a blank canvas!&lt;/p&gt;</description>
            <pubDate>Mon, 25 Aug 2003 19:32:14 +0100</pubDate>
        </item>
    </channel>
</rss>

