_____ _________________________________ / /\ / \ / / / / ___________________________ \ / / / / / _________________________/\ \ / / / / /_/___________ _____ \ \ \ / / / / \ /\ \ \ \ \ / / / /_________________ \ \ \ \ \ \ \ / / / \________________/\ \ \ \ \ \ \ \ / /_/__________________________\_\ \ \ \ \___\/ \ / \ \ \ / /____________________________________________\ \ \____________/ \____________________________________________/ \/___________/FISH P R E S E N T AMIGA MACHINE LANGUAGE - FROM ABACUS BOOKS P A R T I I I Typed by DEE JAY of X-CELL for LSD Extra text by Pazza and Muridae Chapter 7. ---------- 7.Working With Intuition. ------------------------- Now that you've learned so much about machine language,lets look at the special features of the Amiga.Lets look at the operating system Intuition that is in charge of windows,screens,the mouse and lots of other things.Beforetaking a look at these beautiful features,theres some bad news. First,though,lets here the good news.Since Intuition has so many functions,it allows you to be very creative in programming your ideas.The disadvantage is that the flexibility means that you have to use a lot of parameters,and that makes for a lot of tedious work. However,this is no grounds for panic.Once you've built up the necessary routines,the programming and experimentation becomes increasingly interesting.Before you try out new program variations you should save your source code to disk,because Intuition gets fairly upset about bad parameters and often responds by crashing the system. Now lets get to work.To start working with Intuition,you need the Intuition library.You can load it with the OpenLibrary function from the EXEC library.Heres the subroutine that takes care of initialization. openlib =-408 execbase = 4 run: bsr openint ;load intuition library ... openint: ;*initialize and open system move.l execbase,a6 ;exec base address lea intname,a1 ;name of intuition library jsr openlib(a6) ;open intuition move.l d0,intbase ;save intuition base address rts intname: dc.b "intuition.library",0 align intbase: dc.l 0 ;base address of intuition When your program is finished,you need to close the screens,the window and the library.To do this,use the CloseLibrary function from the EXEC library.It has an offset of -414. Heres the subroutine: closelibrary =-414 ... closeint: ;*close intuition move.l execbase,a6 ;exec base address in A6 move.l intbase,a1 ;intuition base address in A1 jsr closelibrary(a6) ;close intuition rts ;done Now that you've got that taken care of,you can finally start working with Intuition. 7.1.Open Screen. ---------------- Intuition is a graphics operating system.For this reason,you'll be working with the screen.Its even more interesting to work with several screens at the same time.However,you only have one monitor on the Amiga. You can open as many screens as you like (at least,as long as theres some memory available).You can open a window,display menus and do I/O's there.The individual screens are fully independant. You can work with all of them simultaneously on the monitor. You can move individual screens forward and back to your hearts content.You can also press the left key and then an "m"to return to the workbench screen after getting into the different screens. You want to begin programming Intuition by setting up a screen.You have already loaded the Intuition library,so you can use the Open- Screen function. Wait a minute!What should the screen look like,where should it go, and what form should it have?You need to look at the options for the form of the screen you have available. The input to the screen is in the form of a table that has 13 entries.Lets take a look at the parameters that you need for our screen. You'll start the table with the label "screen_defs"which must be at an even address: align screen_defs: ;The screen table begins here The first bit of information that the screen needs is the position and size.Lets have it start in the upper left corner and fill the entire screen.You'll use the positions X=0 and Y=0,the width 320 and the height 200.This means that your screen is the maximum size. x_pos: dc.w 0 ;X-Position y_pos: dc.w 0 ;Y-Position width: dc.w 320 ;width height: dc.w 200 ;height Next you need to decide which colors should be displayed.That depends on the number of bitplanes,on the depth.Lets choose two. That means you have 2^2 (4) colours available.Lets choose two, since four colours is usually plenty. depth: dc.w 2 ;number of bitplanes Next you need to choose the colour of the title line and the function symbols.Give the number of the colour register: detail_pen: dc.b 0 ;colour of text,etc... Now for the colour of the text background: block_pen dc.b 1 ;background colour Make sure that these two inputs fit in a byte.The colours are normally the following (if the standard values have'nt been changed).You'll notice that the number of colours depends on the number of bit maps. Pen Colour --------------------------------------------------------- 0 Background (blue) 1 White for two bit planes 2 Black 3 Red for three bit planes 4 Blue 5 Violet 6 Turquoise 7 White for four bit planes 8 Black 9 Red 10 Green 11 Brown 12 Blue 13 Blue 14 Green 15 Green The next word contains the bits that describe the appearance of the screen.The bits are: Bit Value Name Meaning --------------------------------------------------------------- 1 2 GENLOCK_VIDEO 2 4 INTERLACE Puts the screen in Interlace mode.The resolution and thus the maximum screen size are doubled. 6 $40 PFBA 7 $80 EXTRA_HALFBRITE 8 $100 GENLOCL_AUDIO 10 $400 DBLPF Divides the screen into a border and character area. 11 $800 HOLDNMODIFY Turns on Hold-and-Modify mode. 13 $2000 VP_HIDE 14 $4000 SPRITES Allows sprites to be used. 15 $8000 MODE_640 Turns on the highest resolution graphics for the screen(640x400). Choose the value two (normal) for your example screen: view_modes: dc.w 2 ;representation mode The following word is constructed in such away that each bit as its own meaning.Use this to set what sort of screen it is.Choose 15 so the screen is a "Custom screen",which allows you all of the options. screen_type: dc.w 15 ;screen type:custom screen Next theres a pointer to the character set to be used for all output to the screen.If you don't want to install your own character set,just put a zero here,and the standard character set is used. font: dc.l 0 ;character set:standard Next theres a pointer to the text thats used as the name of the screen.The text ends with a zero,just like window names must. title: dc.l name ;pointer to title text Next comes a long word that defines the gadgets.These gadgets represent the functions,like "Bring forward",that can be accessed via a mouse click in the screen.The long word in this table is a pointer to a list which specifies the gadgets.These aren't the system gadgets.However,you're only using system gadgets here,so put a zero here. gadgets: dc.l 0 ;no gadgets Finally theres a long word that you only need if you want to use the special bitmap just for your screen.Since this isn't the case, just put a zero here. bitmap: dc.l 0 ;no bitmap Thats it for the list entries that you need to define the screen. You still need the text for the name of the screen.Enter the following: sname: dc.b 'Our Screen',0 ;screen title Heres a quick overview of the list: align screen_defs: ;*The screen ta x_pos: dc.w 0 ;X-position y_pos: dc.w 0 ;Y-position width: dc.w 320 ;width height: dc.w 200 ;height depth: dc.w 2 ;number of bitplanes detail_pen: dc.b 0 ;colour of the text,etc... block_pen: dc.b 1 ;background colour view_modes: dc.w 2 ;representation mode screen_type: dc.w 15 ;screen type:custom screen font: dc.l 0 ;character set:standard title: dc.l sname ;pointer to title text gadgets: dc.l 0 ;no gadgets bitmap: dc.l 0 ;no bit map sname: dc.b 'Our Screen',0 ;screen title Once you've decided on the parameters,its very easy to open the screen.You need Intuitions OpenScreen function.Its offset is -198 and it only needs one parameter,the address of the parameter table.The program fragment looks like this: openscreen =-198 bsr openint ;open intuition bsr scropen ;open screen ... scropen: ;*open screen move.l intbase,a6 ;intuition base address in A6 lea screen_defs,a0 ;pointer to table jsr openscreen(a6) ;and open move.l d0,screenhd ;save screen handle rts ;return to main program ... screen_defs: ;table info follows Now the Amigas Workbench screen is covered by your screen.Now you can do what you want with it until the program is done.Afterwards, the screen must be closed again,so that you can see the Workbench screen again. Use the CloseScreen function (offset -66) to do this.The only parameter it needs is the pointer to the screen structure you got back from the OpenScreen function. closescreen =-66 ... scrclose: ;* close screen move.l intbase,a6 ;intuition base address in A6 move.l screenhd,a0 ;screen handle in A0 jsr closescreen(a6) ;clos screen rts ;done The long word that OpenScreen returned to you is a pointer to a screen structure that contains all the needed data about the screen.Besides the data which was given,there is a pointer in the screen area for individual bit planes,etc... The form of this structure is fairly complicated and contains some data that you can't use.Several of the parameters are interesting, however.Heres a selection of usable parameters: No Name Function ------------------------------------------------------------------ 0 (NextScreen.L) Pointer to next screen. 4 (FirstWindow) Pointer to first window structure 8 (LeftEdge.W) $A (TopEdge.W) Position of screen $C (Width.W) Width $E (Height.W) Height $10 (MouseY.W) $12 (MouseX.W) Mouse position in the screen $14 (Flags.W) Screen flags $16 (Title.L) Pointer to title text $1A (DefaultTitle) Pointer to normal title $28 (Font.L) Pointer to character set $C0 (Plane0.L) Pointer to bitplane 0 $C4 (Plane1.L) Pointer to bitplane 1 $C8 (Plane2.L) Pointer to bitplane 2 $CC (Plane3.L) Pointer to bitplane 3 An example of an application for the plane pointer is writing and using your own character routine.Next you want to move the address of the plane into an address register as follows: move.l screenhd,a5 ;screen pointer in A5 move.l $c0(a5),a5 ;bitplane 0-pointer in A5 If you want to try this,do the following: move.l screenhd,a5 ;screen pointer in A5 move.l $c0(a5),a5 ;bitplane 0-pointer in A5 move #$20,d0 ;Counter D0=$20 lop1: move d0,(a5) ;write counter bits in picture add.l #80,a5 ;address+80,next line dbra d0,lop1 ;continue until D0 < 0 This program draws a white,square pattern that corresponds to the bit pattern for the numbers $20 to 0.This isn't a particularly useful program,but it shows how easy it is to write from a machine language program directly to the screen.If you change the offset in the second line to $C4,the pattern is read. You can move the entire screen with the normal technique of moving the mouse pointer into the upper border and moving it up and down with the left mouse key depressed.You can do the same with a program. Lets move the screen without the mouse.Use the joystick for demonstration purposes.Put the joystick in port two.As you saw in the chapter on the hardware register,you can read memory location $DFF00C to find information about the joystick.You can find the direction the screen should be moved here. Moving the screen requires another Intuition function.You use the MoveScreen function which as an offset of -162 and needs three parameters to do this.The parameters are: In A0 the pointer to the screen structure that you got back in D0 when you opened the screen.(You saved it in "screenhd") In D1 the desired movement in the Y-direction,the vertical direction. In D0 the horizontal movement in the X-direction.The varient doesn't work so you can only move the screen vertically. Insert the following lines in your program: MoveScreen =-162 ... scrmove: ;*move screen D0 to the right ;and D1 down move.l intbase,a6 ;intuition base address in A6 move.l screenhd,a0 ;screen handle in A0 clr.l d0 ;no horizontal movement jsr movescreen(a6) ;move screen rts ;done Now your looking at a complete program that goes through the following steps: 1. Opens the Intuition library 2. Opens the screen 3. Moves the screen in the direction specified by the joystick in port two 4. Closes the screen when the fire button is hit 5. Closes the Intuition library 6. Ends Here is the complete program including the subroutines,so you'll have it all in one spot: ;** Demo program to open and move a screen ** movescreen =-162 openscreen =-198 closescreen =-66 closelibrary =-414 openlib =-408 ;open library execbase = 4 ;exec base address joy2 =$dff00c ;joystick 2 data fire =$bfe001 ;firebutton 2:bit 7 run: bsr openint ;open intuition bsr scropen ;open screen move joy2,d6 ;save joystick info loop: tst.b fire ;test fire button bpl ende ;pressed down:done move joy2,d0 ;basic info in D0 sub d6,d0 ;subtract new data cmp #$0100,d0 ;up? bne noup ;no move.l #-1,d1 ;dy=-1 direction y bsr scrmove ;move up bra loop noup: cmp #$0001,d0 ;down? bne loop ;no move.l #1,d1 ;dy=1 bsr scrmove ;move down bra loop ende: bsr scrclose ;close screen bsr closeint ;close intuition rts ;done! openint: ;*initialize and open system move.l execbase,a6 ;exec base address lea intname,a1 ;name of intuition library jsr openlib(a6) ;open intuition move.l d0,intbase ;save intuition base address rts closeint: ;*close intuition move.l execbase,a6 ;exec base address in A6 move.l intbase,a1 ;intuition base address in A1 jsr closelibrary(a6) ;close intuition rts ;done scropen: ;*open screen move.l intbase,a6 ;intuition base address in A6 lea screen_defs,a0 ;pointer to table jsr openscreen(a6) ;open move.l d0,screenhd ;save screen handle rts ;return to main program scrclose: ;*close screen move.l intbase,a6 ;intuition base address in A6 move.l screenhd,a0 ;screen handle in A0 jsr closescreen(a6) ;close screen rts ;done scrmove: ;move screen D0 right/D1 down move.l intbase,a6 ;intuition base address in A6 move.l screenhd,a0 ;screen handle in A0 clr.l d0 ;no horizontal movement jsr movescreen(a6) ;and move rts ;done align screen_defs: ;*screen table begins here x_pos: dc.w 0 ;X-position y_pos: dc.w 0 ;Y-position width: dc.w 320 ;width height: dc.w 200 ;height depth: dc.w 2 ;number of bitplanes detail_pen: dc.b 1 ;Text colour=white block_pen: dc.b 3 ;background colour=red view_modes: dc.w 2 ;representation mode screen_type dc.w 15 ;screen type:custom screen font: dc.l 0 ;standard character set title: dc.l sname ;pointer to title text gadgets: dc.l 0 ;no gadgets bitmap: dc.l 0 ;no bit map intbase: dc.l 0 ;base address of intuition screenhd: dc.l 0 ;screen handle intname: dc.b 'intuition.library',0 align sname: dc.b 'Our Screen',0 ;Screen title align end From this example,you can see how easy scrolling actually is. Another easy thing to do is to use the DisplayBeep function.It as an offset -96;the only parameter it needs is the screen pointer that you stored in the "screenhd"memory block.This function covers the screen with an orange colour for a short while.The screen is not changed.The beep function can be used as follows: DisplayBeep: =-96 ... move.l intbase,a6 ;intuition base address in A6 move.l screenhd,a0 ;screen pointer in A0 jsr displaybeep(a6) ;light up screen If you put a zero instead of a screen pointer in A0,the whole screen blinks. Good,now you have your own screen that you can move up and down. What good is it if you can't put anything on it?Lets open a window on the screen! 7.2.Open Window. ---------------- As you saw in the chapter on program initialization,its easy to open a window with the DOS library.You can't use this method on your own screen however.You need to use another method that can open any window on any screen. Intuition has a function called OpenWindow which handles this sort of work.It has an offset of -204 and needs only one parameter,a pointer to a window definition table.This pointer goes in register A0. This table is very similar to the one used to define the screen. The first four values specify the X-and Y-positions,the width,and the height of the window to be opened.Heres an example: align window_defs: dc.w 10 ;x-position dc.w 20 ;y-position dc.w 300 ;width dc.w 150 ;height Next come two bytes that define the colour of the letters on the background: dc.b 1 ;white letter colour dc.b 3 ;on a red background The next long word contains the IDCMP flags in its bits.The bits determine the circumstances under which Intuition sends a message to the program.The bits have the following meanings: Bit Value Name Meaning ----------------------------------------------------------------- 0 $000001 SIZEVERIFY 1 $000002 NEWSIZE Window size changed 2 $000004 REFRESHWINDOW 3 $000008 MOUSEBUTTONS Mouse key hit 4 $000010 MOUSEMOVE Mouse moved 5 $000020 GADGETDOWN A special gadget chosen 6 $000040 GADGETUP Same as above 7 $000080 REQSET 8 $000100 MENUPICK A menu item chosen 9 $000200 CLOSEWINDOW A window closed 10 $000400 RAWKEY A key pressed 11 $000800 REQVERIFY 12 $001000 REQCLEAR 13 $002000 MENUVERIFY 14 $004000 NEWPREFS Preferences modified 15 $008000 DISKINSERTED A disk put in 16 $010000 DISKREMOVED A disk taken out 17 $020000 WBENCHMESSAGE 18 $040000 ACTIVEWINDOW A window activated 19 $080000 INACTIVEWINDOW A window deactivated 20 $100000 DELTAMOVE Report relative mouse movement If you want your first window to respond only by clicking on the close symbol,write the following: dc.l $200 ;IDCMP flags:CLOSEWINDOW Next comes a long word whose bits determine the windows type.You can use this to construct a window to your exact specifications. This is quite different from windows opened with the DOS function. The bits mean: Bit Value Name Meaning ------------------------------------------------------------------ 0 $0000001 WINDOWSIZING Window size is changeable 1 $0000002 WINDOWDRAG Window is moveable 2 $0000004 WINDOWDEPTH Window covering is posible 3 $0000008 WINDOWCLOSE Window close symbol 4 $0000010 SIZEBRIGHT 5 $0000020 SIZEBOTTOM 6 $0000040 SIMPLE_REFRESH New drawing manuel 7 $0000080 SUPER_BITMAP Save the windows contents 8 $0000100 BACKDROP Move window back 9 $0000200 REPORTMOUSE Report mouse co-ordinates 10 $0000400 GIMMEZEROZERO 11 $0000800 BORDERLESS Window without border 12 $0001000 ACTIVATE Window active 13 $0002000 WINDOWACTIVATE 14 $0004000 INREQUEST 15 $0008000 MENUSTATE 16 $0010000 RMBTRAP Right mouse key:no menu 17 $0020000 NOCAREREFRESH No refresh message 24 $1000000 WINDOWREFRESH 25 $2000000 WBENCHWINDOW To refresh is to rebuild the window contents when necessary,for instance when the windows size is changed.If none of the refresh bits are set,you're in Smart-Refresh-Mode.In this case,Intuition takes care of refreshing the window.This is the easiest method. If you choose the value $100F as the type for your example window, the window is active once its opened,and it has all the system gadgets: dc.l $100F ;ACTIVATE and all gadgets The next long word in the list allows you to use your own gadgets in the window.This long word is a pointer to the structure of a your gadget.Since you don't want this,just put a zero here. dc.l 0 ;first gadget:no gadgets of our own The next long word is a pointer to a graphics structure so you can design your own symbol for checking menu points.Put a zero here. You'll use the standard sign: dc.l windowname ;pointer to window name The next long word is a pointer to the screen structure that you got back after calling the OpenScreen function.The easiest way to do this is to save the pointer to this location in the buffer: screenhd: dc.l 0 ;screen pointer The next long word is a pointer to a bit map if you want one of your own for the window.Since you don't want one,put a zero here. dc.l 0 ;no bit map of our own Next come four values that set the maximum and minimum width and height of the window: dc.w 150 ;smallest width dc.w 50 ;smallest height dc.w 320 ;maximum width dc.w 200 ;maximum height The last value in the list is the screen type of the screen the window is located in.Put a 15 here.You're using our screen as a custom screen: dc.w 15 ;screen type:custom screen Heres a quick overview of the whole list: align window_prefs: dc.w 10 ;X-position dc.w 20 ;Y-position dc.w 300 ;width dc.w 150 ;height dc.b 1 ;white print colour dc.b 3 ;on red background dc.l $200 ;IDCMP flags:CLOSEWINDOW dc.l $100f ;ACTIVATE and all gadgets dc.l 0 ;first gadget:no gadgets of ;our own dc.l 0 ;checkmark:standard dc.l windowname ;pointer to window name screenhd: dc.l 0 ;screen pointer dc.l 0 ;no bitmap of our own dc.w 150 ;smallest width dc.w 50 ;smallest height dc.w 320 ;maximum width dc.w 200 ;maximum height dc.w 15 ;screen type:custom screen ;and here comes the window name: windowname: dc.b 'Our Window',0 align Insert these lines in the program you listed above.Here are two subroutines for opening and closing the window: openwindow =-204 closewindow =-72 ... windopen: move.l intbase,a6 ;intuition base address in A6 lea windowdef,a0 ;pointer to window definition jsr openwindow(a6) ;open window move.l d0,windowhd ;save window handle rts windclose: move.l intbase,a6 ;intuition base address in A6 move.l windowhd,a0 ;window handle jsr closewindow(a6) ;close window rts ... windowhd: dc.l 0 ;window handle Now you can insert a "bsr windowopen"after the "bsr scropen"and a "bsr windclose"before the "bsr scrclose"command.Once you've started the program,move the window around in the screen.You'll find that you can't move the window out of the screen with the mouse. The window in the example has the close gadget in the upper left corner.Normally if you click it,the window is closed.Try clicking it.You'll find that nothing happens. The display of this and all other gadgets,as well as other events must be programmed in,since Intuition doesn't know which action causes which event.We'll take a look at how to handle this in the next chapter. 7.3.Requesters. --------------- If you only have one disk drive,you've certainly seen the Amiga message,"Please insert xxx in unit 0",a lot.This window is another that has two fields for clicking.This sort of message with a choice of options is called a requester. You want to take a look at how to program a requester.First,you need a window for the requester to appear in.You opened a window of this sort in the example program. To display a requester,use the Intuition function AutoRequest (offset -348).It takes care of drawing and managing the requester. This function needs the following parameters: In A0 The pointer to the window structure that you put in "windowhd". In A1 A pointer to the text structure that should stand over the choice buttons. In A2 Same as above for the text of the left button. In A3 Same as above for the right button. In D0 The IDCMP flag which lets you know what event should go with the clicking of the left button. In D1 Same as above for the right button. In D2 The width of the whole requester. In D3 The height of the requester. Insert the following lines in your program: autorequest =-348 ... request: move.l windowhd,a0 ;pointer to window structure lea btext,a1 lea ltext,a2 ;pointer to text structure lea rtext,a3 move.l #0,d0 ;left activates by clicking move.l #0,d1 ;right activates by clicking move.l #180,d2 ;width and move.l #80,d3 ;height of requester move.l intbase,a6 ;intuition base address jsr autorequest(a6) ;display requester rts The flags passed in D0 and D1 offer some interesting posibilites. The system messages that tells you to enter a particular disk are overlooked when the DISKINSERTED flag is similar.Putting a disk in brings about the same responce as clicking the "Retry"button. Whats new is the use of a text structure.Use three of them.Text structures are lists that contain entries for the text that you need. These lists begin with two bytes that are used to define the colour.The first byte is the colour of the text.The second is for the background colour.Here this doesn't have any meaning. btext: dc.b 2 ;black text colour dc.b 0 ;background colour The next byte specifies the character mode.A zero means that the text is output normally.A four means the text is output inverted. dc.b 0 ;normal text representation The next entries are words.For this reason the addresses must be even,so you need to either insert another byte or use the "align" pseudo-op.The following words are the X-and Y-position of the text relative to the upper left corner of the requester. dc.w 10 ;X-position dc.w 5 ;Y-position relative to upper ;left corner Next,theres a pointer to the character set that is used.Put a zero here to use the standard set. dc.l 0 ;standard character set Next you need to give the address of the text that should be output.This text must be closed with a null byte. dc.l text ;pointer to text You need a long word at the end of the list that is either a pointer to another text or a zero if no more text is needed. dc.l 0 ;no more text Here are the three text structures that you need for the example: btext: ;text structure for the title dc.b 0,1 ;colour dc.b 0 ;mode align dc.w 10,10 ;text position dc.l 0 ;standard font dc.l bodytxt ;pointer to text dc.l 0 ;no more text bodytxt: dc.b "Requester Text",0 align ltext: ;text structure of left button dc.b 0,1 ;colour dc.b 0 ;mode align dc.w 5,3 ;text position dc.l 0 ;standard font dc.l lefttext ;pointer to text dc.l 0 ;no more text lefttext: dc.b "left",0 align rtext: dc.b 0,1 ;colour dc.b 0 ;mode align dc.w 5,3 ;text position dc.l 0 ;standard font dc.l righttext ;pointer to text dc.l 0 ;no more text righttext: dc.b "right",0 align After calling the requester,D0 contains the information about which of the buttons were pressed,and in which button the event took place.If D0 is zero,it was the right button.If it is one,it was the left button. 7.4.Event Handling. ------------------- Pretend you've opened a window that as a close symbol,and you want the program to react to this symbol being clicked.You need a signal from Intuition that lets you know that an event as taken place.The signal is called a message. The IDCMP flag of the window specifies which events should cause Intuition to send a message.By setting the bits for WINDOWCLOSE, you can allow a message to be sent when the close symbol is clicked. To get the message,you can use the EXEC function GetMsg (offset -372).It needs the source address of the event as a parameter.Here the source is the User port (which doesn't have anything to do with the User port on old Commodore computors). The User port contains a table which has entrieswhich specify the events that have taken place and related things like mouse position and time. How do you find the User port?Use the pointer to the window structure that you got back from the OpenWindow function and stored in the "windowhd"memory block. This pointer points to the window structure of this window.This structure consists of a number of entries.Some are copies of the parameters from our window definition table.We won't cover all the entries,because most won't be interesting to you.You're more interested in the pointer to the User port.Its in the window structure. You can find this in the long word that begins in the 86th byte of the structure.You can get this long word with the following lines of code: move.l windowhd,a0 ;pointer to structure in A0 move.l 86(a0),a0 ;user port pointer in A0 You can call the GetMsg function with this pointer in A0 by using the following lines of code in your program: GetMsg = -372 ... move.l windowhd,a0 ;pointer to structure in A0 move.l 86(a0),a0 ;user port pointer in A0 move.l execbase,a6 ;exec base address in A6 jsr getmsg(a6) ;get message This function returns a value in the D0 register.This value is a pointer to another structure,the Intuition Message Structure.If theres a zero in D0,no event as taken place. The long word that starts at the 20th byte in this structure contains the information about which event took place.Evaluating the information is easy,since the bits of this long word have the same meaning as the IDCMP flag that you described when you looked at opening windows. Put the lines above after "loop"and then insert the following: move.l d0,a0 ;message pointer in A0 move.l 20(a0),d6 ;save event in D6 tst.l d0 ;did the event take place? bne end ;yes! Now you can end this program by clicking the close symbol.This way you can find out if an event as taken place.You can use D6 to determine what event took place.In the example,D6 contains the number $00000200,which means that the close symbol was clicked. To see if this works with other events,change the $200 IDCMP flag to $10200 in the window definition table.When you've assembled and started this version,take the disk out of the drive-the program terminates. The IDCMP flags that you've got now cause the clicking of the close symbol and the taking out of the disk (DISKREMOVED) to be reported.If you want to find out which of the events took place, you can look in D6.It has a $200 in it if the window is closed,a $10000 if the disk was removed. 7.5.Menu Programming. --------------------- Now lets look at one of Intuitions more interesting capabillities: menu programming.By using menus,you can make your programs very user friendly. There are a lot of ways for you to use menus.You can make menu points unusable,output sub-menus,choose the type of menu entries (allow text or pictures to be output),etc..To have lots of options you need some parameters. Lets produce a menu with the SetMenuStrip function (offset -264) of Intuition.The function only needs two parameters,a pointer to the menu structure of the window to be drawn and a pointer to the window structure of the window in which the menu is to function. Each window can have its own menu that is active when the window is activated. Heres the subroutine to set up the menu: SetMenuStrip =-264 ... setmenu: ;* Initialize a menu move.l intbase,a6 ;intuition base address in A6 move.l windowhd,a0 ;pointer to window structure lea menu,a1 ;pointer to menu structure jsr setmenustrip(a6) ;call function rts Heres a routine to erase the menu: ClearMenuStrip =-54 ... clearmenu: move.l intbase,a6 ;intuition base address in A6 move.l windowhd,a0 ;pointer to window structure jsr clearmenustrip(a6) rts You've already got the pointer to the window structure.Lets look at the menu structure you need for the menu.You need to build a structure like this for each menu--for each menu title that appears when you press the right mouse key. This structure is a table with the following form: First there is a long word that points to the menu structure of the next menu.If the current menu is the last one,a zero goes here. align menu: dc.l menu1 ;pointer to the next menu Next come two words which contain tha X- and Y-position of the menu title: dc.w 20 ;X-position dc.w 0 ;Y-position Next,use two words to store the menu titles width and height in pixels: dc.w 50 ;width dc.w 10 ;height of menu title The next word contains the flag bit that determines whether the menu is available or not.An unavailable menu either as grey entries or they are drawn weakly.If the flag bit,bit 0,is set the menu is available.Otherwise,it is not. dc.w 1 ;menu available Now comes a long word which functions as a pointer to the text which is used as the menu title.Make sure the length isn't larger than the width entry allows!Otherwise unpleasent things will happen. dc.l menutext ;pointer to title text Next comes a long word which functions as a pointer to the structure of the first menu entry of this menu.Each menu entry needs its own structure. dc.l menuitem01 ;pointer to the first menu item The last entries in the table are four words that are reserved for internal functions.They must be here. dc.w 0,0,0,0 ;reserved words Thats the structure of the first menu.This structures first long word points to the next structure which has the same form.The pointer is set to zero in the last menu. You still need the structure of the menu entries.These structure tables have the following form: They start with a pointer to the next menu item.This pointer is set to zero for the last entry. align menuitem01: dc.l menuitem02 ;pointer to next menu item Next comes the four words:the X- and Y-position,the width and the height of the box the menu entry goes in.The size becomes obvious when the item is chosen by having the right mouse key clicked on it.Then the box becomes visible.As you can see,the next word is determined in the flags.First lets set the position and size of the menu point,though: dc.w 0 ;X-position of entry dc.w 0 ;Y-position dc.w 90 ;width in pixels dc.w 10 ;height in pixels The position entries are relative to the upper left corner of the menu that is pulled down. The following word was described above:it contains flags for entries to this menu item.There are several interesting variations possible.The following flag bits are contained in this word: Bit Value Name Meaning When Set ------------------------------------------------------------------ 0 $0001 CHECKIT Point is checked when chosen 1 $0002 ITEMTEXT Text menu item 2 $0004 COMMSEQ Choice can be made with keys as well 3 $0008 MENUTOGGLE Check turned on and off 4 $0010 ITEMENABLED Menu item available 6 $0040 HIGHCOMP Item inverted when chosen 7 $0080 HIGHBOX Iten framed when chosen 8 $0100 CHECKED Item is checked Heres a description of the bits: Name Description ------------------------------------------------------------------ CHECKIT If this bit is set,a check or a user-defined drawing is put in front of the text when the item is chosen.The text should begin with two blanks. ITEMTEXT The menu item is a normal text if this bit is set. Otherwise a drawing is output. COMMSEQ By setting this bit and entering a character,this menu point can be chosen by pressing the right key and the key that was input.The input character is then displayed in the menu with the Amiga symbol.There needs to be space available for this. MENUTOGGLE If this bit is set and checking is allowed (bit 0), the second time this point is chosen the check is erased,the next time it is displayed again,etc... ITEMENABLED Erasing this bit makes the menu item available. HIGHCOMP If this bit is set,the box you've defined is inverted when this menu item is chosen by the mouse pointer. HIGHBOX In this mode,the box is framed whin its chosen. The two previous bits determine the mode of the chosen menu item. The following combinations are possible: HIGHIMAGE If both bits are cleared,choosing the bit causes a self-defined drawing to be output. HIGHNONE When both bits are set,there isn't any reaction to choosing this item. CHECKED This bit can be set by either the program or Intuition.It lets you know if the menu text has a check next to it or not.You can use this to find out if the item was checked by testing but eight.If its set,the item was checked.You can also use it to cause the item to be checked. You're choosing the mode CHECKIT,ITEMTEXT,COMMSEQ,MENUTOGGLE,ITEM- ENABLED and HIGHBOX for the example: dc.w $10011111 ;mode flag Lets get back to the structure of the menu items.After the flag word,there is a long word whose flag bits determine whether this menu point can be turn off another one.Set this to zero: dc.l 0 ;no connection Now comes the pointer to the structure of the text that should be displayed.If the ITEMTEXT bit isn't set,this pointer must point to the structure of the drawing.If nothing should be shown,you can set this to zero.Use a text in the example and write the following: dc.l menu01text ;pointer to menu text structure The following long word only has a meaning if the HIGHIMAGE flag is set.Then this long word points to the text or the drawing that should be displayed when the menu items box is clicked.Otherwise the long word is ignored,so insert a zero: dc.l 0 ;no drawing when clicked The next entry is a byte that is used for input of keyboard characters,which together with the right key can be used to choose the menu item.This only works if the COMMSEQ bit is set. Place a character here: dc.b 'A' ;choose item using /'A' Since the next item is a long word,you need an "align"peudo-op here.Next comes the long word that points to the menu item structure or a submenu.The submenu is automatically shown when this menu item is clicked.You can't nest them any deeper,however, so this long word is ignored for submenus. If you don't want a submenu to this item,put a zero here: align dc.l 0 ;no submenu The next and final long word is written to by Intuition if you choose several menu itens.In this case,the menu number of the next menu item chosen goes here: dc.l 0 ;preparation Thats the structure for a menu item.You still need the text structure for the text of the item.This isn't complicated,but it makes you get into fine details about the form of the menu.You've already learned about this text structure when you looked at requesters,so we'll skip an explanation. Heres the complete structure of an example menu.You can use two menus,each with two subpoints.The second menu point of the left menu has a submenu with two entries.You ought to type this program in,so that you can experiment with it.You can also use this example to evaluate the clicked menu item. ;**Complete menu structure foe example menu ** menu: dc.l menu1 ;no next menu dc.w 10,30 ;X/Y dc.w 50,10 ;width/height dc.w 1 ;menu enabled dc.l menuname ;menu title dc.l menuitem01 ;menu entry menuname: dc.b "Menu 1",0 ;first menu name align menu1: dc.l 0 ;no further menu dc.w 80,0 ;see above dc.w 50,10 dc.w 1 dc.l menuname1 dc.l menuitem11 dc.w 0,0,0,0 menuname1: dc.b "Menu 2",0 ;second menu name align menuitem01: ;first menu item dc.l menuitem02 ;pointer to next entry dc.w 0,0 ;X/Y dc.w 130,12 ;width/height dc.w $9f ;flags dc.l 0 ;exclude dc.l text01 ;pointer to text structure dc.l 0 ;select fill dc.b "1" ;command align dc.l 0 ;subitem:none dc.w 0 ;next select:no text01: dc.b 0,1 ;colours dc.b 0 ;mode:overwrite align dc.w 5,3 ;X/Y position dc.l 0 ;standard character set dc.l text01txt ;pointer to text dc.l 0 ;no more text text01txt: dc.b "Point 0.1",0 align menuitem02: ;second menu item dc.l 0 dc.w 0,10 dc.w 130,12 dc.w $57 dc.l 0 dc.l text02 dc.l 0 dc.b "2" ;activate with /'2' align dc.l 0 dc.w 0 text02: dc.b 0,1 dc.b 0 align dc.w 5,3 dc.l 0 dc.l text02txt dc.l 0 text02txt: dc.b "Point 0.2",0 align menuitem11: ;first menu point of the second menu dc.l menuitem12 ;pointer to second menu point dc.w 0,0 dc.w 90,12 dc.w $52 dc.l 0 dc.l text11 dc.l 0 dc.b 0 align dc.l 0 dc.w 0 text11: dc.b 0,1 dc.b 0 align dc.w 5,3 dc.l 0 dc.l text11txt dc.l 0 text11txt: dc.b "Point 1.1",0 align menuitem12: ;second menu item of second menu dc.l 0 ;no more items dc.w 0,10 dc.w 90,12 dc.w $92 dc.l 0 dc.l text12 dc.l 0 dc.b 0 align dc.l submenu0 ;pointer to submenu dc.w 0 text12: dc.b 0,1 dc.b 0 align dc.w 5,3 dc.l 0 dc.l text12txt dc.l 0 text12txt: dc.b "Point 1.2",0 align submenu0: ;first point of submenu dc.l submenu1 ;pointer to next point dc.w 80,5 dc.w 90,12 dc.w $52 dc.l 0 dc.l texts0 dc.l 0 dc.b 0 align dc.l 0 dc.w 0 texts0: dc.b 0,1 dc.b 0 align dc.w 5,3 dc.l 0,texts0txt,0 texts0txt: dc.b "S Point 1",0 align submenu1: ;submenu,second item dc.l 0 dc.w 80,15 dc.w 90,12 dc.w $52 dc.l 0 dc.l texts1 dc.l 0 dc.b 0 align dc.l 0 dc.w 0 texts1: dc.b 0,1 dc.b 0 align dc.w 5,3 dc.l 0 dc.l texts1txt dc.l 0 texts1txt: dc.b "S Point 2",0 align The menu items in this example have the following properties as a result of their flags: Menu 1; The first item,"Point 0.1",can be chosen using the right key and the "1" key.This point alternates between checked and not checked,which can easily be used to check out the key function.If the item is checked and you hit both keys,the check disappears and vice versa.The box at this point is framed when the mouse pointer clicks on it. The second item,"Point 0.2",can be chosen using the right key and the "2"key.This item is checked the first time it is chosen.However,in contrast to the item above,it can't be erased. The box of this item is inverted when clicked. Menu 2; These two points can't be chosen using keys.The box of the upper item is inverted when clicked on:the lower one is framed.When you click the second item,"Point 1.2",a submenu with two entries is displayed. Experiment with this structure a little bit.Change some values and see what happens.As you can see,menu programming isn't as bad as you thought,and it offers a lot of options (but you'll have to do lots of typing!). When you've done experimenting,you'll want to produce your own program with menus.How does the program find whether a menu item in a menu has been clicked on? You already looked at one way to find out the menus state.You can test the CHECKED bit in the flag word of a menu item.If this is set,the user clicked on this item with the mouse. This only works if checking is allowed for the item being tested. You could allow all the menu items to be checked,but this still isn't a good solution--it requires testing all the flag bits of all the menus one after the other.That makes very boring programming. You've already learned about finding about events from Intuition. You've moved the message about which event took place into D6,and you can look at it to find out what happend. If you set the eight bit,the MENUPICK bit,of the IDCMP flag long word in the window definition,the choice of the menu point is reported.Put the following lines in your loop in the main program. loop: move.l execbase,a6 ;exec base address in A6 move.l windowhd,a0 ;window structure pointer move.l 86(a0),a0 ;user point pointer in A0 jsr getmsg(a6) ;get message tst,l d0 ;whay happend? beq loop ;nothing happend move.l d0,a0 ;message pointer in A0 move.l $14(a0),d6 ;event in D6 If the program makes it out of the loop,an event as taken place. You have the events flag in the D6 register.You can evaluate the event using CMP or BTST to find out which flag bits are set.You can then execute the function corresponding to the set bit.You can use lines like the following ones: cmp #$200,d6 ;WINDOWCLOSE? beq ende ;yes:program end These lines terminate the program when the window is closed. If the user chose a menu item,there is a $100 in the D6 register. You now need to determine which item it was. You can find this information in a word that comes right after the long word with the event flags in the message structure.Write: move $18(a0),d7 You now have the code for the clicked menu item in the D7 register.If the user just pressed the right key and let it go without choosing a menu item,you'll find a $FFFF here.This word doesn't contain just one,but three pieces of information: Which menu was the item chosen from? Which menu item? Which submenu? The information is divided in three bit groups.The division is as follows: Bits 0-4 Menu title number Bits 5-10 Menu item number Bits 11-15 Submenu item number The numbering begins with zero-ie the first menu point of the first menu has the numbers 0 and 0. To try this out insert the following lines: move d7,d6 ;move code into D6 lsr #8,d7 ;shift right 11 times lsr #3,d7 ;submenu item now in D7 clr.l d5 roxr #1,d6 ;bit 0 in X-flag roxl #1,d5 ;menu number now in D5 and.l #$7f,d6 ;issolate lower bits cmp #$7f,d6 ;no menu item? beq loop ;no:continue lsr #4,d6 ;else menu item in D6 ende By making a test run with AssemPro,you can easily see if this works right-just look at the registers after the program is over. If you,for example,want to write a program with four menus with 10 menu items each,this sort of method is too much work-there are 44 tables.For this reason,lets look at a short program that takes care of the necessary structure table itself. The menu structure is built very simply-it doesn't offer submenus or the option of choosing items via the keyboard.If you want these extras,you can still use this program,but you'll have to use MOVE commands to insert the desired flags and pointers. The input that this program needs is a list of the menu names and the items in each menu.The addresses of the menu texts go in a table with the following simple form: dc.l Menu title 1 dc.l Point1,Point2,Point3,...,0 dc.l Menu title 2 dc.l Point1,Point2,Point3,...,0 dc.l Menu title 3 oder 0 This program is set up in such a way that up to four menus can lie next to each other (in normal screen resolution),which is often plenty.The table above ends by putting a zero instead of a pointer to the nxt menu title.As you can see,its pretty simple. This program is inserted in your big program right behind the "setmenu"label.After the "bsr setmenu"command is executed,the menu structure is built and initialized at the same time.You don't need to change the rest of the program,it'll be shorter that way. Heres the program fragment for the complete "setmenu"routine: setmenu: ;*initialize menu structure lea mentab,a0 ;pointer to text pointer in A0 lea menu,a1 ;pointer to menu field in A1 move #10,d1 ;horizontal menu position=10 menuloop: clr.l d2 ;vertical menu position=0 move.l a1,a2 ;save address of pointer tst.l (a0) ;another menu there? beq setmenu1 ;no:quit clr.l (a1)+ ;"no more menus"preperations move d1,(a1)+ ;set X-position add.l #70,d1 ;and increment move.l #50,(a1)+ ;Y-position and width move.l #$a0001,(a1)+ ;height and flag move.l (a0)+,(a1)+ ;menu title lea 12(a1),a3 move.l a3,(a1)+ ;pointer to menu item clr.l (a1)+ ;reserved words clr.l (a1)+ itemloop: tst.l (a0) ;last entry? beq menuend ;yes:menu done lea 54(a1),a3 move.l a3,(a1)+ ;pointer to next item move.l d2,(a1)+ ;X- and Y-positions add #10,d2 ;Y-position+10 move.l #$5a000a,(A1)+ ;WIDTH/HEIGHT move #$52,(a1)+ ;flag:normal clr.l (a1)+ ;no connection lea 16(a1),a3 move.l a3,(a1)+ ;text structure pointer clr.l (a1)+ ;no fill structure clr.l (a1)+ ;no command,no submenu clr.l (a1)+ ;and no continuation move #$1,(a1)+ ;set text structure:colour clr.l (a1)+ ;mode 0 move.l #$50003,(a1)+ ;X- and Y-position clr.l (a1)+ ;standard character set move.l (a0)+,(a1)+ ;text pointer clr.l (a1)+ ;no continuation bra itemloop ;next item... menuend: ;eventual transfer to next menu clr.l -54(a1) ;erase pointer to next item tst.l (a0)+ ;increment table pointer tst.l (a0) ;another menu there? beq setmenu1 ;no:done move.l a1,(a2) ;pointer to next menu bra menuloop ;and continue setmenu1: ;*initialize menu (like before) move.l intbase,a6 ;intuition base address in A6 move,l windowhd,a0 ;window structure in A0 lea menu,a1 ;pointer to menu structure jsr setmenustrip(a6) rts You need three things yet for this program:the memory to be used for the structure,the table of text pointers and the text.Heres an example: mentab: dc.l menu1 ;first menu title dc.l mp11,mp12,mp13 ;menu items dc.l 0 ;end of menu 1 dc.l menu2 ;second menu title dc.l mp21,mp22,mp23 ;menu items dc.l 0 ;end of menu 2 dc,l 0 ;you're out of menus! ;** Menu Text ** menu1: dc.b "Menu 1",0 mp11: dc.b "Point11",0 mp12: dc.b "Point12",0 mp13: dc.b "Point13",0 menu2: dc.b "Menu 2",0 mp21: dc.b "Point21",0 mp22: dc.b "Point22",0 mp23: dc.b "Point23",0 align ;** Storage space for menu structure ** menu: blk.w 500 Make sure that the memory area reserved for the menu structure is big enough and change the entry "blk.w 500"to the calculated value. If you use this program,and want to build some special features into the menu (for instance key commands),you can make entries in the menu structure table while the program is running.You can find the word (or byte or long word) that interests you in the table as follows: For example,to find the keyboard command byte of the second entry in the first menu,calculate as follows: Address = Start_address+Menu*30+(entry-1)*54+26 which in the example comes to: Address = menu+30+54+26 = menu+110 The 26 is the distance from the beginning of the MenuItem structure to the desired byte,the command byte.In this way,you can calculate the addresses and use MOVE commands to modify the menu to fit your wishes.By the way,in the example above,the correspond- ing flag bit must be set as well,so that the keyboard command is recognized. Now lets get back to the window.Its nice to have a window that you can change and close,but you really want to be able to output text in a window! 7.6.Text Output. ---------------- Its very easy to use Intuition's text output function.Use the PrintIText function (offset -216).It needs four parameters. In A0 A pointer to the RastPort of the window.You can find this in the window structure. In A1 A pointer to the text structure of the text that should be output. In D0 The X-position. In D1 The Y-position of the text in the window. Its very easy to enter the X- and Y-positions.You've already used the text structure twice (for requesters and menus). Whats new is accessing the windows RastPort.The RastPort is a structure that describes the window.The address is needed by several Intuition functions. The pointer to the RastPort starts at the 50th byte in the window structure.You can access it as follows: move.l windowhd,a0 ;address of window structure move.l 50(a0),a0 ;RastPort address in A0 Now you've got the address of the RastPort.Lets write a routine that prints a text.The X- and Y-positions are in D0 and D1 respectively and the address of the text structure in A1 before the routine is called: PrintIText = -216 ... print: move.l intbase,a6 ;intuition base address in A6 move.l windowhd,a0 ;address of window structure move.l 50(a0),a0 ;rastport address in A0 jsr printitext(a6) ;call function rts You can try out this routine by using the requesters text that is still in a structure of the program.Write the following lines before the "loop"label: lea btext,a1 ;pointer to text structure in A1 move.l #10,d0 ;X-position move.l #30,d1 ;Y-position of text bsr print ;output text Start the program and the text appears in the middle of the window If this doesn't happen,check the colour of the text in the text structure.Its probably zero.Just change it to three,and the text appears in red the next time you start the program. 7.7.Images. ----------- An image is a drawing that goes in a rectangular field and is defined bitwise.The disk symbol of the Intuition screen and the system gadgets in the screen and window borders are examples of such Images. The rectangle that the drawing goes in can be arbitrarily large, but each pixel in the rectangle needs its own bit,so programming screen-sized Images isn't advisable.You'll stick to an Image that requires about 32x16 bits-an Image thats about 3x1cm. You can make all sorts of images as you've seen looking at window gadgets.There is an Intuition functionthat draws an Image:It is the DrawImage function (offset -114) and it needs 4 parameters: In A0 The address of the rastport image is drawn in.You've already learned how to access this address in the section on the text function. In A1 The structure address of the image to be drawn. In D0 The relative X-position In D1 The relative Y-position of the drawing. Lets draw this picture in your window.It justs takes a simple routine.You just need to put the address of the image structure in A1 and the position of the image in D0 and D1 before you call it. DrawImage =-114 ... draw: ;*draw image move.l intbase,a6 ;intuition base address in A6 move.l windowhd,a0 ;pointer to window structure move.l 50(a0),a0 ;now,rastport address in A0 jsr drawimage(a6) ;draw image rts Now you need the structure of the image.The structure contains nine entries which have the following meanings: The first two entries are words which specify the distance in the X- and Y-direction from the co-ordinates that were given to tell where the image should be drawn.You'll just put two zeros here: image: dc.w 0,0 ;X- and Y-position Next come two words which specify the width and height of the image in pixels.Lets draw a 32x13 point image.Enter: dc.w 32,13 ;width and height of image The next word in the list specifies the number of planes in the drawing.If its a simple image that only uses two colours,just enter a one.For more colours,you'll need a correspondingly bigger number.When more colurs are worked with,the bit pattern of the image must have more data.Lets just have one bit plane: dc.w 1 ;one bitplane:2^1=2 colours Next comes a long word that points to the data of the image: dc.l imgdata ;pointer to image data The next two bytes are very interesting.The first byte,the PlanePick byte,tells which plane of the window or screen the image data should be written in.Since you only have one plane,you need to enter the bit plane of the window.This information is found in the bits of the byte-bit0 stands for plane 0,bit 1 for plane 1,etc ..You also define the colour of the image with this input.If you enter a two,every set bit of your image represents a red point. dc.b 2 ;drawing red:plane 1 The second byte,the PlaneOnOff byte,is an interesting enhancement. Each bit of the window bit plane corresponds to a whole number here.The only bytes that are interesting though are the ones that are cleared in the PlanePick byte.If the bit is set in PlaneOnOff, evert bit of the image in the corresponding plane is set.Otherwise they are cleared.To make sure that each bit of the image that isn't set appears white,enter a one.All the bits of the image that aren't set,are set in Plane 1 and appear white. dc.b 1 ;background:white The last entry of the structure is a lobg word that points to another image.You don't need this,so set the long word to zero: dc.l 0 ;no more images Heres a quick overview of the image structure: image: dc.w 0,0 ;X- and Y-positions dc.w 32,13 ;width and height of image dc.w 1 ;one bitplane:2^1=2 colours dc.l imgdata ;pointer to image data dc.b 2 ;drawing red:plane 1 dc.b 1 ;background:white dc.l 0 ;no more images Now lets produce the image data.Each image row uses a word,long word,or several of these represent the pattern.The set points of the image correspond to the set bits.This is repeated as often as the height of the image requires.The data on each line must begin on a word border,on a even address. For the example,its easy to decide on the data,since you're going 32 points across-that corresponds to exacty one long word.Its easiest to program the image using the binary representation of the data. Lets use,as an example,an image that represents a switch in "OFF" mode.This form is chosen for a good reason,so you should type it in.In the chapter on gadgets thats coming up,we'll show you how to turn the switch on.Here is the example data for the switch image: imgdata: ;Data for switch in "OFF" mode dc.l %00000000000000000000000000000000 dc.l %00000000000000000000111000000000 dc.l %00011101110111000001111100000000 dc.l %00010101000100000001111100000000 dc.l %00010101100110000001111000000000 dc.l %00011101000100000011100000000000 dc.l %00000000000000000111000000000000 dc.l %00000000000000001110000000000000 dc.l %00000000000111111111100000000000 dc.l %00000000001111111111110000000000 dc.l %00000000001111111111110000000000 dc.l %00000000000110000001100000000000 dc.l %00000000000000000000000000000000 Once you've typed in this data,you can experiment with displaying it on the screen.Enter the following lines before the "loop"label: move.l image,a1 ;pointer to image structure move #30,d0 ;X-postion in window move #50,d1 ;Y-position bsr draw ;draw image How do you like the image on the screen?You'll run into this switch again when we talk about putting the switch in the "ON" state when discussing gadgets.You need to look at other methods of drawing in the window first,though. 7.8.Borders. ------------ A border is a collection of lines that are connected.They can be of any length or at any angle.Intuition lets you draw borders to do things like put frames around windows and screens.They are used to put borders around pictures or text,especially for use with string gadgets.We'll talk about that later,though. Its easy to draw borders.Just use the Intuition function DrawBorder (offset -108) which needs four parameters: In A0 The rastport address of the output medium the lines should be drawn in.Use your window. In A1 The address of the border structure.We'll look at the form of this structure shortly. In D0 The relative X-co-ordinate which is used with the X- and Y co-ordinate list to calulate the actual line co-ordinates. In D1 The relative Y-co-ordinates.Relative,here too,means that this is relative to the upper left corner of the screen. Lets write a short routine that is called with three parameters. The structure address in A1 and the X and Y co-ordinates are in D0 and D1 respectively when the routine is called.The border is drawn in the window whose structure address is in "windowhd". DrawBorder =-108 ... borderdraw: ;* draw several lines move.l inbase,a6 ;intuition base address in A6 move.l windowhd,a0 ;pointer to window structure move.l 50(a0),a0 ;now rastport address in A0 jsr drawborder(a6) ;draw lines rts Now lets look at the border structure.The list needs the eight following parameters: First,you need two words for the vertical and horizontal distance from the co-ordinates given in the function call.To avoid losing sight of some of the many distance entries,put two zeros here: border: dc.w 0 ;horizontal distance dc.w 0 ;vertical distance Next come two bytes that determine the colour.Use a red frame: dc.b 3 ;red frame dc.b 0 ;background (unused) As you can see,the background colour isn't used.You have two modes to choose between for drawing the lines.The following mode determines the mode that is used.If it is zero,each line is drawn in the colour chosen,no matter what was done before.This is the JAM1 mode.The other mode is the XOR mode which ignores both colour entries.In this mode,all the points that lie under the line have their colour value inverted.As a result,a white point becomes black,and a blue one becomes red.That is mode two.Lets use the JAM1 mode for the example: dc.b 0 ;mode:JAM1 (2=XOR) The next entry specifies how many co-ordinate pairs there are in the list.Since this word must be on an even address,you need to use the "align"peudo-op first.Then enter the number of pairs. Remember that you need three points to draw two lines:beginning, corner and end point.To draw a rectangular frame,you need five pairs: dc.b 5 ;5 X,Y pairs used together The next item is a pointer to the co-ordinate table that contains a list of points to be connected: dc.l coord ;pointer to cordinate table The border structures final entry is a long word that can point to another border structure.If you don't have any more structures to be pointed to,just enter a zero here.The pointer is useful for connecting two independant border structures-for example,to produce a two coloured frame that really stands out.You don't need this pointer in the example,though: dc.l 0 ;no more structures Thats the border structure.Now lets look at the co-ordinate list. For the example,it consists of five pairs of numbers which represent a rectangle.I recommend entering these values,because you'll use them in example programs further down the line. coord: ;coordinates for rectangle frame dc.w -2,-2 dc.w 80,-2 dc.w 80,9 dc.w -2,9 dc.w -2,-2 Heres a quick overview of the border structure: border: dc.w 0 ;horizontal distance dc.w 0 ;vertical distance dc.b 3 ;red frame dc.b 0 ;background (unused) dc.b 0 ;mode:JAM1 (2=XOR) dc.b 5 ;5 X,Y pairs used together dc.l coord ;pointer to cordinate table dc.l 0 ;no more structures coord: ;coordinates for rectangle frame dc.w -2,-2 dc.w 80,-2 dc.w 80,9 dc.w -2,9 dc.w -2,-2 Once you've typed this in,you can try the whole thing out.Type the following lines before the "loop"label in the program: lea border,a1 ;address of the border structure move #20,d0 ;X base position move #80,d1 ;Y base position bsr drawborder ;draw frame As you can see,using enough X and Y co-ordinates,you can draw the Eiffel tower.Thats enough about simple drawings.You want to put some life into your drawings and text.Lets manipulate them with the mouse! 7.9.Gadgets. ------------ We already talked a bit about gadgets when you looked at screen construction.Looking at system gadgets like the window close symbol,you can activate by clicking and causes a program function to be executed. You can make your own gadgets as well.Intuition allows you a lot of interesting possibilities. There are four types of gadgets: Boolean gadgets are used in Yes/No situations.You can click and activate it (Yes) or deactivate it (No). String gadgets are used to accept input of text of a specified length. Integer gadgets are a special sort of string gadgets which accept the input of a decimal number.Intuition converts the value into a long word and sends it to the program. Proportional gadgets let you choose an analog value with the mouse You can move these around with the mouse. 7.9.1.Boolean Gadgets. ---------------------- Lets start with the simplest type,the boolean gadget.an example of this sort of gadget is the close symbol of the window.The only status it differenciates between are clicked and not clicked.Lets develop a gadget of this type step by step.The flags and other parameters are similar for the other gadgets. Each gadget needs a structure containing fifteen entries.There is a pointer to this structure in window,screen or requester that the gadget is to appear in.Theres always a long word available for this purpose.Up to this point,you've just put a zero there.If there is an address of a gadget structure there,the gadget or gadgets are displayed when the window is opened. A gadget structure as the following entries: The first long word is a pointer to the next gadget to be installed.The gadgets are displayed in a row,like pearls on a string.This pointer is the first gadget in this linked list of gadgets.If you just want one gadget in your window,put a zero here: gadget1: dc.l 0 ;no more gadgets The next two words determine the position of the gadget in the window.There are several ways to determine the position.Use flags to access the various possibilities.Lets start with a gadget that stays in one spot: dc.w 40 ;X and dc.w 50 ;Y position of the gadget The next two words determine the size of the gadgets Hit box.This box isn't the visible size of the gadget (that depends on the image data).It is the size of the rectangle that Intuition should watch.If the mouse pointer is moved into this box and the left button pressed,the gadget is activated.Clicking on parts of the gadget that are outside this box have no effect! dc.w 32 ;width and dc.w 13 ;height of the hit box Next comes the word whose bits determine the properties of the gadget.Bits 0 and 1 determine what should happen when this objects hit box is clicked on.The meanings of the various values of these bits go as follows: Bit 0 1 Value Name Meaning ------------------------------------------------------------------ 0 0 0 GADGHCOMP The gadget inverted 0 1 1 GADGHBOX The gadget framed 1 0 2 GADGHIMAGE Another image appears 1 1 3 GADGHNONE No reaction Bit 2 determines whether the gadget should consist of a drawing or a border.If it is set(Value+4),it is treated as an image;otherwise its treated like a border. The next bit determines if the gadget should appear in the upper or lower border of the frame.If it is set(Value+8).the position is relative to the lower border;otherwise it is relative to the upper border.The next bit as the same meaning for the horizontal position.If set(Value+$10),it is a relative positioning.Otherwise, it is an absolute positioning. Notice that when you define a gadget to be relative,you must have a negative value in the position input in the first word of the structure.Since the desired position isn't under,but its over this position! In this way,you can choose either absolute or relative positioning of the gadget.An example of a gadget that is positioned absolutely is the system gadget,close window.An example of a relative gadget is the symbol for changing the size. The width and height of the gadgets hit box can also be relative to the window size.Specify this by using bit 5 for width (Value + $20)and bit 6 for the height (Value +$40).A set bit mens a relative size. Bit 7 (Value+$80)makes the object active as soon as the window is opened. Bit 8 (Value+$100)determines whether the gadget can be used or not If this bit is set,the gadget can't be activated. For the example,you'll use absolute positioning and size,the inverted appearance for the activated gadget,and the representation of the object as an image.That means you must use the value four: dc.w 4 ;flags:image,invert Next comes a word whose bits are used as flags.This flag is called the Activation Flag.It determines the functions of the gadget.The bits,their values and meanings follow: Bit Value Name Meaning ------------------------------------------------------------------ 0 1 RELVERIFY Causes the gadget to be activated only when the left mouse key is let loose over the gadget. 1 2 GADGIMMEDIATE Lets the gadget be active as soon as there is a click. 2 4 ENDGADGET Lets you choose to end this choice and have it disappear if this is a requester gadget. 3 8 FOLLOWMOUSE Lets the gadget know the mouse position at regular intervals from the time it is selected until the time it is deselected.You can use this to move the gadget with the mouse when you want to change the gadget position. 4 $10 RIGHTBORDER This makes sure thay when borders are used that the page is adjusted to the size of the gadget so that it fits in the border. 5 $20 LEFTBORDER 6 $40 TOPBORDER 7 $80 BOTTOMBORDER 8 $100 TOGGLESELECT Allows the objects state to change every time it is clicked.If activated,it becomes deactivated and vice versa. 9 $200 STRINGCENTRE For a string gadget,these two bits determine whether the string should appear centred or right justified.If neither is set,the string is output left justified. 10 $400 STRINGRIGHT 11 $800 LONGINT Turns a string gadget into a Integer gadget (explanation later). 12 $1000 ALTKEYMAP Causes another ketboard placement to be in effect for string gadget input Thats it for the activation flags.Lets choose the TOGGLESELECT and GADGETIMMEDIATED flags for example: dc.w $102 ;activation The next word of the gadget structure determines the gadget type. Heres the meaning of the individual bits: Bit Value Name Meaning(report what circumstances) ---------------------------------------------------------------- 0 1 BOOLGADGET This is a boolean gadget 1 2 GADGET002 2 4 STRGADGET String order Integer gadget 0+1 3 PROPGADGET Proportional gadget System gadgets: 4 $10 SIZING Size changing gadget 5 $20 WDRAGGING Moving gadget for window 4+5 $30 SDRAGGING Same for screen 6 $40 WUPFRONT Gadget to move window forward 6+4 $50 SUPFRONT Gadget to move screen forward 6+5 $60 WDOWNBACK Move window back 6+5+4 $70 SDOWNBACK Move screen back 7 $80 CLOSE Window close gadget Type definitions: 12 $1000 REQGADGET Requester gadget 13 $2000 GZZGADGET Border gadget in GIMMEZEROZERO window 14 $4000 SCRGADGET Screen gadget when set 15 $8000 SYSGADGET System gadget when set You want to use a simple boolean gadget for your example,so enter: dc.w 1 ;gadget type:boolean Next comes a pointer to the gadget structure.The first pointer contains the address of the image or border structure which should be used to represent the gadget.If no representation is needed,put a zero here.You want to represent the gadget as an image,so put a pointer to the image structure that you produced in the chapter about images: dc.l image ;gadget image The next pointer is only used if the GADGHIMAGE flag in the flag word of the structure is set.This is a pointer to another structure that should be put on the screen when the object is activated.If a border structure is used for the gadget represent- ation,this must be a border structure as well.You won't use a second image,so put a zero here: dc.l 0 ;no new gadget displayed The next pointer is to the text structure that should be output by the gadget.If no text is needed,just put a zero here.You want to use some text,however: dc.l ggtext ;gadget text Now comes a long word that determines which gadgets are deactivated when this is activated.This function still doesn't work right so put a zero here: dc.l 0 ;no exclude You'll set the next pointer to zero as well,because it is only used for String and Proportional gadgets.For these gadgets,this is a special structure to describe the characteristics of the gadget. Its called SpecialInfo. dc.l 0 ;no SpecialInfo The next word contains the Gadget Identification (ID) number: dc.w 1 ;gadget ID Finally there is a long word that doesn't have any function,so put a zero here: dc.l 0 ;user data (ignore) Thats it.Heres a quick overview of the gadget structure: gadget1: dc.l 0 ;no more gadgets dc.w 40 ;X and dc.w 50 ;Y position of gadget dc.w 32 ;width and dc.w 13 ;height of hit box dc.w 4 ;flags:image,invert dc.w $102 ;activation flags dc.w 1 ;gadget type:boolean dc.l image ;gadget image dc.l 0 ;no new gadget displayed dc.l ggtext ;gadget text dc.l 0 ;no exclude dc.l 0 ;no SpecialInfo dc.w 1 ;gadget ID dc.l 0 ;user data (ignore) You've already prepared a structure that you can use for this image.Now you need the text that appears under the gadget. Since the gadget looks like a switch,label it "switch".The text structure looks like this: ggtext: dc.b 1,0 ;colours dc.b 1 ;mode align dc.w -8,14 ;X and Y position dc.l 0 ;standard font dc.l swtext ;pointer to text dc.l 0 ;no more text swtext: dc.b "switch",0 align Once you've typed this in,save it,assemble it and start again.You can click the switch and cause it to be inverted.Click it again, and it appears normal. Now you can experriment with the structure.If you change the flag from four to five,you can cause the gadget to be framed when it is activated.Set the RELVERIFY bit(bit0:+1)in the Activation Flag word.Then you can move the mouse pointer onto the object and press the button.It is activated.Keep the mouse button pressed down and move the mouse.Once you leave the hit box,the activation disapears This way,you can avoid accidently activating a gadget. Now you want to display the switch in an on state.This is easy.All you need to do is produce another image structure,one for the on state.You put this pointer in the long word right after the pointer to the normal image structure.You can change the flag word to six which causes a second image to be displayed when the gadget is activated. Here is the image structure for the switch in the one state. image2: dc.w 0,0 ;no offset dc.w 32,13 ;32x13 pixels dc.w 1 ;mode 1 dc.l imgdata2 ;pointer to the data dc.b 2,1 ;same colours as before dc.l 0 ;nothing else imgdata2: ;data for switch in the On state dc.l %00000000000000000000000000000000 dc.l %00000000011100000000000000000000 dc.l %00000000111110000011101001000000 dc.l %00000000111110000010101101000000 dc.l %00000000011110000010101011000000 dc.l %00000000000111000011101001000000 dc.l %00000000000011100000000000000000 dc.l %00000000000001110000000000000000 dc.l %00000000000111111111100000000000 dc.l %00000000001111111111110000000000 dc.l %00000000001111111111110000000000 dc.l %00000000000110000001100000000000 dc.l %00000000000000000000000000000000 Now the state of the object can be determined by looking at the picture.If the gadget is activated,the switch is on.If not,the switch is off. Thats it for boolean gadgets.You can learn about the things you did'nt touch with some experimentation.You want to get to the string gadgets that also do some interesting things. 7.9.2.String Gadgets. --------------------- Lets pretend you want a program to load data from the disk.To get the user to enter the filename,you need to output text telling the user to enter the name.Then you need to call an input routine to evaluate the keyboard input. Its easier and more elegant to use a String gadget.This function allows for easy input and/or editingof short text.You have the option of having the text framed.The Undo function can be used by pressing the right key and a "Q",and the old contents of the gadget,the old text are restored. You can also vary the size of the text and the input field.If the text is longer than the input field is wide,the text is moved back and forth through the visible area when you move the cursor keys or the normal input to the border. You can also restrict input to just digits.This makes it posible to accept numeric input.Intuition even converts the digit string into a binary number.This saves the machine language programmer some work.A specialized String gadget of this sort is called a Integer gadget. The structure is similar to the Boolean gadgets structure.There are only two major differences: The type word of the structure must be a four to declare that this is a String gadget (STRGADGET). The pointer to the SpecialInfo structure is needed.Put a pointer to the StringInfo structure that you are going to design later here. The width and height entries in the gadget structure have a different meaning than they had previously.They do declare the area in which you can bring the mouse pointer to activate the String gadget.However,it is also used for representation of text. These values determine the size of the box in which the text is output.You should surround the box with a border using the Border function,so that the user can see where it is. If the text is longer than the box,only a portion of it is seen on the screen.You can move through the area by entering text or using the left/right cursor keys to move through the box.The characters that are entered are inserted at the cursor position,so the rest of the text is shifted by one character when you are on the right edge of the input area.The following functions can be used for editing this text: Cursor key left/right Moves the cursor over the text thats already on hand.Moves the text through the Container. Cursor keys with Puts the cursor on the beginning or the end of the text. Deletes the character under the cursor. Deletes the character to the left of the cursor. Ends text input. right+"Q" This is the Undo function.It replaces the text with the original contents. The StringInfo structure only has a few entries: First theres a pointer to the memory area that is used to store the text that is input.The memory buffer must be big enough to handle all the text entered. strinfo: dc.l strpuffer ;pointer to text buffer Next comes the pointer to the Undo buffer.This pointer and this buffer are only needed if you want the Undo function.If you do,you must have a buffer that is at least as big as your text buffer. Every time the string gadget function is called,the text buffers contents are copied into this buffer.To get the old contents back, just press the right key and the "Q"key.The contents of the Undo buffer are copied back to the text buffer.If you use several string gadgets in a program,you can use the same Undo buffer for all of them,since only one string gadget is used at one time. dc.l undo ;pointer to undo buffer The following word contains the cursor position in the text.You should set this word to zero,so that the user can see the beginning of the text when the string gadget appears. dc.w 0 ;cursor position The next word contains the maximum number of characters that can be input.If you type one more than this number of characters,the screen blinks,to show that you can't enter a longer input string. The number of characters and the reserved space for the input field don't have to agree,since text can be scrolled by typing. dc.w 10 ;maximum # of characters The following word tells at which character of text in the buffer, the output to the box should begin.You should put a zero here,so that the user can see the beginning of the text. dc.w 0 ;output text from this character The next five words are used by Intuition,so you don't have to initialize them.Just put zeros here.The words contain the following information: dc.w 0 ;character position in undo buffer dc.w 0 ;number of chars in text buffer dc.w 0 ;number of chars visible in box dc.w 0 ;horizontal box offset dc.w 0 ;vertical box offset The next two long words are initialized by Intuition as well: dc.l 0 ;pointer to rastport dc.l 0 ;long word with value of the input ; ;(for integer gadgets) The final entry is a pointer to the keyboard table that is used if the ALTKEYMAP flag of the gadget is set. dc.l 0 ;standard keyboard table Heres a quick overview of the StringInfo structure: strinfo: dc.l strpuffer ;pointer to text buffer dc.l undo ;pointer to undo buffer dc.w 0 ;cursor position dc.w 10 ;maximum # of characters dc.w 0 ;output text from this character dc.w 0 ;character position in undo buffer dc.w 0 ;number of chars in text buffer dc.w 0 ;number of chars visible in box dc.w 0 ;horizontal box offset dc.w 0 ;vertical box offset dc.l 0 ;pointer to rastport dc.l 0 ;long word with value of input ; ;(for integer gadgets) dc.l 0 ;standard keyboard table Here are the text and undo buffers: strpuffer: dc.b "Hello!",0,0,0 undo: dc.l 0,0,0,0 align Once you've entered these lines,you can either alter the old gadget structure or build a new one.We'd recommend building another gadget structure so that you can have the switch and use it later.Change the first pointer in the old structure from zero to "gadget1"and insert this new structure.Here is an example strucure for the string gadget.It as the following entries: gadget1: ;*structure for string gadget dc.l 0 ;no more gadgets dc.w 20,80 ;position dc.w 80,10 ;width and height of box dc.w 0 ;flags:normal dc.w 2 ;activation($802 for long int) dc.w 4 ;type:string gadget dc.l border ;pointer to border dc.l 0 ;no drawing selected dc.l 0 ;no text dc.l 0 ;no exclude dc.l strinfo ;pointer to stringinfo structure dc.w 2 ;gadget ID dc.l 0 ;no user data border: ;*border for box frame dc.w 0,0 ;no offset dc.b 3,3 ;red colour dc.b 0 ;mode:JAM1 dc.b 5 ;5 X,Y pairs dc.l coord ;pointer to coordinates table dc.l 0 ;no more structures coord: ;*coordinates for frame dc.w -2,-2 ;start in upper left corner dc.w 80,-2 ;upper right dc.w 80,9 ;lower right dc.w -2,9 ;lower left dc.w -2,-2 ;back to beginning This data causes a red rectangle,the border,to appear around the "Hello!"text.You can change the text by clicking in the field and editing once the cursor appears.If you type something wrong,you can use the undo function(the right key and the Q key),to get "Hello!"back. Once you've done some typing and deactivated the gadget by pressing or by clicking outside the field (cursors disapear),you can terminate the program. Change the activation flag to $802 and the "strbuffer"to "dc.l 0,0,0,0",assemble,and then start the program.You can type in the string gadget once it has been activated,but you can only enter digits.The screen blinks if you enter letters. Enter a number,and then end the program after deactivating the gadget.If you look at the stringinfo structure you can look at the value of the number you input(in hex)in the eight long word. After looking at boolean,text and numeric input to gadgets,lets look at Proportional gadgets which allow the user to enter analog values by moving a symbol. 7.9.3.Proportional Gadgets. --------------------------- You've seen the advantages of slider devices over knobs that you turn,maybe on a hifi,maybe on a toaster,but certainly someplace. Its easier to tell the state the item is in with a slider, especially if several such devices are next to each other(for example graphic equalizers).You can represent sliders on the Amigas screen and work with them with the mouse.This offers a nice way to represent information graphically in your programs. You can do this with gadgets.Using Proportional gadgets,you can put a symbol in a frame and move horzontally and/or vertically.The size of the frame and the slider can be variable size,so that the frame size is relative to the screen size so when the window changes size,it will also.The slider can be set up so that its size in the grows or shrinks. These are best seen via example and experimentation.(The posibilities mentioned do not form a complete list by any stretch of the imagination.)You want to set up a simple Proportional gadget that can be moved horizontally. You need a gadget structure that as the same form as others.To show the differences,heres a complete example structure for your gadget.You can connect this gadget to the other one,by changing the first long word in the last structure to "dc.l gadget2". gadget2: ;*structure for Proportional gadget dc.l 0 ;no more gadgets dc.w 150,30 ;position dc.w 100,10 ;width and height of frame dc.w 4 ;flags:GADGIMAGE dc.w 2 ;activation:GADGIMMEDIATE dc.w 3 ;type:proportional gadget dc.l mover ;pointer to slider data dc.l 0 ;no select structure dc.l 0 ;no text dc.l 0 ;no exclude dc.l propinfo ;pointer to propinfo structure dc.w 3 ;gadget ID dc.l 0 ;no user data You see two special features.Use an image structure for the mover and put a pointer to another structure in the spot for the Special Info pointer. First,lets look at the "mover"structure,the sliders image structure.Heres an example of this structure: mover: ;*structure for slider image dc.w 0,0 ;no offset dc.w 16,7 ;16x7 pixels big dc.w 1 ;one bit plane dc.l moverdata ;pointer to image data dc.b 1,0 ;colour:white dc.l 0 ;don't continue moverdata: ;*image data for mover dc.w %0111111111111110 dc.w %0101111111111010 dc.w %0101011111101010 dc.w %0101010110101010 dc.w %0101011111101010 dc.w %0101111111111010 dc.w %0111111111111110 Up till now,there was'nt anything new.Now lets look at the PropInfo structure that describes the properties of the Proportional gadget. The structure starts with a flag word that contains the following bits: Bits Value Name Meaning ----------------------------------------------------------------- 0 1 AUTOKNOB Mover is set up automatically 1 2 FREEHORIZ Allows horizontal movement 2 4 FREEVERT Allows vertical movement 3 8 PROPBORDERLESS Turns off automatic framing 8 $100 KNOBHIT Set when the mover is touched You can set the first four bits to get the representation that you want.Bit 8 is set by Intuition when the mover is clicked with the mouse pointer. Bit 0,AUTOKNOB,allos for the simplest sort of Proportional gadget. If this bit is set,no move data are used for the mover image. Instead,a white mover is generated that is adjusted to the size of the box and the values to be represented.When you use this slider to represent the displayed lines in a long text of a program,the displayed lines are a percentage of the total text.The relationship between the total number of lines and the lines shown is represented by an AUTOKNOB as the relationship between the frame and the slider.The bigger the percentage,the bigger the slider is.You don't want to work with this though,even though it is simple and interesting,because a simple white button isn't particularly attractive.If you experiment with it,make sure that the pointer to the image data points to a four word long buffer that Intuition can use to store values.The buffer is of the following form: buffer: dc.w 0 ;X position of the slider in the box dc.w 0 ;Y position in the box dc.w 0 ;width of slider dc.w 0 ;height of slider Leys look at the PropInfo structure.Since you're not using AUTOKNOB and wish to allow horizontal movement only,put two in as a flag: propinfo: dc.w 2 ;flags:FREEHORIZ In the next two words of the structure,the horizontal (HorizPot) and vertical (VertPot) position of sliders are stored.A value of zero means left or upper,while the value $FFFF means right or lower.The value that results from movement is in this range.You set these values to zero at the start of the program.After moving the mouse,there is different values here. dc.w 0,0 ;X and Y position of the slider Next come two words which determine the size of the AUTOKNOB or the step size of the slider(this determines how far the slider moves when you click in the box next to the slider).These words are called HorizBody (horizontal movement) and VertBody (vertical movement). dc.w $ffff/16 ;horizontal step size:1/16 dc.w 0 ;no vertical movement ;The next six words are initialized by Intuition. dc.w 0 ;box width dc.w 0 ;box height dc.w 0 ;absolute step size horizontal dc.w 0 ;and vertical dc.w 0 ;left border of box dc.w 0 ;upper border of box Thats it.Heres a quick overview of the PropInfo structure: prpoinfo: dc.w 2 ;flags:FREEHORIZ dc.w 0,0 ;X and Y position of slider dc.w $ffff/16 ;horizontal step size:1/16 dc.w 0 ;no vertical movement dc.w 0 ;box width dc.w 0 ;box height dc.w 0 ;absolute step size horizontal dc.w 0 ;and vertical dc.w 0 ;left border of box dc.w 0 ;upper border of box Once you've typed this in,you can start the program and try it out. You can also try vertical movement by setting the flag word equal to six,the vertical step size to $FFFF/10,and the height of the gadget to 80,for the example.To try out the AUTOKNOBs,change the flag value to seven. 7.10.Example Program. --------------------- Here is a complete example program using what you have learned in this chapter: ;7_Intuition.asm ;** Demo-Program for working with Intuition ** movescreen =-162 openscreen =-198 closescreen =-66 openwindow =-204 closewindow =-72 autorequest =-348 setmenustrip =-264 clearmenustrip=-54 printitext =-216 drawimage =-144 drawborder =-108 displaybeep =-96 closelibrary =-414 openlib =-408 execbase = 4 getmsg =-372 joy2 =$dff0c fire =$bfe001 ;!!!when > 500kb !!! ;org $40000 ;load $40000 ; or use AssemPro to place in CHIP RAM ;!!!!!!!!!!!!!!!!!!!!!!! run: bsr openint bsr scropen bsr windopen bsr setmenu bsr print lea border,a1 move #22,d0 move #30,d1 bsr borderdraw bsr draw bsr request loop: move.l execbase,a6 move.l windowhd,a0 move.l 86(a0),a0 ;user port jsr getmsg(a6) tst.l d0 beq loop ;no event move.l d0,a0 move.l $16(a0),msg ;event:LO=item,HI=Event move.l msg,d6 ;to test move.l d6,d7 lsr #8,d7 lsr #3,d7 ;sub menu point in D7 clr.l d5 roxr #1,d6 roxl #1,d5 ;menu number in D5 and.l #$7f,d6 cmp #$7f,d6 ;no menu point? beq loop ;no:continue lsr #4,d6 ;menu point in D6 cmp #1,d6 ;point 2? bne no1 move,l intbase,a6 move.l screenhd,a0 jsr displaybeep(a6) no1: cmp #0,d6 bne loop ende: bsr clearmenu bsr windclose bsr scrclose bsr closeint rts openint: move.l execbase,a6 lea intname,a1 jsr openlib(a6) move.l d0,intbase rts closeint: move.l execbase,a6 move.l intbase,a1 jsr closelibrary(a6) rts scropen: move.l inbase,a6 lea screen_defs,a0 jsr openscreen(a6) move.l d0,screenhd scrclose: move.l inbase,a6 move.l screenhd,a0 jsr closescreen(a6) rts scrmove: move.l intbase,a6 move,l screenhd,a0 jsr movescreen(a6) rts windopen: move.l intbase,a6 lea windowdef,a0 jsr openwindow(a6) move.l d0,windowhd rts windclose: move.l intbase,a6 move.l windowhd,a0 jsr closewindow(a6) rts request: move.l windowhd,a0 lea btext,a1 lea ltext,a2 lea rtext,a3 move.l #0,d0 move.l #0,d1 move.l #180,d2 move.l #80,d3 move.l intbase,a6 jsr autorequest(a6) rts setmenu: lea mentab,a0 ;pointer to text pointer in A0 lea menu,a1 ;pointer to menu field in A1 move #10,d1 ;menu position = 10 menuloop: clr.l d2 ;menu point-Y=0 move.l a1,a2 ;save pointer tst.l (a0) beq setmenu1 ;end clr.l (a1)+ move d1,(a1)+ add.l #70,d1 move.l #50,(a1)+ move.l #$a0001,(a1)+ move.l (a0)+,(a1)+ ;menu title lea 12(a1),a3 move.l a3,(a1)+ ;menu point clr.l (a1)+ clr.l (a1)+ itemloop: tst.l (a0) ;last one? beq menuend ;yes lea 54(a1),a3 move.l a3,(a1)+ ;pointer to next point move.l d2,(a1)+ ;X/Y add #10,d2 move.l #$5a000a,(a1)+ ;width/height move #$52,(a1)+ clr.l (a1)+ lea 16(a1),a3 move.l a3,(a1)+ ;text structor-pointer clr.l (a1)+ clr.l (a1)+ clr.l (a1)+ move #$1,(a1)+ ;text-structor set clr (a1)+ move.l #$50003,(a1)+ clr.l (a1)+ move.l (a0)+,(a1)+ ;text pointer clr.l (a1)+ bra itemloop ;next point... menuend: clr.l -54(a1) tst.l (a0)+ tst.l (a0) ;still in menu? beq setmenu1 ;no:ready move.l a1,(a2) ;pointer to next menu bra menuloop ;and continue setmenu1: move.l intbase,a6 move.l windowhd,a0 lea menu,a1 jsr setmenustrip(a6) rts clearmenu: move.l intbase,a6 move.l windowhd,a0 jsr clearmenustrip(a6) rts print: move.l intbase,a6 move.l windowhd,a0 move.l 50(a0),a0 lea ggtext,a1 move.l #30,d0 ;X move.l #16,d1 ;Y jsr printitext(a6) rts draw: move.l intbase,a6 move.l windowhd,a0 move.l 50(a0),a0 lea image,a1 move.l #200,d0 move.l #100,d1 jsr drawimage(a6) rts borderdraw: move.l intbase,a6 move.l windowhd,a0 move.l 50(a0),a0 jsr drawborder(a6) rts screen_defs: dc.w 0,0 dc.w 640,200 dc.w 4 dc.b 0 dc.b 1 dc.w $800 dc.w 15 dc.l 0 dc.l tite1 dc.l 0 dc.l 0 windowdef: dc.w 10,20 dc.w 300,150 dc.b 0,1 dc.l $300 dc.l $100f dc.l gadget dc.l 0 dc.l windname screenhd: dc.l 0 dc.l 0 dc.w 200,40,600,200 dc.w $f btext: dc.b 3,3 dc.b 0 align dc.w 10,10 dc.l 0 dc.l bodytxt dc.l 0 bodytxt:dc.b "Requester-Text",0 align ltext: dc.b 3,1 dc.b 0 align dc.w 5,3 dc.l 0 dc.l lefttext dc.l 0 lefttext: dc.b "left",0 align rtext: dc.b 0,1 dc.b 0 align dc.w 5,3 dc.l 0 dc.l righttext dc.l 0 righttext: dc.b "right",0 align tite1: dc.b "User Screen",0 windname: dc.b "Window-Title",0 align windowhd: dc.l 0 intbase:dc.l 0 intname:dc.b "intuition.library",0 align msg:dc.l 0 mentab: dc.l menu1 dc.l mp11,np12,mp13,mp14,mp15,mp16,mp17,mp18,mp19,0 dc.l menu2 dc.l mp21,mp22,mp23,0 dc.l menu3 dc.l mp31,mp32,0 dc.l menu4,mp41,0 dc.l 0 menu1: dc.b "Menu 1",0 mp11: dc.b "Point 11",0 mp12: dc.b "Point 12",0 mp13: dc.b "Point 13",0 mp14: dc.b "Point 14",0 mp15: dc.b "Point 15",0 mp16: dc.b "Point 16",0 mp17: dc.b "Point 17",0 mp18: dc.b "Point 18",0 mp19: dc.b "Point 19",0 menu2: dc.b "Menu 2",0 mp21: dc.b "End!",0 mp22: dc.b "Beep",0 mp23: dc.b "Point 23",0 menu3: dc.b "Menu 3",0 mp31: dc.b "Point 31",0 mp32: dc.b "Point 32",0 menu4: dc.b "Menu 4",0 mp41: dc.b "Point 41",0 align gadget: dc.l gadget1 dc.w 20,80,80,10 dc.w 0 dc.w $2 ;activation,$802 for longint dc.w 4 dc.l border dc.l 0 dc.l 0 dc.l 0 dc.l strinfo dc.w 2 dc.l 0 border: dc.w 0,0 dc.b 1,0,0 dc.d 5 ;XY-pair dc.l koord dc.l 0 koord: dc.w -2,-2,80,-2,80,9,-2,9,-2,-2 strinfo: dc.l strpuffer dc.l undo dc.w 0 ;cursor position dc.w 10 ;max.char dc.w 0 dc.w 0,0,0,0,0 dc.l 0,0,0 strpuffer: dc.b "Hello!",0,0,0 undo: dc.l 0,0,0 align gadget1: dc.l gadget2 ;more gadget dc.w 40,50,32,13 dc.w $6 ;flags:invert dc.w $103 ;activate dc.w 1 ;gadget type dc.l image ;gadget image dc.l image2 ;select gadget dc.l ggtext ;gadget text dc.l 0 ;no exclude dc.l 0 ;special info dc.w 1 ;ID dc.l 0 ;user data ggtext: dc.b 1,0,1 align dc.w -8,14 dc.l 0 dc.l swtext dc,l 0 swtext: dc.b "Switch",0 align image: dc.w 0,0 dc.w 32,13 dc.w 1 dc.l imgdata dc.b 2,1 dc.l 0 image2: dc.w 0,0 dc.w 32,13 dc.w 1 dc.l imgdata2 dc.b 2,1 dc.l 0 imgdata: dc.l 0 dc.l %00000000011100000000000000000000 dc.l %00000000111110000011101001000000 dc.l %00000000111110000010101101000000 dc.l %00000000011110000010101011000000 dc.l %00000000000111000011101001000000 dc.l %00000000000011100000000000000000 dc.l %00000000000001110000000000000000 dc.l %00000000000111111111100000000000 dc.l %00000000001111111111110000000000 dc.l %00000000001111111111110000000000 dc.l %00000000000110000001100000000000 dc.l 0 imgdata2: dc.l 0 dc.l %00000000000000000000111000000000 dc.l %00011101110111000001111100000000 dc.l %00010101000100000001111100000000 dc.l %00010101100110000001111000000000 dc.l %00011101000100000011100000000000 dc.l %00000000000000000111000000000000 dc.l %00000000000000001110000000000000 dc.l %00000000000111111111100000000000 dc.l %00000000001111111111110000000000 dc.l %00000000001111111111110000000000 dc.l %00000000000110000001100000000000 dc.l 0 gadget2: dc.l 0 dc.w 150,30,100,50 dc.w 5 dc.w 2 dc.w 3 ;prop.gadet dc.l mover ;border dc.l 0,0,0 dc.l specinfo dc.w 3 dc.l 0 specinfo: dc.w 6 ;flags:free horiz dc.w 0,0 dc.w $ffff/10,$ffff/5 dc.w 0,0,0,0,0,0 mover: dc.w 0,0,16,7 dc.w 1 dc.l moverdata dc.b 1,0 dc.l 0 moverdata: dc.w %0111111111111110 dc.w %0101111111111010 dc.w %0101011111101010 dc.w %0101010110101010 dc.w %0101011111101010 dc.w %0101111111111010 dc.w %0111111111111110 menu:blk.w 500 end Chapter 8. ---------- 8.Advanced Programming. ----------------------- You've learned a lot about machine language programming on the Amiga.What you need yet are a few routines that can be used as programming tools.We'll work on that right now.They'll be easy to use in your own program.The sky's the limit now! 8.1.Supervisor Mode. -------------------- As mentioned in the chapter on the MC68000 processor,there are two operating modes:the User and the Supervisor mode.It is often necessary to move between the two modes.However,this isn't a simple process. The reason you want to do this,is that in User mode,you can't access the Status register.If you write to one of them,an Exception is executed which crashes the program. How can you get in Supervisor mode? No problem.The operating system of the Amiga contains a function in the EXEC library that lets you get into supervisor mode.Its called SuperState and it doesn't need any parameters.You can easily call this program by using the following lines: execbase = 4 ;exec base address superstate =-150 ;turn on function ... move.l execbase,a6 ;exec base address in A6 jsr superstate(a6) ;turn on supervisor mode move.l d0,savesp ;save return value ... savesp:blk.l 1 ;space for sp value You get the value of the Stack Pointer(SP)back in the D0 register. You'll also find it in register A7,but this register is changed regularly.The reason is that in Supervisor mode,the Amiga works with all the Interrupts and with the SP,and there are lots of Interrupts for this computor.We'll talk about interrupts in a bit. After this call,you'll use the user stack instead of the supervisor stack.In this way,you can access the old user stack.You need to make sure that the user stack is large enough since the interrupts must have enough room for their data on the stack. You need to save the value returned in D0,because you'll need this value later.You need to return to user mode sometime.Theres a function for this in the exec library as well.It is called the UserState function.It needs one parameter,the SP value that comes back from the SuperState function. Since you've saved this value in the long word starting at "savesp",you can write the following: userstate =-156 ... move.l execbase,a6 ;exec base address in A6 move.l savesp,d0 ;put old sp in D0 jsr userstate(a6) ;return to user mode Now you are back in the user mode.The user stack point(USP)is the same as before.You can write functions that need to be run from the supervisor mode as subroutines.First you call superstate,save the return value,execute the desired function,call userstate,and end with a RTS command.If the USP was changed,the RTS command would'nt work right,and the computor would jump who knows where and perhaps crash.Here it works though. Now comes the question:how does the operating system get the supervisor mode?Thats not too difficult;it goes like this: The superstate function attempts to access a Status Register.This causes an Exception to occur and a routine is called whose address begins at the long word starting at $20.It is the Exception Vector for Privilege Violation.The routine that it branches to is called in supervisor mode.Then it tests where this exception came from.If the routine finds that the exception comes from the superstate routine whose address it knows,the matter is settled.It just branches to the routine without turning off the user mode.Thats all there is to it. 8.2.Exception Programming. -------------------------- The exceptions described in the processor chapter offer you a lot of oppertunities to control the Amiga's functions.You can use them to specify how errors should be handled and even list a crash program. Here is a list of vectors that are used to jump to the exception routines: Number Address Use with ------------------------------------------------------------------ 2 $008 Bus error 3 $00C Address eror 4 $010 Illegal command 5 $014 Division by zero 6 $018 CHK command 7 $01C TRAPV command 8 $020 Privilege Violation 9 $024 Trace 10 $028 Axxx command emulation 11 $02C Fxxx command emulation $030-$038 Reserved 15 $03C Uninitialized interrupt $040-$05F Reserved 24 $060 Unauthorised interrupt 25-31 $064-$083 Level 1-7 interrupt 32-47 $080-$0BF TRAP commands $0C0-$0FF Reserved 64-255 $100-$3FF User interrupt vector Lets look at the TRAP commands as an example.They aren't used in the Amiga operating system.A TRAP command and a number between zero and fifteen are used to call one of the 16 posible TRAP routines.If the command TRAP #0 is executed,the processor (in supervisor mode)branches to the routine whose address lies at $80 in memory.This routine must end with a RTE(ReTurn from Exception) command. Some operating systems,for example,the ATARI ST's TOS operating systems,are completely callable via these TRAP's.Parameters are put on the stack,and then a TRAP command is executed.The advantage is that you don't have to know any of the operating systems addresses.In the Amiga you must know the addresses(Execbase=4). Lets write your own TRAP routine to demonstrate the use of the TRAP command.You'll need three program sections: 1.The initialization of the TRAP vector. 2.The TRAP routine itself(It must end with RTE). 3.A test routine that calls the TRAP command. Initialization is very short: init: move.l #trap0,$80 ;set vector for TRAP #0 rts Now you need to write the trap0 routine.Lets use the example from the hardware chapter that produced a beep. Lets write this routine using as little effort as possible.Change the RTS to a RTE at the end,erase the line in which the loop counter D0 was loaded for the tone production,and change the loop so that it works with long words.Now you can load the register with an arbitrary value and have the TRAP #0 followed by a peep of arbitrary duration. ;** beep tone production after a TRAP #0 ** ctlw =$dff096 ;DMA control c0thi =$dff0a0 ;HI table address c0tlo =c0thi+2 ;LO table address c0tl =c0thi+4 ;table length c0per =c0thi+6 ;read in rate c0vol =c0thi+8 ;volume trap0: ;* produce a short peep move.l #table,c0thi ;table beginning move #4,c0tl ;table length move #300,c0per ;read in rate move #40,c0vol ;volume move #$8201,ctlw ;start DMA (sound) loop: subq.l #1,d0 ;counter -1 bne loop ;count dwn to zero still: move #1,ctlw ;turn on tone rte ;exception end table: ;sound table dc.b -40,-70,-40,0,40,70,40,0 You need to make sure that "table"is in CHIP RAM($00000-$7FFFF), otherwise the sound chip can't access the data! After entering this,you can test it out using the following routine: test: move.l #$2ffff,d0 ;pass tone length in D0 trap #0 ;carry out exception:peep rts Now assemble both routines and start the initialization routine, init.Nothing happens. Start the second routine,test.A beep that lasts about one second is output. One thing you must keep in mind is that if you change the program and reassemble it,the address of the trap0 routine can change. Before you execute the TRAP command,you must repeat the initializ- ation,so that the computor doesn't jump to the wrong location! Appendices. ----------- Overview of Library Functions. ------------------------------ The following table gives you an overview of the available libraries and their functions.Each sublist of functions is preceded by the name of the library it is found in. These functions are listed with their negative offset in hex and decimal.Their name and their parameters are also specified.The parameter names are in parenthesis behind the function name.The second set of parenthesis includes a list of registers that correspond to the parameter names.If no parameters are needed,we put () to let you know. CLIST.LIBRARY -$001E -30 InitCLPool (cLPool,size) (A0,D0) -$0024 -36 AllocCList (cLPool) (A1) -$002A -42 FreeCList (cList) (A0) -$0030 -48 FlushCList (cList) (A0) -$0036 -54 SizeCList (cList) (A0) -$003C -60 PutCLChar (cList,byte) (A0,D0) -$0042 -66 GetCLChar (cList) (A0) -$0048 -72 UnGetCLChar (cList,byte) (A0,D0) -$004E -78 UpPutCLChar (cList) (A0) -$0054 -84 PutCLWord (cList,word) (A0,D0) -$005A -90 GetCLWord (cList) (A0) -$0060 -96 UnGetCLWord (cList,word) (A0,D0) -$0066 -102 UnPutCLWord (cList) (A0) -$006C -108 PutCLBuf (cList,buffer,length) (A0,A1,D1) -$0072 -114 GetCLBuf (cList,buffer,maxLength) (A0,A1,D1) -$0078 -120 MarkCList (cList,offset) (A0,D0) -$007E -126 IncrCLMark (cList) (A0) -$0084 -132 PeekCLMark (cList) (A0) -$008A -138 SplitCList (cList) (A0) -$0090 -144 CopyCList (cList) (A0) -$0096 -150 SubCList (cList,index,length) (A0,D0.D1) -$009C -156 ConcatCList (sourceCList,destCList) (A0,A1) CONSOLE.LIBRARY -$002A -42 CDInputHandler (events,device) (A0,A1) -$0030 -48 RawKeyConvert (events,buffer,length,keyMap) (A0,A1,D1,A2) DISKFONT.LIBRARY -$001E -30 OpenDiskFont (textAttr) (A0) -$0024 -36 AvailFonts (buffer,bufBytes,flags) (A0,D0,D1) DOS.LIBRARY -$001e -30 Open (name,access mode)(d1,d2) -$0024 -36 Close (file)(d1) -$002a -42 Read (file,buffer,length)(d1,d2,d3) -$0030 -48 Write (file,buffer,length)(d1,d2,d3) -$0036 -54 Input() -$003c -60 Output() -$0042 -66 Seek(file,position,offset)(d1,d2,d3) -$0048 -72 DeleteFile (name)(d1) -$004e -78 Rename(oldname,newname)(d1,d2) -$0054 -84 Lock(name,type)(d1,d2) -$005a -90 UnLock(lock)(d1) -$0060 -96 DupLock(lock)(d1) -$0066 -102 Examine(lock,fileinfoblock)(d1,d2) -$006c -108 ExNext(lock,fileinfoblock)(d1,d2) -$0072 -114 Info(lock,parameterblock)(d1,d2) -$0078 -120 CreateDir(name)(d1) -$007e -126 CurrentDir(lock)(d1) -$0084 -132 IoErr() -$008a -138 CreateProc(name,pri,seglist,stacksize)(d1,d2,d3,d4) -$0090 -144 Exit(returncode)(d1) -$0096 -150 LoadSeg(filename)(d1) -$009c -156 UnLoadSeg(segment)(d1) -$00a2 -162 Getpacket(wait)(d1) -$00a8 -168 Queuepacket(packet)(d1) -$00ae -174 DeviceProc(name)(d1) -$00be -180 SetComment(name,comment)(d1,d2) -$ooba -186 SetProtection(name,mask)(d1,d2) -$00c0 -192 DateStamp(date)(d1) -$00c6 -198 Delay(timeout)(d1) -$00cc -204 WaitForChar(file,timeout)(d1,d2) -$00d2 -210 ParentDir(lock)(d1) -$00d8 -216 IsInteractive(file)(d1) -$00de -222 Execute(string,file,file)(d1,d2,d3) EXEC.LIBRARY -$001e -30 Supervisor() -$0024 -36 ExitIntr() -$002a -42 Schedule() -$0030 -48 Reschedule() -$0036 -54 Switch() -$003c -60 Dispatch() -$0042 -66 Exception() -$0048 -72 InitCode(startclass,version)(d0,d1) -$004e -78 InitStruct(inittable,memory,size)(a1,a2,d0) -$0054 -84 MakeLibrary(funcinit,structinit,libinit,datasize, codesize)(a0,a1,a2,d0,d1) -$005a -90 MakeFunctions(target,functionarray,funcdispbase) (a0,a1,a2) -$0060 -96 FindResident(name)(a1) -$0066 -102 InitResident(resident,seglist)(a1,d1) -$006c -108 Alert(alertnum,parameters)(d7,a5) -$0072 -114 Debug() -$0078 -120 Disable() -$007e -126 Enable() -$0084 -132 Forbid() -$008a -138 Permit() -$0090 -144 SetSR(newsr,mask)(d0,d1) -$0096 -150 SuperState() -$009c -156 UserState(sysstack)(d0) -$00a2 -162 setIntVector(intnumber,interrupt)(d0,d1) -$00a8 -168 AddIntServer(intnumber,interrupt)(d0,d1) -$00ae -174 RemIntServer(intnumber,interrupt)(d0,d1) -$00b4 -180 Cause(interrup)(a1) -$00ba -186 Allocate(freelist,bytesize)(a0,d0) -$00c0 -192 Deallocate(freelist,memoryblock,bytesize)(a0,a1,d0) -$00c6 -198 AllocMem(bytesize,requirements)(d0,d1) -$00cc -204 AlloAbs(bytesize,location)(d0,a1) -$00d2 -210 FreeMem(memoryblock,bytesize)(a1,d0) -$00d8 -216 AvailMem(requirements)(d1) -$00de -222 AllocEntry(entry)(a0) -$00e4 -228 FreeEntry(entry)(a0) -$00ea -234 Insert(list,node,pred)(a0,a1,a2) -$00f0 -240 AddHead(list,node)(a0,a1) -$00f6 -246 AddTail(list,node)(a0,a1) -$00fc -252 Remove(node)(a1) -$0102 -258 RemHead(list)(a0) -$0108 -264 RemTail(list)(a0) -$010e -270 Enqueue(list,node)(a0,a1) -$0114 -276 FindName(list,name)(a0,a1) -$011a -282 AddTask(task,initpc,finalpc)(a1,a2,a3) -$0120 -288 RemTask(task)(a1) -$0126 -294 FindTask(name)(a1) -$012c -300 SetTaskPri(task,prority)(a1,d0) -$0132 -306 SetSignal(newsignals,signelset)(d0,d1) -$0138 -312 SetExcept(newsignals,signalset)(d0,d1) -$013e -318 Wait(signalset)(d0) -$0144 -324 Signal(task,signalset)(a1,d0) -$014a -330 AllocSignal(signalnum)(d0) -$0150 -336 FreeSignal(signalnum)(d0) -$0156 -342 AllocTrap(trapnum)(d0) -$015c -348 FreeTrap(trapnum)(d0) -$0162 -354 AddPort(port)(a1) -$0168 -360 RemPort(port)(a1) -$016e -366 PutMsg(port,message)(a0,a1) -$0174 -372 GetMsg(port)(a0) -$017a -378 ReplyMsg(message)(a1) -$0180 -384 WaitPort(port)(a0) -$0186 -390 FindPort(name)(a1) -$018c -396 AddLibrary(library)(a1) -$0192 -402 RemLibrary(library)(a1) -$0198 -408 OldOpenLibrary(libname)(a1) -$019e -414 CloseLibrary(library)(a1) -$01a4 -420 Setfunction(library,funcoffset,funcentry)(a1,a0,d0) -$01aa -426 SumLibrary(library)(a1) -$01b0 -432 AddDevice(device)(a1) -$01b6 -438 RemDevice(device)(a1) -$01bc -444 OpenDevice(devname,unit,iorequest,flags)(a0,d0,a1 ,d1) -$01c2 -450 CloseDevice(iorequest)(a1) -$01c8 -456 DoIO(iorequest)(a1) -$01ce -462 SendIO(iorequest)(a1) -$01d4 -468 CheckIO(iorequest)(a1) -$01da -474 WaitIO(iorequest)(a1) -$01e0 -480 AbortIO(iorequest)(a1) -$01e6 -486 AddResource(resource)(a1) -$01ec -492 RemResource(resource)(a1) -$01f2 -498 OpenResource(resname,version)(a1,d0) -$01f8 -504 RawIOInit() -$01fe -510 RawMayGetChar() -$0204 -516 RawPutChar(char)(d0) -$020a -522 RawDoFmt()(a0,a1,a2,a3) -$0210 -528 GetCC() -$0216 -534 TypeOfMem(address)(a1) -$021c -540 Procedure(semaport,bidmsg)(a0,a1) -$0222 -546 Vacate(semaport)(a0) -$0228 -552 OpenLibrary(libname,version)(a1,d0) GRAPHICS.LIBRARY -$001e -30 BltBitMap(scrbitmap,scrx,scry,destbitmap,destx, desty,sizex,sizey,minterm,mask,tempa) (a0,d0,d1,a1,d2,d3,d4,d5,d6,d7,a2) -$0024 -36 BltTemplate(source,scrx,scrmod,destrastport,destx, desty,sixex,sizey)(a0,d0,d1,a1,d2,d3,d4,d5) -$002a -42 ClearEOL(rastport)(a1) -$0030 -48 ClearScreen(rastport)(a1) -$0036 -54 TextLength(rastport,string,count)(a1,a0,d0) -$003c -60 Text(rastport,string,count)(a1,a0,d0) -$0042 -66 SetFont(rastportid,textfont)(a1,a0) -$0048 -72 OpenFont(textattr)(a0) -$004e -78 CloseFont(textfont)(a1) -$0054 -84 AskSoftStyle(rastport)(a1) -$005a -90 SetSoftStyle(rastport,style,enable)(a1,d0,d1) -$0060 -96 AddBob(bob,rastport)(a0,a1) -$0066 -102 AddVSprite(vsprite,rastport)(a0,a1) -$006c -108 DoCollision(rastport)(a1) -$0072 -114 DrawGList(rastport,viewport)(a1,a0) -$0078 -120 InitGels(dummyhead,dummytail,gelsinfo)(a0,a1,a2) -$007e -126 InitMasks(vsprite)(a0) -$0084 -132 RemIBob(bob,rastport,viewport)(a0,a1,a2) -$008a -138 RemVSprite(vsprite)(a0) -$0090 -144 SetCollision(type,routine,gelsinfo)(d0,a0,a1) -$0096 -150 SortGList(rastport)(a1) -$009c -156 AddAnimObj(obj,animationkey,rastport)(a0,a1,a2) -$00a2 -162 Animate(animationkey,rastport)(a0,a1) -$00a8 -168 etGBuffers(animationobj,rastport,doublebuffer)(a0, a1,d0) -$00ae -174 InitGMasks(animationobj)(a0) -$00b4 -180 GelsFuncE() -$00ba -186 GelsFuncF() -$00c0 -192 LoadRGB4(viewport,colurs,count)(a0,a1,d0) -$00c6 -198 InitRastPort(rastport)(a1) -$00cc -204 InitVPort(viewport)(a0) -$00d2 -210 MrgCop(view)(a1) -$00D8 -216 MakeVPort (view,viewPort) (A0,A1) -$00DE -222 LoadView (view) (A1) -$00E4 -228 WaitBlit () -$00EA -234 SetRast (rastPort,color) (A1,D0) -$00F0 -240 Move (rastPort,x,y) (A1,D0,D1) -$00F6 -246 Draw (rastPort,x,y) (A1,D0,D1) -$00FC -252 AreaMove (rastPort,x,y) (A1,D0,D1) -$0102 -258 AreaDraw (rastPort,x,y) (A1,D0,D1) -$0108 -264 AreaEnd (rastPort) (A1) -$010E -270 WaitTOF () -$0114 -276 QBlit (blit) (A1) -$011A -282 InitArea (areaInfo,vectorTable,vectorTableSize) (A0,A1,D0) -$0120 -288 SetRGB4 (viewPort,index,r,g,b) (A0,D0,D1,D2,D3) -$0126 -294 QBSBlit (blit) (A1) -$012C -300 BltClear (memory,size,flags) (A1,D0,D1) -$0132 -306 RectFill (rastPort,xl,yl,xu,yu) (A1,D0,D1,D2,D3) -$0138 -312 BltPattern (rastPort,ras,xl,yl,maxX,maxY, fillBytes) (A1,A0,D0,D1,D2,D3,D4) -$013E -318 ReadPixel (rastPort,x,y) (A1,D0,D1) -$0144 -324 WritePixel (rastPort,x,y) (A1,D0,D1) -$014A -330 Flood (rastPort,mode,x,y) (A1,D2,D0,D1) -$0150 -336 PolyDraw (rastPort,count,polyTable) (A1,D0,A0) -$0156 -342 SetAPen (rastPort,pen) (A1,D0) -$015C -348 SetBPen (rastPort,pen) (A1,D0) -$0162 -354 SetDrMd (rastPort,drawMode) (A1,D0) -$0168 -360 InitView (view) (A1) -$016E -366 CBump (copperList) (A1) -$0174 -372 CMove (copperList,destination,data) (A1,D0,D1) -$017A -378 CWait (copperList,x,y) (A1,D0,D10 -$0180 -384 VBeamPos () -$0186 -390 InitBitMap (bitMap,depth,width,height) (A0,D0,D1,D2) -$018C -396 ScrollRaster (rastPort,dX,dY,minx,miny,maxx, maxy) (A1,D0,D1,D2,D3,D4,D5) -$0192 -402 WaitBOVP (viewPort) (A0) -$0198 -408 GetSprite (simpleSprite,num) (A0,D0) -$019E -414 FreeSprite (num) (D0) -$01A4 -420 ChangeSprite (vp,simpleSprite,data) (A0,A1,A2) -$01AA -426 MoveSprite (viewPort,simpleSprite,x,y) (A0,A1,D0,D1) -$01B0 -432 LockLayerRom (layer) (A5) -$01B6 -438 UnlockLayerRom (layer) (A5) -$01BC -444 SyncSBitMap (1) (A0) -$01C2 -450 CopySBitMap (11,12) (A0,A1) -$01C8 -456 OwnBlitter () -$01CE -462 DisownBlitter () -$01D4 -468 InitTmpRas (tmpras,buff,size) (A0,A1,D0) -$01DA -474 AskFont (rastPort,textAttr) (A1,A0) -$01E0 -480 AddFont (textFont) (A1) -$01E6 -486 RemFont (textFont) (A1) -$01EC -492 AllocRaster (width,height) (D0,D1) -$01F2 -498 FreeRaster (planeptr,width,height) (A0,D0,D1) -$01F8 -504 AndRectRegion (rgn,rect) (A0,A1) -$01FE -510 OrRectRegion (rgn,rect) (A0,A1) -$0204 -516 NewRegion () -$020A -522 ** reserved ** -$0210 -528 ClearRegion (rgn) (A0) -$0216 -534 DisposeRegion (rgn) (A0) -$021C -540 FreeVPortCopLists (viewPort) (A0) -$0222 -546 FreeCopList (coplist) (A0) -$0228 -552 ClipBlit (srcrp,srcX,srcY,destrp,destX,destY, sizeX,sizeY,minterm) (A0,D0,D1,A1,D2,D3,D4,D5,D6) -$022E -558 XorRectRegion (rgn,rect) (A0,A1) -$0234 -564 FreeCprList (cprlist) (A0) -$023A -570 GetColorMap (entries) (D0) -$0240 -576 FreeColorMap (colormap) (A0) -$0246 -582 GetRGB4 (colormap,entry) (A0,D0) -$024C -588 ScrollVPort (vp) (A0) -$0252 -594 UCopperListInit (copperlist,num) (A0,D0) -$0258 -600 FreeGBuffers (animationObj,rastPort, doubleBuffer) (A0,A1,D0) -$025E -606 BltBitMapRastPort (srcbm,srcx,srcy,destrp, destX,destY,sizeX,sizeY,minter) (A0,D0,D1,A1,D2,D3,D4,D5,D6) ICON.LIBRARY -$001E -30 GetWBObject (name) (A0) -$0024 -36 PutWBObject (name,object) (A0,A1) -$002A -42 GetIcon (name,icon,freelist) (A0,A1,A2) -$0030 -48 PutIcon (name,icon) (A0,A1) -$0036 -54 FreeFreeList (freelist) (A0) -$003C -60 FreeWBOject (WBOject) (A0) -$0042 -66 AllocWBOject () -$0048 -72 AddFreeList (freelist,mem,size) (A0,A1,A2) -$004E -78 GetDiskObject (name) (A0) -$0054 -84 PutDiskObject (name,diskobj) (A0,A1) -$005A -90 FreeDiskObj (diskobj) (A0) -$0060 -96 FindToolType (toolTypeArray,typeName) (A0.A1) -$0066 -102 MatchToolValue (typeString,value) (A0,A1) -$006C -108 BumbRevision (newname,oldname) (A0,A1) INTUITION.LIBRARY -$001E -30 OpenIntuition () -$0024 -36 Intuition (ievent) (A0) -$002A -42 AddGadget (AddPtr,Gadget,Position) (A0,A1,D0) -$0030 -48 ClearDMRequest (Window) (A0) -$0036 -54 ClearMenuStrip (Window) (A0) -$003C -60 ClearPointer (Window) (A0) -$0042 -66 CloseScreen (Screen) (A0) -$0048 -72 CloseWindow (Window) (A0) -$004E -78 CloseWorkbench () -$0054 -84 CurrentTime (Seconds,Micros) (A0,A1) -$005A -90 DisplayAlert (AlertNumber,String,Height) (D0,A0,D1) -$0060 -96 DiplayBeep (Screen) (A0) -$0066 -102 DoubleClick (sseconds,smicros,cseconds, cmicros) (D0,D1,D2,D3) -$006C -108 DrawBorder (Rport,Border,LeftOffset,TopOffset) (A0,A1,D0,D1) -$0072 -114 DrawImage (RPort,Image,LeftOffset,TopOffset) (A0,A1,D0,D1) -$0078 -120 EndRequest (requester,window) (A0,A1) -$007E -126 GetDefPref (preferences,size) (A0,D0) -$0084 -132 GetPrefs (preferences,size) (A0,D0) -$008A -138 InitRequester (req) (A0) -$0090 -144 ItemAddress (MenuStrip,MenuNumber) (A0,D0) -$0096 -150 ModifyIDCMP (Window,Flags) (A0,D0) -$009C -156 ModifyProp (Gadget,Ptr,Reg,Flags,HPos,VPos, HBody,VBody) (A0,A1,A2,D0,D1,D2,D3,D4) -$00A2 -162 MoveScreen (Screen,dx,dy) (A0,D0,D1) -$00A8 -168 MoveWindow (Window,dx,dy) (A0,D0,D1) -$00AE -174 OffGadget (Gadget,Ptr,Req) (A0,A1,A2) -$00B4 -180 OffMenu (Window,MenuNumber) (A0,D0) -$00BA -186 OnGadget (Gadget,Ptr,Req) (A0,A1,A2) -$00C0 -192 OnMenu (Window,MenuNumber) (A0,D0) -$00C6 -198 OpenScreen (OSArgs) (A0) -$00CC -204 OpenWindow (OWArgs) (A0) -$00D2 -210 OpenWorkBench () -$00D8 -216 PrintIText (rp,itext,left,top) (A0,A1,D0,D1) -$00DE -222 RefreshGadgets (Gadgets,Ptr,Req) (A0,A1,A2) -$00E4 -228 RemoveGadgets (RemPtr,Gadget) (A0,A1) -$00EA -234 ReportMouse (Window,Boolean) (A0,D0) -$00F0 -240 Request (Requester,Window) (A0,A1) -$00F6 -246 ScreenToBack (Screen) (A0) -$00FC -252 SCreenToFront (Screen) (A0) -$0102 -258 SetDMRequest (Window,req) (A0,A1) -$0108 -264 SetMenuStrip (Window,Menu) (A0,A1) -$010E -270 SetPointer (Window,Pointer,Height,Width, XOFFset, YOFFset) (A0,A1,D0,D1,D2,D3) -$0114 -276 SetWindowTitles (Window,windowTitle, screenTitle) (A0,A1,A2) -$011A -282 ShowTitle (Screen,ShowIt) (A0,D0) -$0120 -288 SizeWindow (Windowmdx,dy) (A0,D0,D1) -$0126 -294 ViewAddress () -$012C -300 ViewPortAddress (Window) (A0) -$0132 -306 WindowToBack (Window) (A0) -$0138 -312 WindowToFront (Window) (A0) -$013E -318 WindowLimits (Window,minwidth,minheight, maxwidth, maxheight) (A0,D0,D1,D2,D3) -$0144 -324 SetPrefs (preferences,size,flag) (A0,D0,D1) -$014A -330 IntuiTextLength (itext) (A0) -$0150 -336 WBenchToBack () -$0156 -342 WBenchToFront () -$015C -348 AutoRequest (Window,Body,PText,NText,PFlag, NFlag,W,H) (A0,A1,A2,A3,D0,D1,D2,D3) -$0162 -354 BeginRefresh (Window) (A0) -$0168 -360 BuildSysRequest (Window,Body,PosText,NegText, Flags,W,H) (A0,A1,A2,A3,D0,D1,D2) -$016E -366 EndRefresh (Window,Complete) (A0,D0) -$0174 -372 FreeSysRequest (Window) (A0) -$017A -378 MakeScreen (Screen) (A0) -$0180 -384 RemakeDisplay () -$0186 -390 RethinkDisplay () -$018C -396 AllocRemember (RememberKey,Size,Flags) (A0,D0,D1) -$0192 -402 AlohaWorkBench (wbport) (A0) -$0198 -408 FreeRemember (RememberKey,ReallyForgot) (A0,D0) -$019E -414 LockIBase (dontknow) (D0) -$01A4 -420 UnlockIBase (IBLock) (A0) LAYERS.LIBRARY -$001E -30 InitLayers (li) (A0) -$0024 -36 CreateUpfrontLayer (li,bm,x0,y0,xl,yl,flags, bm2) A0,A1,D0,D1,D2,D3,D4,A2) -$002A -42 CreateBehindLayer (li,bm,x0,y0,xl,yl,flags, bm2) (A0,A1,D0,D1,D2,D3,D3,A2) -$0030 -48 UpfrontLayer (li,layer) (A0,A1) -$0036 -54 BehindLayer (li,layer) (A0,A1) -$003C -60 MoveLayer (li,layer,dx,dy) (A0,A1,D0,D1) -$0042 -66 SizeLayer (li,layer,dx,dy) (A0,A1,D0,D1) -$0048 -72 ScrollLayer (li,layer,dx,dy) (A0,A1,D0,D1) -$004E -78 BeginUpdate (layer) (A0) -$0054 -84 EndUpdate (layer) (A0) -$005A -90 DeleteLayer (li,layer) (A0,A1) -$0060 -96 LockLayer (li,layer) (A0,A1) -$0066 -102 UnlockLayer (li,layer) (A0,A1) -$006C -108 LockLayers (li) (A0) -$0072 -114 UnlockLayers (li) (A0) -$0078 -120 LockLayerInfo (li) (A0) -$007E -126 SwapBitRastPortClipRect (rp,cr) (A0,A1) -$0084 -132 WhichLayer (li,x,y) (A0,D0,D1) -$008A -138 UnlockLayerInfo (li) (A0) -$0090 -144 NewLayerInfo () -$0096 -150 DisposeLayerInfo (li) (A0) -$009C -156 FattenLayerInfo (li) (A0) -$00A2 -162 ThinLayerInfo (li) (A0) -$00A8 -168 MoveLayerInfrontOf (layer_to_move, layer_to_be_in_front_of) (A0,A1) MATHFFP.LIBRARY -$001E -30 SPFix (float) (D0) -$0024 -36 SPFit (integer) (D0) -$002A -42 SPCmp (leftFloat,right,Float) (D1,D0) -$0030 -48 SPTst (float) (D1) -$0036 -54 SPAbs (float) (D0) -$003C -60 SPNeg (float) (D0) -$0042 -66 SPAdd (leftFloat,rightFloat) (D1,D0) -$0048 -72 SPSub (leftFloat,rightFloat) (D1,D0) -$004E -78 SPMul (leftFloat,rightFloat) (D1,D0) -$0054 -84 SPDiv (leftFloat,rightFloat) (D1,D0) MATHIEEEDOUBBAS.LIBRARY -$001E -30 IEEEDPFix (integer,integer) (D0,D1) -$0024 -36 IEEEDPFit (integer) (D0) -$002A -42 IEEEDPCamp (integer,integer,integer,integer) (D0,D1,D2,D3) -$0030 -48 IEEEDPTst (integer,integer) (D0,D1) -$0036 -54 IEEEDPAbs (integer,integer) (D0,D1) -$003C -60 IEEEDPNeg (integer,integer) (D0,D1) -$0042 -66 IEEEDPAdd (integer,integer,integer,integer) (D0,D1,D2,D3) -$0048 -72 IEEEDPSub (integer,integer,integer,integer) (D0,D1,D2,D3) -$004E -78 IEEEDPMul (integer,integer,integer,integer) (D0,D1,D2,D3) -$0054 -84 IEEEDPDiv (integer,integer,integer,integer) (D0,D1,D2,D3) MATHTRANS.LIBRARY -$001E -30 SPAtan (float) (D0) -$0024 -36 SPSin (float) (D0) -$002A -42 SPCos (float) (D0) -$0030 -48 SPTan (float) (D0) -$0036 -54 SPSincos (leftFloat,rightFloat) (D1,D0) -$003C -60 SPSinh (float) (D0) -$0042 -66 SPCosh (float) (D0) -$0048 -72 SPTanh (float) (D0) -$004E -78 SPExp (float) (D0) -$0054 -84 SPLog (float) (D0) -$005A -90 SPPow (leftFloat,rightFloat) (D1,D0) -$0060 -96 SPSqrt (float) (D0) -$0066 -102 SPTieee (float) (D0) -$006C -108 SPFieee (float) (D0) -$0072 -114 SPAsin (float) (D0) -$0078 -120 SPAcos (float) (D0) -$007E -126 SPLog10 (float) (D0) POTGO.LIBRARY -$0006 -6 AllocPotBits (bits) (D0) -$000C -12 FreePotBits (bits) (D0) -$0012 -18 WritePotgo (word,mask) (D0,D1) TIMER.LIBRARY -$002A -42 AddTime (dest,src) (A0,A1) -$0030 -48 SubTime (dest,src) (A0,A1) -$0036 -54 CmpTime (dest,src) (A0,A1) TRANSLATOR.LIBRARY -$001E -30 Translate (inputString,inputLength, outputBuffer,bufferSize) (A0,D0,A1,D1) Abbreviations (symbols) used: label A label or address reg Register an Address register n dn Data register n source source operand dest destination operand address of register #n direct value GENERAL INSTRUCTIONS BCC label Conditional branch, depends on condition. BRA label Unconditional branch (Similar to JMP). BSR label Branch to subprogram. Return address is deposited on the stack, RTS causes return to that address. CHK ,dx Check data register for limits, activate the CHK instruction exception. DBCC reg,label Check condition, decrement on branch. JMP label Jump to address (Similar to BRA). JSR label Jump to a subroutine. Return address is deposited on stack, RTS causes return to that address. NOP No operation. RESET Reset peripherals (Caution!). RTE Return from exception. RTR Return with loading of flags. RTS Return from subroutine (After BSR or JSR). SCC Set a byte to -1 when condition is met. STOP Stop processing (Caution!). TRAP #n Jump to an exception. TRAPV Check overflow flag, then TRAPV exception. ARITHMETIC OPERATIONS WITH WHOLE NUMBERS ADD source,dest Binary addition. ADDA source,an Binary addition to an address register. ADDI #n, Addition with a constant. ADDQ #n, Fast addition of a constant which can be only from 1 to 8. ADDX source,dest Addition with transfer in X flag. CLR Clear an operand. CMP source,dest Comparison of two operands. CMPA ,an Comparison with an address register. CMPI #n, Comparison with a constant. CMPM source,dest Comparison of two memory operands. DIVS source,dest Sign-true division of a 32 bit destination by a 16 bit source operand. The result of the division is stored in the LO word of the destination, the remainder in the HI word. DIVU source,dest Division without regard to sign, similar to DIVS. EXT dn Sign-true expansion to twice original size (width) data unit. MULS source,dest Sign-true multiplication of two words into one word. MULU source,dest Multiplication without regard to sign, similar to MULS. NEG Negation of an operand (twos complement). SUB source,dest Binary subtraction. SUBA ,an Binary subtraction from an address register. SUBI #n, Subtraction of a constant. SUBQ #n, Fast subtraction of a three bit constant. SUBX source,dest Subtraction with transfer in X flag. TST Test operand and set N and Z flag. BINARY CODED DECIMAL NUMBERS ABCD source,dest Addition of two binary coded decimal numbers. NBCD source,dest Negation of a binary coded decimal number (nine complement). SBCD source,dest Subtraction of two binary coded decimal numbers. LOGICAL OPERATIONS AND source,dest Logic AND. ANDI #n, Logic AND with a constant. EOR source,dest Exclusive OR. EORI #n, Exclusive OR with a constant. NOT Inversion of an operand. OR source,dest Logic OR. ORI #n, Logic OR with a constant. TAS Check a byte and set bit 7. SINGLE BIT MANIPULATION BCHG #n, Change bit n(0 is changed to 1 and vice versa). BCLR #n, Clear bit n. BSET #n, Set bit n. BTST #n, Test bit n, result is desplayed in Z flag. SHIFT AND ROTATE OPERANDS NOTE: n indicates a register, # indicates a direct value which specifies the number of shiftings. AS n, Arithmetic shift to the left (*2^n) ASR n, Arithmetic shift to the right (/2^n) LSL n, Logic shift to the left. LSR n, Logic shift to the right. ROL n, Rotation left. ROR n, Rotation right. ROXL n, Rotation left with transfer in X flag. ROXR n, Rotation right with transfer in X flag. MOVE DATA INSTRUCTIONS EXG rn,rn Exchange two register contents (don't confuse with swap!). LEA ,an Load an effective address in address register an. LINK an,#n Build stack range. MOVE source,dest Carry value over from source to destination. MOVE SR, Transfer the status register contents. MOVE ,SR Transfer the status register contents. MOVE USP, Transfer the user stack pointer. MOVE ,USP Transfer the user stack pointer. MOVEA ,an Transfer a value to the address register an. MOVEM regs, Transfer several registers at once. MOVEM ,regs Transfer several registers at once. MOVEP source,dest Transfer data to peripherals. MOVEQ #n,dn Quickly transfer an eight bit constant to the data register dn. PEA Deposit an address on the stack. SWAP dn Swap the halves of the register (the upper 16 bit with the lower). UNLK an Unlink the stack. --=End of Book=-- LSD greetings go to; DEE JAY (well done and thanx!), RAZOR BLADE (Mr Abacus!), RYGAR, SCOOTER, and all docs fans everywhere!