· 9 years ago · Dec 07, 2016, 12:44 PM
1AMIGA MACHINE LANGUAGE
2Typed by DEE JAY
3
4
5
6 Table of Contents.
7 ------------------
8 1. Introduction
9 1.1 Why machine code?
10 1.2 A look into the Amiga's memory
11 1.2.1 RAM,ROM,hardware register
12 1.2.2 Bits,bytes and words
13 1.2.3 Number systems
14 1.3 Inside the Amiga
15 1.3.1 Components and libraries
16 1.3.2 Memory
17 1.3.3 Multi-tasking
18
19 2 The MC68000 processor
20 2.1 Registers
21 2.2 Addressing memory
22 2.3 Operating modes
23 2.3.1 User and supervisor modes
24 2.3.2 Exceptions
25 2.3.3 Interrupts
26 2.3.4 Condition codes
27 2.4 The 68000 Instructions
28
29 3 Working with assemblers
30 3.1 The development assembler
31 3.2 AssemPro
32 3.3 The K-SEKA assembler
33
34 4 Our first programs
35 4.1 Adding tables
36 4.2 Sorting tables
37 4.3 Converting number systems
38 4.3.1 Converting hex to ASCII
39 4.3.2 Converting decimal to ASCII
40 4.3.3 Converting ASCII to hex
41 4.3.4 Converting ASCII to decimal
42
43 5 Hardware registers
44 5.1 Checking for special keys
45 5.2 Timing
46 5.3 Reading the mouse or joystick
47 5.4 Tone production
48 5.5 Hardware registers overview
49
50 6 The Amiga operating system
51 6.1 Load libraries
52 6.2 Calling functions
53 6.3 Program initialization
54 6.3.1 Reserve memory
55 6.3.2 Opening a simple window
56 6.4 Input/output
57 6.4.1 Screen output
58 6.4.2 Keyboard input
59 6.4.3 Printer control
60 6.4.4 Serial I/O
61 6.4.5 Speech output
62 6.5 Disk operations
63 6.5.1 Open files
64 6.5.2 Reading and writing data
65 6.5.3 Erase files
66 6.5.4 Rename files
67 6.5.5 CLI directory
68 6.5.6 Read directory
69 6.5.7 Direct access to disk
70
71 7 Working with Intuition
72 7.1 Open screen
73 7.2 Openwindow
74 7.3 Requesters
75 7.4 Event handling
76 7.5 Menu programming
77 7.6 Text output
78 7.7 Images
79 7.8 Borders
80 7.9 Gadgets
81 7.9.1 Boolean gadgets
82 7.9.2 String gadgets
83 7.9.3 Proportional gadgets
84 7.10 Example program
85
86 8 Advanced programming
87 8.1 Supervisor mode
88 8.2 Exception programming
89
90 Appendix
91 Overview of library functions
92 Overview of the MC68000 Instructions
93
94
95
96
97 CHAPTER 1
98 ---------
99 1.Introduction.
100 --------------
101 Before you tackle machine language,you should take a closer
102 look at several things that are vital to machine language
103 programming.
104
105 1.1.Why Machine Language.
106 ------------------------
107 Machine language is actually the only language the MC68000
108 processor understands.All other languages,such as Basic,Pascal
109 or C,must first be translated(interpreted or compiled) into
110 machine code.This process can take place either when the
111 program is executed(the BASIC interpreter),or before program
112 execution(the Pascal and C compilers).
113 Advantages;
114 The great advantage of machine language over an interpreted
115 and compiled program is machine language programs are faster.
116 With an interpreter like BASIC,each line must first be
117 interpreted before it is executed,which requires a great deal
118 of time.A Pascal or C compiler translates the source into
119 machine language.This translation procedure does not produce
120 programs that are as fast as pure machine language programs.
121 Another advantage machine language has over BASIC is that an
122 interpreter is not needed for the execution of a machine
123 language program.
124 Machine language can access all the capabilities of the
125 computor since it is the language native to the computor.It
126 is possible that machine subroutines are required by a higher
127 level language to access functions that aren't directly
128 accessible by that language.
129
130 1.2.A Look Into The Amiga's Memory.
131 ----------------------------------
132 Before a machine language program can be written,you must
133 know exactly what the program is required to do.You must also
134 be aware of what resources are needed and available to achieve
135 those goals.The most important of these resources is the
136 memory in the Amiga.
137
138 1.2.1.RAM,ROM,Hardware Register.
139 -------------------------------
140 Random Access Memory,referred to as RAM,allows information to
141 be placed in it and then withdrawn at a later time.This memory
142 consists of electronic componants that retain data only while
143 the computor is turned on(or until power failure).
144 So that the computor is able to do something when it is first
145 turned on,such as promting the Workbench or Kickstart disk,a
146 program has to remain in memory when the power is off.A memory
147 type which can retain data in memory without any power being
148 needed.This second memory type is known as ROM.
149 ROM;
150 ROM stands for Read Only Memory,indicating that data can only
151 be read from this memory,not written to it.The Amiga contains
152 a ROM,that loads the Workbench or Kickstart disk into RAM.The
153 first version of the Amiga did not contain the Kickstart in
154 ROM.
155 PROM;
156 One variation of ROM is the PROM,or Programmable Read Only
157 Memory.This special type of ROM can actually be programmed
158 once.Since it cannot be erased once programmed,it isn't
159 encountered very often.More often you will see EPROM's. or
160 Erasable Programmable ROM's.These special chips,which can be
161 erased with ultraviolet light,have a little window on the
162 surface of the chip usually covered with tape.
163 EEROM;
164 Although not available on the consumer market and much more
165 expensive than RAM,the EEROM(Electically Erasable ROM) offers
166 another alternative to programmable ROM.These chips function
167 like RAM,except that information is not lost when the power
168 is turned off.
169 WOM;
170 With the birth of the Amiga,another type of memory,WOM,was
171 created.This particular type of memory is Write Once Memory.
172 The Kickstart disk is read into this memory when the computor
173 is first booted.After this,no more data can be read into that
174 memory.Actually this isn't a completely new component,but
175 simply RAM that is locked once data has been read into it,
176 after which the data can only be read from that memory.
177 Registers;
178 In addition to RAM and these variations of ROM there is another
179 type of memory situated between those two groups.This memory
180 is connected to the processor through a group of peripheral
181 controllers.Thus it is commonly refered to as the Hardware
182 Register,since the computor's hardware is managed by this
183 system.We'll go into greater detail on how to use these hardware
184 registers later in this book.
185 Lets take a closer look at the structure and use of the memory
186 most familiar to us,RAM.
187
188 1.2.2.Bits,Bytes,and Words.
189 --------------------------
190 Kilobyte;
191 The standard size in which memory is measured is a Kilobyte
192 (Kbyte).One kilobyte consists of 1024 bytes,not 1000 as you
193 might expect.This unusual system stems from the computor's
194 binary mode of operation,where numbers are given as powers of
195 2,including kilobytes.
196 To access a memory block of one kilobyte,the processor requires
197 10 connections which carry either one volt or zero volts.Thus
198 2^10=1024 combinations or 1024 bytes of memory,are possible.
199 Byte;
200 A byte,in turn,consists of yes/no,on/off information as well.
201 A byte can be one of 2^8 different values,and thus it can
202 represent any one of 256 numbers.The individual numerical
203 values that make up a byte,which also are the smallest and
204 most basic unit encountered in any computor,are called bits
205 (short for binary coded digit).
206 A 512 kbyte memory,such as the Amiga's,contains 2^19=524288
207 bytes and 4194304 bits.It may seem unimaginable,but a memory
208 of that size has 2^4194300 different combinations.
209 Word;
210 Back to the basics...bits and bytes are sufficent to program
211 an eight bit processor like the 6500,since it can only work
212 with bytes.To program a 16/32 bit processor like the Amiga's
213 MC68000,you'll need to know two new data forms:words,consisting
214 of 16 bits(the equivalent of two bytes),and long words,which
215 are 32 bits(the equivalent of four bytes,or 2 words).
216 A word can be any number between 0 and 65536,a long word can
217 0 to 4294967295.The MC68000 processor can process these
218 gigantic numbers with a single operation.
219 Once in a while you need to use negative numbers as well as
220 positive ones.Since a bit can only be 1 or 0 and not -1,an
221 alternative system has been adopted.If a word is to have a
222 specific sign,the highest value digit or 15th bit in the word
223 (positions are always counted from zero) determines the sign
224 of the word.With this method words can carry values from -32768
225 to +32768.One byte can range from -127 to +127.In a byte,the
226 value -1 is given by $FF; in a word it's $FFFF,-2 is $FE(FFFE),
227 etc.
228 Lets stick with positive values for the time being,to aid in
229 the visualization of a bit in relation to its bit pattern.
230 Machine language does not use the familiar decimal system.
231 Instead,it commonly employs the binary as well as the octal and
232 hexadecimal number systems.
233
234 1.2.3.Number Systems.
235 --------------------
236 Lets take a look at the decimal system:its base number is 10.
237 This means that every digit represents a power of 10.This means
238 that the 246 represents 2*10^2+4*10^1+6*10^0.The decimal system
239 offers a selection of 10 characters,namely 0-9.
240 Binary;
241 This procedure is different for the binary system.The binary
242 system offers only two different characters:1 and 0.Thus the
243 systems base number is two.The decimal value of 1010 would be:
244 1*2^3+0*2^2+1*2^1+0*2^0=2^3+2^1=8+2=10 (in decimal system)
245 Generally binary numbers are identified by having a percentage
246 symbol as a prefix.See if you can determine the decimal value of
247 this number:110010...
248 Well did you get 50?.Thats the right answer.The most simple
249 method to arrive at this result is to simply add up the values
250 of the digits contained at 1.The values of the first eight digits
251 are as follows:
252 digit 8 7 6 5 4 3 2 1
253 value 128 64 32 16 8 4 2 1
254 Octal;
255 The octal system whose base is eight,is similar.The character set
256 consists of numbers 0 to 7.The decimal equivalent of the octal
257 number 31 is: 3*8^1+1*8^0=25.However the octal system isn't
258 nearly as important as the next one...
259 The base number of the hexadecimal system is 16,and its character
260 set ranges from 0 to F.Thus,A would be equivalent of a decimal 10
261 and F would be 15.The dollar sign($) indicates a hexadecimal
262 number.The binary and hexadecimal systems are the most important
263 numerical systems for assembly language programming.
264 Hex;
265 The hexadecimal representation of a byte ranging from 0 to 256
266 always has two digits:$00 to $FF.A word ranges from $0000 to $FFFF
267 and a longword from $00000000 to $FFFFFFFF.
268 Its quite easy to convert binary numbers into hexadecimal:simply
269 split up the binary numbers into groups of four digits.Each of
270 these groups of four digits then corresponds to one hexadecimal
271 digit.Heres an example:
272 binary number %110011101111
273 split up %1100 %1110 %1111
274 result $C $E $F
275 thus: %110011101111=$CEF
276 The opposite operation is just as easy...
277 hexadecimal $E30D
278 split up $E $3 $0 $D
279 result %1110 %0011 %0000 %1101
280 thus: $E30D = %1110001100001101
281 This method can also be used to convert binary into octal and vice
282 versa,except that groups of three digits are used in that case:
283 octal number 7531
284 split up 7 5 3 1
285 result %111 %100 %011 %001
286 thus: octal 7531=%111101011001
287 This binary number can the be converted into hexadecimal,as well:
288 binary number %111101011001
289 split up %1111 %0101 %1001
290 result $F $5 $9
291 thus: octal 7531=$F59
292 The following calculation can then be used to convert the number
293 into the familiar decimal system:
294 hexadecimal $F59
295 split up $F $5 $9
296 result 15*16^2+5*16+9
297 thus: $F59=3929 decimal
298 Although this conversions are quite simple ,they can get to be
299 rather annoying.Many assemblers can ease this task somewhat:they
300 allow you to enter a value with '?'upon which it returns the
301 value in decimal and hexadecimal forms.There are even calculators
302 that perform number base conversions.
303 Often this conversion as to be performed in a program,for instance
304 when a number is entered by the user and then processed by the
305 computor.In this case the number entered,being simply a
306 combination of graphic symbols,is evaluated and the usually
307 converted into a binary number,in effect,a word or a longword.
308 This process is often required in reverse order,as well.If the
309 computor is to display a calculated value in a specific number
310 system,it must first convert that number into a series of
311 characters.In a later chapter you will develop machine language
312 routines to solve these problems.You can then use these routines
313 in your own programs.First you still have to cover some things
314 that are fundamental to machine language programming on the Amiga.
315
316 1.3.Inside the Amiga.
317 --------------------
318 In order to program machine language,it is not sufficent to know
319 only the commands of the particular processor,one must also have
320 extensive knowledge of the Amiga being programmed.Lets take a
321 look inside the Amiga.
322
323 1.3.1.Components and Libraries.
324 ------------------------------
325 The Amiga is a very capable machine,due to the fact that there
326 are components that do a large part of the workload,freeing up
327 the 68000 processor.These are refered to as the"custom"chips,
328 which perform various tasks independantly of the 68000 processor.
329 Custom Chips;
330 This task force is comprised of three chips,whose poetic names
331 are Agnus,Denice,and Paula.The main task of Agnus,alias blitter,
332 is the shifting of memory blocks,which is helpful for operations
333 such as quick screen changes.Denise is responsible for transfering
334 the computors thoughts on to the screen.Paula's tasks consist of
335 input/output jobs,such as disk operation or sound.
336 These chips are accessed by the processor through several adresses
337 starting at $DFF000,which are also known as the hardware registers
338 (you'll find more detailed information about the registers in the
339 corresponding chapter).To simplify the otherwise complicated
340 procedure of utilizing these chips,several programs have been
341 included in the Kickstart and Workbench libraries.These programs
342 can be called by simple routines and then take over the respective
343 chips.
344 If only these library functions are used to program the Amiga,the
345 parameters are the same,regardless of the language used.Only the
346 parameter notations differs from language to language.BASIC is an
347 exception in this respect,since its interpreter translates the
348 program calls,which is why you don't need to know how the Amiga
349 executes these functions in order to use them.
350 The library functions are written in machine language and are thus
351 closely related with your own machine language programs.Actually
352 you could do without the library programs and write all of the
353 functions yourself.However the incredible workload of this task is
354 so discouraging,that you'd rather stick with the library functions
355
356 1.3.2.Memory.
357 ------------
358 First lets look at the RAM of the Amiga 1000.The standard version
359 of this computor has over 512 kbytes of RAM,ranging from the
360 address $00000 to $7FFFF,or 0 to 524287.If the memory is expanded
361 to one megabyte,the first address still starts at $00000,however
362 the start of anything greater than 512k can go anywhere in the
363 address space between $200000 to $9FFFFF.With the release of
364 AmigaDOS 1.2,the Amiga figures out where to put the memory
365 expansion by using a special`Autoconfig`scheme.This allows you to
366 add memory and I/O without worrying about addresses and dip
367 switches.
368 Chip RAM;
369 The chips that support the Amiga`s processor access RAM almost
370 totally independantly and thus ease the workload of the processor.
371 However there is a draw back:these chips can only access the first
372 512k bytes of RAM.Thus graphics and sound data handled by these
373 chips MUST be stored in this memory range.Because of this,that
374 memory range is referred to as `Chip RAM`.
375 Fast RAM;
376 The counterpart to chip RAM is the remaining RAM which,if the
377 computor is equipped with it,begins at $200000.Since only the
378 processor itself as access to this part of memory it is known has
379 `Fast RAM`.
380 Here`s an overview of the Amiga`s memory:
381 $000000-$07FFFF chip RAM
382 $080000-$1FFFFF reserved
383 $200000-$9FFFFF potential fast RAM
384 $A00000-$BEFFFF reserved
385 $BFD000-$BFDF00 PIA B (even addresses)
386 $BFE001-$BFEF00 PIA C (odd addresses)
387 $C00000-$DFEFFF reserved for expansion
388 $DFF000-$DFFFFF custom chip registers
389 $E00000-$E7FFFF reserved
390 $E80000-$EFFFFF expansion ports
391 $F00000-$F7FFFF reserved
392 $F80000-$FFFFFF system ROM
393 Since the Amiga is multi-tasking,when a program is loaded into
394 memory,it is simply loaded into another memory location.The memory
395 range thus occupied is added to a list of occupied memory and the
396 memory range is then considered barred from other uses.If another
397 program is loaded,which is quite possible with the Amiga,it is
398 read into another memory location which is then marked on the
399 occupied list.If the first program should require additional
400 memory,to use a text buffer for example,that memory first has to
401 be reserved.Otherwise another program could accidently be loaded
402 into the memory needed for this task.
403 What`s interesting about this procedure is that when the first
404 loaded has ended,the memory occupied by it is freed for further
405 use.As a result,RAM is then chopped up into occupied and free
406 parts,which are no longer related to each other.The Amiga can
407 still utilize these chunks of memory as if they were one
408 continuous chunk.After all,parts is parts.An example of this is
409 the dynamic RAM disk which is always available under the name RAM:
410 This RAM disk is actually quite a phenomenon,since it is always
411 completely filled.If a program is erased from RAM disk,the memory
412 allocated to that program,regardless of its location or structure,
413 is given back to the system.Thus,if you reserved and filled 100
414 kbytes of memory,it would be quite posible that the 100kbytes
415 actually consists of various pieces of memory independant of one
416 another.You never notice this since the Amiga automatically
417 corrects the difference between apparent and actual memory.
418
419 1.3.3.Multi-Tasking.
420 -------------------
421 The Amiga is truly an amazing machine,being capable of doing
422 several things at one time.A red and white ball might be bouncing
423 around in one window while you`re working on text in another
424 window and watching a clock tick away in a third.
425 At least that`s the impression most people get when they recieve
426 their first Amiga demonstration.However,there is a catch to this:
427 even the Amiga as only one processor,which can really only do one
428 thing at a time.
429 The tricky part is when more than one program is running,each
430 program is executed part by part,and the Amiga is constantly
431 switching from one program back to the other program.In the
432 example above,the ball would first be moved by one pixel,then
433 the processor would check for a text entry and if necessary display
434 it,after which it would move the clock`s second hand.This
435 procedure would be repeated over and over,as the three programs
436 are executed together.The problem is,that the greater the work
437 load on the processor,the slower the things happen.Thus,programs
438 run slower during heavy multi-tasking.
439 Tasks;
440 Each of these jobs that the Amiga has to execute are commonly
441 referred to has tasks...thus,multi-tasking.During multi-tasking,
442 each task is assigned a special time segment during which that
443 particular task is executed.These time segments can be controlled,
444 so that more time consumming programs can be allotted somewhat
445 more processing time.
446 The programmer actually doesn`t need to know how this time slicing
447 works.You can write aprogram without paying any attension to
448 multi-tasking and then run it simultaneously with another program
449 running in the background.The only restriction is that you`ll have
450 to start the program from the CLI with`run`,or from the Workbench.
451 If you execute the program from the CLI by simply typing its name,
452 the processor allots all the time it can get from the CLI to that
453 program,until the execution is complete.Starting the program with
454 run free`s the CLI for other uses while the program is being
455 executed.
456 There is another restriction regarding multi-tasking that applies
457 to assembler programmers.Aside from the use of extra memory,which
458 must first be reserved,the hardware registers should not be
459 directly accessed.Instead the library functions should be used.The
460 reason for this is quite simple:
461 Should you,for instance,specify the printer port as the input line
462 and are reading data in,another task might suddenly think its
463 supposed to be printing.The line would thus be switched to output
464 and data would be written out.After this,your program would try to
465 read more data in,which would not be possible.
466 This is an oversimplified example,but it points out the problem
467 nevertheless.In real programming situations the effects of
468 multiple direct programming of the hardware registers can be much
469 more catastrophic.If your program still needs to access the
470 hardware registers directly(which can have some advantages),then
471 make sure that the program always runs by itself.
472
473
474
475
476 Chapter 2.
477 ---------
478 2.The MC68000 Processor.
479 -----------------------
480 The Amiga`s MC68000 processor is a 16/32 bit processor,which means
481 that while it can process data of 32 bits,it"only"has a 16 bit
482 data bus and a 24 bit address bus.Thus,it can access 2^24=16777216
483 bytes(or 16 Mbytes)of memory directly.
484 7.1 Megaherz;
485 The Amiga 68000 processor,running at 7.1 megaherz,is quite fast,
486 which is required for a computor with a workload as heavy as the
487 Amiga`s.The Amiga also processes a number of custom chips that
488 greatly ease the workload of the processor.These custom chips
489 manage sound in/output,graphics and animation,thus freeing the
490 processor for calculations.
491
492 2.1.Registers.
493 -------------
494 In addition to the standard RAM,the processor contains internal
495 memory called registers.There are eight data registers(D0-D7),
496 eight address registers(A0-A7),a status register(SR),two stack
497 pointers,a user stack pointer,a system stack pointer(USP and SSP)
498 and the program counter(PC).
499 Register Sizes;
500 The data registers,the address registers,and the program counter
501 are all 32 bits,while the status register is 16 bits.These
502 registers are located dirctly in the processor so they are not
503 accessed the same way memory would be accessed.There are special
504 instructions for accessing these registers.
505 Data Registers;
506 The data registers are used for all kinds of data.They can handle
507 operations with bytes(8 bits)words(16 bits)and longwords(32bits).
508 Address Registers;
509 The address registers are used for storing and processing
510 addresses.This way they can be used as pointers to tables,in which
511 case only words and longwords operations are possible.
512 Stack Pointer;
513 The address register A7 plays a special role:this register is
514 utilized as the Stack Pointer(SR)by the processor,and thus is not
515 recommended for normal use by the programmer.Which of the two
516 possible stacks is being pointed to depends on the present mode of
517 the processor,but more about that later.
518 The stack,to whose actual position the stack pointer is pointing,
519 is used to store temporary internal data.The stack works similar
520 to a stack of notes on your desk:the note that was added to the
521 stack last is the first one to come off the stack.This type of
522 stack is known as LIFO(Last in,First out).There is another type of
523 stack,the FIFO(First in,First out)which is not used by the
524 processor itself.
525 How these registers and the SP can be manipulated,or how to work
526 with the stack,is presented in the next chapter.Lets continue with
527 the registers for now.
528 Status Register;
529 The status register plays an important role in machine language
530 programming.This 16-bit quality(word)contains important
531 information about the processor status in 10 of its bits.The word
532 is divided into two bytes,the lower byte(the user byte)and the
533 upper byte(the system byte).The bits that signify that certain
534 conditions are refered to as flags.This means that when a certain
535 condition is present,a particular bit is set.
536 The user byte contains five flags,which have the following meaning
537
538 Bit Name Meaning
539 -----------------------------------------------
540 0 (C,Carry) Carry bit,modified by math
541 calculation,and shift instructions.
542 1 (V,Overflow) Similar to carry,indicates a change
543 of sign,in other words,a carry from
544 bit six to bit seven.
545 2 (Z,Zero) Bit is set when the result of an
546 operation is zero.
547 3 (N,Negative) Is set when the result of an
548 operation is negative.
549 4 (X,Extended) Like carry,is set for arithmetic
550 operations.
551 5-7 Not used.
552
553 The system byte contains five significant bits:
554
555 Bit Nane Meaning
556 -----------------------------------------------
557 8 I0 Interupt mask.Activates interupt
558 9 I1 levels 0 to 7,where 0 is the lowest
559 10 I2 and 7 is the highest priority.
560 11 not used.
561 12 not used.
562 13 (S,Supervisor) This bit indicates the actual
563 pocessor mode(0=User,1=Supervisor
564 mode).
565 14 not used.
566 15 (T,Trace) If this bit is set,the processor is
567 in single step mode.
568
569 Here's an overview of the status word;
570
571 bit : 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
572 name : T - S - - I2 I1 I0 - - - X N Z V C
573
574 Don't let the new terms,like mode and interupt confuse you.We'll
575 talk about these in greater detail in the chapter dealing with the
576 operating conditions of the processor.
577
578 2.2.Addressing Memory.
579 ---------------------
580 In the standard Amiga 500's and 1000's,the processor has over 512k
581 of RAM available.The Amiga 2000 has one mega-byte of RAM that can
582 be accessed by the processor.How does the processor access all
583 this memory?
584 If you're programming in BASIC you don't have to worry about
585 memory management.You can simply enter MARKER%=1,and the value is
586 stored in memory by the BASIC interpreter.
587 In assembler,there are two ways of accomplishing this task:
588 1) Store the value in one of the data or address registers,or
589 2)Write it directly into a memory location.
590 To demonstrate these two methods let's get a little ahead and
591 introduce a machine language instruction,which is probably the
592 most common:MOVE.As its name states,this instruction moves values.
593 Two parameters are required with the instruction:source and
594 destination.
595 Lets see what the example from above would look like if you
596 utilize the MOVE instruction...
597 1) MOVE #1,D0
598 This instruction moves the value 1 into data register D0.As you
599 can see,the source value is always entered before the destination.
600 Thus,the instruction MOVE D0,#1 is not possible.
601 2) MOVE #1,$1000
602 deposits the value 1 in the memory location at $1000.This address
603 was arbitrarily chosen.Usually addresses of this form won't be
604 used at all in assembler programs,since labels that point to a
605 certain address are used instead.Thus,the more common way of
606 writing this would be:
607 ...
608 MOVE #1,MARKER
609
610 ...
611 MARKER:DC.W 1
612
613 These are actually two pieces of program:the first part executes
614 the normal MOVE instruction whose destination is `MARKER`.This
615 label is usually defined at the end of a program and specifies the
616 address at which the value is stored.
617 The paraneter DC.W 1 is a pseudo op,apseudo operation.This means
618 that this isn`t an instruction for the processor,but an
619 instruction for the assembler.The letters DC stand for`DeClare`and
620 the suffix .W indicates that the data is a Word.The other two
621 suffix alternatives would be .B for a byte(8 bits)and .L for a
622 long word(32 bits).
623 This suffix(.B.W or.L)is used with most machine language
624 instructions.If the suffix is omitted,the assembler uses .W(word)
625 as the default parameter.If you wanted a long word,you`d use an
626 instruction that looks something like this:MOVE .L #$1234678,D0
627 where as an instruction like MOVE.B #$12,D0 would be used for a
628 byte of data.However,with this instruction there`s one thing you
629 must be aware of...
630 CAUTION:
631 If the memory is accessed by words or long words,the address must
632 be even(end digit must be 0,2,4,6,8,A,C,E)!
633 Assemblers usually have a pseudo-op,`EVEN`or`ALIGN`,depending on
634 the assembler,that aligns data to an even address.This becomes
635 necessary in situations similar to this:
636 ...
637 VALUE1: DC.B 1
638 VALUE2: DC.W 1
639
640 If the VALUE1 is located at an even address,VALUE2 is automaticaly
641 located at an odd one.If an ALIGN(EVEN)is inserted here,a fill
642 byte(0)is inserted by the assembler,thus making the second address
643 even.
644 ...
645 VALUE1: DC.B 1
646 ALIGN
647 VALUE2: DC.W 1
648
649 Back to the different ways of addressing.The variations listed
650 above are equivalent to the BASIC instruction MARKER%=1 where the
651 % symbol indicates an integer value.
652 Lets go a step further and translate the BASIC instruction MARKER
653 %=VALUE% into assembler.You`ve probably already guessed the answer
654 right?
655
656 MOVE VALUE,MARKER
657 ...
658 ...
659 MARKER: DC.W 1
660 VALUE : DC.W 1
661
662 In this case,the contents in the address at VALUE are moved into
663 the address at MARKER.
664 With the help of these simple examples,you`ve already become
665 familiar with four different ways of addressing,in other words,
666 ways that the processor can access memory.The first is
667 characterized by the number sign(#)and represents a direct value.
668 Thus,this method is also known as direct addressing,and is legal
669 only for the source parameter!
670 A further method in which a direct address(in our case,`MARKER`and
671 `VALUE`)can be specified is known as absolute addressing.This
672 method is legal for the source parameter as well as for the
673 destination parameter.
674 This method can be divided into two different types,between which
675 the programmer usually does'nt notice a difference.Depending on
676 whether the absolute address is smaller or larger than $FFFF,in
677 other words if it requires a long word,it is called absolute
678 addressing(for addresses above $FFFF)or otherwise absolute short
679 addressing.The assembler generally makes the distinction between
680 these two types,and thus,only general knowledge of absolute
681 addressing is required.
682 The fourth method of addressing that you've encountered so far is
683 known as DATA REGISTER DIRECT.It was the first one introduced(MOVE
684 #1,D0)in conjunction with direct addressing,the only difference
685 being that this type accesses a data register(such as D0).
686 These four methods aren't the only ones available to the MC68000
687 processor,in fact there are a total of 12.One other variation
688 called ADDRESS REGISTER DIRECT,is almost identical to data
689 register direct,except that it accesses the address register
690 instead of the data register.Thus,you can use MOVE.L #MARKER,A0 to
691 access the address register A0 directly.
692 You now know five ways to address memory with which quite a bit
693 can be accomplished.Now,lets tackle something more complicated and
694 more interesting.
695 Lets take another example from BASIC:
696
697 10 A=1000
698 20 POKE A,1
699
700 In this example the first line assigns the value 1000 to the
701 variable A.This can be done in assembler as well:MOVE.L #1000,A0.
702 In the assembler version the absolute value of 1000 ia stored in
703 the address register A0.
704 Line 20 doesn't assign a value to the variable A itself,but rather
705 to the memory location at the address stored in A.This is an
706 indirect access,which is quite easy to duplicate in assembler:
707
708 MOVE.L #1000,A0 ;bring address in A0
709 MOVE #1,(A0) ;write 1 into this address
710
711 The parentheses indicates an addressing known as ADDRESS REGISTER
712 INDIRECT.This method only works with address registers,since a
713 'data register indirect' does not exist.
714 There are several variations of this method.For instance,a
715 distance value can be specified,which is added to the address
716 presently located in the address register before the register is
717 actually accessed.The instruction MOVE #1,4(A0),if applied to the
718 example above,writes the value 1 into the memory cell at 1000+4=
719 1004.This distance value can be positive or negative.Thus,values
720 from -32768 to +32768 are accepted.This specific variation of
721 addressing is called ADDRESS REGISTER INDIRECT WITH A 16 BIT
722 DISPLACEMENT value.
723 There is another very similar variation:ADDRESS REGISTER INDIRECT
724 WITH AN 8 BIT INDEX value.While this variation is limited to 8
725 bits,it also brings another register into play.This second
726 register is also a distance value,except that it is a variable as
727 well.
728 We'll try to clarify this with an example.Lets assume that a
729 program includes a data list that is structured like this:
730
731 ...
732 RECORD: DC.W 2 ;number of entries -1
733 DC.W 1,2,3 ;elements of list
734
735 We'll use MOVE.L #RECORD,A0 to load the list into the address
736 register A0.Then you can use MOVE (A0),D0 to pull the number of
737 in the list into the data register.To access the last element of
738 the listonly one instruction is needed.The whole thing looks
739 something like this:
740
741 CLR.L D0 ;erase D0 completely
742 MOVE.L #RECORD,A0 ;address of list in A0
743 MOVE (A0),D0 ;number of elements -1 in D0
744 MOVE 1(A0,D0),D1 ;last element in D1
745 ...
746 RECORD: DC.W 2 ;number of entries -1
747 DC.W 1,2,3 ;elements of list
748
749 This last instruction accesses the byte that is located at 1+A0+D0
750 in other words,the record +1 where the data begins plus the
751 contents of D0(in this case 2).
752 This method of accessing is very useful.It works exquisitely for
753 the processing of tables and lists,as the example demonstrates.If
754 no distance value is needed,simply use a distance value of zero,
755 which some assemblers automatically insert as the default value if
756 for instance only MOVE (A0,D0)is entered.
757 The latter two methods have a third variation,which as its own
758 characteristic trait.It dosen't utilize an address register,but
759 uses the Program Counter(PC)instead.The program counter with
760 displacement method proves useful when a program must function
761 without any changes in all address ranges.The following two
762 statements(in the 15 bit limits)have the same effect:
763
764 MOVE MARKER,D0
765
766 and
767
768 MOVE MARKER(PC),D0
769
770 This method is actually rather imprecise,since the first
771 instruction specifies the actual address of the marker with MARKER
772 while the second line specifies the distance between the
773 instruction and the marker.However since it would be quite
774 cumbersome to constanly calculate the distance,the assembler takes
775 this task off our hands and calculates the actual value automatic.
776 Lets examine the difference between the two instructions.In a
777 program they'll accomplish the same thing,although they are
778 interpreted as two completely different things by the assembler.
779 You'll assume a program being at the address $1000 and the marker
780 is located at $1100.The generated program code looks something
781 like this:
782
783 $001000 30 39 00 00 11 00 MOVE MARKER,D1
784
785 or
786
787 $001000 30 3A 00 FE MOVE MARKER(PC),D1
788
789 As you can see,the generated code of the second line is two bytes
790 shorter than the first line.In addition,if you were to shift this
791 code to the address $2000,the first version still accesses the
792 memory at $1100,while the second line using the PC indirect
793 addressing accesses memory at $2000 correctly.Thus,the program can
794 be transferred to almost any location.
795 This,then,is PROGRAM COUNTER WITH 16 BIT DISPACEMENT value.As we
796 mentioned,there is also PROGRAM COUNTER WITH 8 BIT INDEX value,
797 which permits a second register as a distance value,also known as
798 offset.
799 There are two addressing modes left.These two are based on
800 indirect addressing.They offer the capability of automatically
801 raising or lowering the address register by one when memory is
802 accessed with address register indirect.
803 To automatically increase the register,you'd use ADDRESS REGISTER
804 DIRECT WITH POST-INCREMENT.The address register raises this by the
805 number of bytes used AFTER accessing memory.Thus if you write:
806
807 MOVE.L #1000,A0
808 MOVE.B #1,(A0)+
809
810 the 1 is written in the address $1000 and then A0 is raised by one
811 Instructions like this are very helpful when a memory range is to
812 be filled with a specific value(for instance when the screen is
813 cleared).For such purposes the instruction can be placed in a loop
814 ...which we'll get to later.
815 The counter part to post increment is ADDRESS REGISTER WITH PRE-
816 DECREMENT.In this case the specified address register is lowered
817 by one BEFORE the access to memory.The instructions:
818
819 MOVE.L #1000,A0
820 MOVE.B #1,-(A0)
821
822 writes 1 in the address 999,since the contents of A0 is first
823 decremented and the 1 is written afterwards.
824 These two methods of addressing are used to manage the stack
825 pointer(SP).Since the stack is filled from top to bottom,the
826 following is written to place a word(s.aD0)on the stack:
827
828 MOVE.B D0,-(SP)
829
830 and to remove it from the stack,again in D0:
831
832 MOVE.B (SP)+,D0
833
834 This way the stack pointer always points to the byte last
835 deposited on the stack.Here,again,you'll have to be careful that
836 an access to the stack with a word or a long word is always on an
837 even address.Thus,if you're going to deposit a byte on the stack,
838 either use a whole word or make sure the byte is not followed by a
839 JSR or BSR.The JSR or BSR instructions deposit the addresses from
840 which they stem on the stack in the form of a long word.
841 In the code above,the SP is generally replaced by the address
842 register A7 in the program code,since this register is always used
843 as the SP.Thus,you can write A7 as well as S,the resulting program
844 is the same.However,we recommend the use of SP,since this makes
845 the code somewhat easier to read.After all,quite often you'll want
846 to employ your own stacks,in which case the difference between the
847 processor stack and your own stacks become very important.
848 These are the twelve ways of addressing the MC68000 processor,Here
849 is a summary:
850
851 No Name Format
852 -- ---- ------
853 1 data register direct Dn
854 2 address register direct An
855 3 address register indirect (An)
856 4 address register indirect with post-increment (An)+
857 5 address register indirect with pre-decrement -(An)
858 6 address register indirect with 16 bit displacement d16(An)
859 7 address register indirect with 8 bit index value 8(An,Rn)
860 8 absolute short xxxx.W
861 9 absolute long xxxxxxxx.L
862 10 direct #'data'
863 11 program counter indirect with 16 bit displacement d16(PC)
864 12 program counter indirect with 8 bit index value d8(PC,Rn)
865
866 The abbreviations above have the following meanings:
867
868 An address registers A0-A7
869 Dn data registers D0-D7
870 d16 16 bit value
871 d8 8 bit value
872 Rn register D0-D7,A0-A7
873 'data' up to 32 bit value,(either .B .W .L)
874
875 These are the addressing modes used by the MC68000 processor.The
876 bigger brother of this processor,the 32 bit MC68020,has six more
877 methods which we won't discuss here.
878 Next you're going to see under what conditions the processor can
879 operate.
880
881 2.3.Operating Modes.
882 -------------------
883 In the previous section about registers you encountered the Status
884 Register(SR).The individual bits of this register reflect the
885 present operating condition of the processor.You differentiated
886 between the system byte(bits 8-15)and the user byte(bits 0-7).Now,
887 lets take a closer look at the system byte and its effects upon
888 the operation of the processor.
889
890 2.3.1.User and Supervisor Modes.
891 -------------------------------
892 Isn't it rather strange that the processor classifies you either
893 as a'user'or a 'supervisor'?Both of these operating modes are
894 possible,the user mode being the more common mode.In this mode it
895 is impossible to issue some instructions,and that in your own
896 computor!
897 Don't worry though,you can get around that,as well.The Amiga's
898 operating system contains a function that allows us to switch the
899 processor from one mode to the other.
900 The mode is determined by bit 13 of the Status Register.Usually
901 this bit is cleared(0),indicating that the processor is in user
902 mode.It is possible to write directly into the status register,
903 although this is a privileged instruction that can only be
904 executed from the supervisor mode.Thus,this instructioncould only
905 be used to switch from the supervisor mode into the user mode,by
906 using AND #$DFFF,SR to clear the supervisor bit.However,it is
907 quite preferable to let the operating system perform the switch
908 between these two modes.
909 Now what differentiates these two modes in terms of application?
910 Well,we already mentioned the first difference:some instructions,
911 such as MOVE xx,SR, are privileged and can only be executed from
912 the supervisor mode.An attempt to do this in user mode would
913 result in an exception and interruption of the program.Exceptions
914 are the only way of switching to the supervisor mode,but more
915 about later.
916 A further difference is in the stack range used.Although A7 is
917 still used as the stack pointer,another memory range is used for
918 the stack itself.Thus,the SP is changed rach time you switch from
919 one mode to the other.Because of this you differentiate between
920 the User(USP)and the Supervisor SP(SSP).
921 Accessing memory can also depend on these two modes.During such
922 accessing,the processor sends signals to the peripheral components
923 informing them of the current processor moce.This way a MC68000
924 computor can protect(privilege)certain memory ranges so they can't
925 be accessed by the user.
926 In the supervisor mode it is possible to execute all instructions
927 and access all areas of memory.Because of this,operating systems
928 usually run in the supervisor mode.This is accomplished through
929 the use of Exceptions.
930
931 2.3.2.Exceptions.
932 ----------------
933 Exceptions are similar to interupts on 6500 computors.This allows
934 stopping a program,running a sub-program,and then restarting the
935 stopped program.When an exception occurs the following seps are
936 taken:
937
938 1) The status register is saved.
939 2) The S bit in SR is set(supervisor mode)and the T bit is
940 cleared(no trace).
941 3) The program counter and the user SP are saved.
942 4) The exception vector,which points to the needed exception
943 routine,is retrieved.
944 5) The routine is executed.
945
946 The vectors mentioned,which contain the starting addresses for the
947 various routines,are located at the very beginning of the memory.
948 Here is an overview of the vectors and their respective addresses:
949
950 Number Address Used for
951 ----- ------ --------
952 0 $000 RESET:starting SSP
953 1 $004 RESET:starting PC
954 2 $008 bus error
955 3 $00C address error
956 4 $010 illegal instruction
957 5 $014 division by zero
958 6 $018 CHK instruction
959 7 $01C TRAPV instruction
960 8 $020 privilege violation
961 9 $024 trace
962 10 $028 Axxx-instruction emulation
963 11 $02C Fxxx-instruction emulation
964 $030-$038 reserved
965 15 $03C uninitialed interrupt
966 $040-$05F reserved
967 24 $060 unjustified interrupt
968 25-31 $064-$083 level 1-7 interrupt
969 32-47 $080-$0BF TRAP instructions
970 $0C0-$0FF reserved
971 64-255 $100-$3FF user interrupt vectors
972
973 The individual entries in the table above need detailed
974 explanation.So lets go through them one by one...
975 RESET:staring SSP;
976 At reset,the long word stored at this location is used as the
977 stack pointer for the supervisor mode(SSP).This way you can
978 specify the stack for the RESET routine.
979 RESET:starting PC;
980 Again at reset,the value at this location is used as the program
981 counter.In other words,the RESET routine is started at the address
982 stored here.
983 Bus Error;
984 This exception is activated by a co-processor when,for instance,a
985 reserved or non-existant memory range is accessed.
986 Address Error;
987 This error occurs when a word or long word access is atempted at
988 an odd address.
989 Illegal Instruction;
990 Since all MC68000 instructions consist of one word,a total 65536
991 different instructions are possible.However,since the processor
992 doesn't that many instructions,there are a number of words that
993 are invalid instructions.Should such a word occur,the exception is
994 prompted.
995 Division by Zero;
996 Since the processor has a division function,and the division of
997 anything by zero is mathematically undefined and thus illegal,this
998 exception occurs when such an operation is attempted.
999 CHK Instruction;
1000 This exception only occurs with the CHK instruction.This
1001 instruction tests that a data registers contents are within a
1002 certain limit.If this is not the case,the exception is activated.
1003 TRAPV Instruction;
1004 If the TRAPV instruction is executed and the V bit(bit 1)in the
1005 status word is set,this exception is prompted.
1006 Privilege Violation;
1007 If a privileged instruction is called from the user mode,this
1008 exception is activated.
1009 Trace;
1010 If the trace bit(bit 15)in the status word is set,this exception
1011 is activated after each instruction that is executed.This method
1012 allows you to employ a step by step execution of machine programs.
1013 Axxx-Instruction Emulation;
1014 Fxxx-Instruction Emulation;
1015 These two vectors can be used for a quite interesting trick.If an
1016 instruction beginning with $A or $F(such as $A010 or $F200)is
1017 called the,the routine to which the corresponding vector is
1018 pointing is accessed.In these routines you can create chains of
1019 other instructions,in effect expanding the processors instruction
1020 vocaulary!
1021 Reserved;
1022 These vectors are not used.
1023 Uninitialized Interrupt;
1024 This exception is activated when a peripheral component that was
1025 not initialized sends an interrupt.
1026 Unassigned Interrupt;
1027 Is activated when a BUS error occurs during the interrupt
1028 verification of the activating component.However,the interrupt is
1029 usually only by some type of disturbance.
1030 Level 1-7 Interrupt;
1031 These seven vectors point to the interrupt routines of the
1032 corresponding priority levels.If the level indicated in the status
1033 word is higher than the level of the occuring interrupt,the
1034 interrupt is simply ignored.
1035 TRAP Instructions;
1036 These 16 vectors are used when a corresponding TRAP instruction
1037 occurs.Thus,TRAP instructions from TRAP #0 to TRAP #15 are
1038 possible.
1039 User Interrupt Vectors;
1040 These vectors are used for interrupts which are activated by
1041 several peripheral components that generate their own vector
1042 number.
1043
1044 At this point you don't want to delve any deeper into the secrets
1045 of exceptions,since we'd be expanding this book beyond its frame
1046 work.However,there's one last thing to say about exceptions:the
1047 exception routines are ended with the RTE(ReTurn from Exception)
1048 instruction,with which the original status is restored and the
1049 user program is continued.
1050
1051 2.3.3.Interrupts.
1052 ----------------
1053 Interrupts are processed similarly to exceptions.They are breaks
1054 (or interruptions)in the program which are activated through
1055 hardware(such as a peripherical component or an external trigger).
1056 The interrupt level is stored in bits 8-10 of the status register.
1057 A value between 0 and 7 indicates the interrupt level.There are
1058 eight possible interrupts,each of which as a different priority.If
1059 the level of this interrupt happens to be higher than the value in
1060 the status register,the interrupt is executed,or else ignored.
1061 When a valid interrupt occurs,the computor branches to the
1062 corresponding routine whose address is indicated in the exception
1063 vector table above.
1064 The interrupts are very important if you're trying to synchronize
1065 a program with connected hardware.In this manner,a trigger(s.a the
1066 keyboard)which is to feed the computor data,can signal the request
1067 for a legal value using an interrupt.The interrupt routine then
1068 simply takes the value directly.This method is also employed for
1069 the operation of the serial interface(RS232).
1070 We'll talk about the use of interrupts at a later time.The last
1071 thing we want to mention about interrupts at this time is that,
1072 like exceptions,interrupt routines are terminated with the RTE
1073 instruction.
1074
1075 2.3.4.Condition Codes.
1076 ---------------------
1077 When you write a program in any language,the need for a
1078 conditional operation arises quite often.For instance,in a BASIC
1079 program
1080
1081 IF D1=2 THEN D2=0
1082
1083 represents a conditional operation.To write the equivalent in
1084 machine language,you first need to make the comparison:
1085
1086 CMP #2,D1
1087
1088 CMP stands for compare and compares two operands,in this case D1
1089 and D2.How is this operation evaluated?
1090 For this purpose you have condition codes(CC's),which exist in the
1091 branch instructions of machine language.Because of this,you must
1092 specify when and where the program is to branch.
1093 The simplest variation of the branch instruction is an
1094 unconditional branch.The corresponding instruction is 'BRA address
1095 ',although this won't help you here.After all,you need a
1096 conditional branch.
1097 To retain the result of the operation,in this case a comparrison
1098 (CMP),several bits are reserved in the status word.Lets look at
1099 bit 2 first,which is the zero flag.This flag is set when the
1100 result of the previous operation was zero.
1101 To explain the relationship between CMP and the Z flag,you must
1102 first clarify the function of the CMP instruction.Actually this
1103 instruction performs the subtraction of the source operand from
1104 the destination operand.In the example above,the number 2 is
1105 subtracted from the content of the memory cell at D1.Before the
1106 result of this subtraction is discarded,the corresponding flags
1107 are set.
1108 If the contents of D1 in our example above happened to be 2,the
1109 result of the subtraction would be 0.Thus,the Z flag would be set,
1110 which can then be evaluated through a corresponding branch
1111 instruction.Our example would then look like this:
1112
1113 ...
1114 CMP #2,D1 ;comparison,or subtraction
1115 BNE UNEQUAL ;branch,if not equal(Z flag not set)
1116 MOVE #0,D2 ;otherwise execute D2=0
1117
1118 UNEQUAL:
1119
1120 ... ;program branches to here
1121
1122 BNE stands for Branch if Not Equal.This means,that if the Z flag
1123 was cleared(=0)by the previous CMP,the program branches to the
1124 address specified by BNE(here represented by UNEQUAL).The counter
1125 part to the BNE instruction is the BEQ(Branch if EQual)instruction
1126 which is executed if Z=1.
1127 Here's a list of condition codes,which allow you to form
1128 conditional branches using the Bcc(cc=condition code)format:
1129
1130 cc Condition Bits
1131 ---------------------------------------------------
1132 T true,corresponds to BRA
1133 F false,never branches
1134 HI higher than C'* Z'
1135 LS lower or same C + Z
1136 CC,HS carry clear,higher or same C'
1137 CS,LO carry set,lower C
1138 NE not equal Z'
1139 EQ equal Z
1140 VC overflow clear V'
1141 VS overflow set V
1142 PL plus,positive
1143 MI minus,negative
1144 GE greater or equal N*V+N'*V'
1145 LT less than N*V'+N'*V
1146 GT greater than N*V*Z'+N'*V'*Z'
1147 LE less or equal Z + N*V' + N'*V
1148
1149 *=logic AND, +=logic OR, '=logic NOT
1150
1151 Here are a few examples to demonstrate how these numerous
1152 conditions can be utilized:
1153
1154 CMP #2,D1
1155 BLS SMALLER_EQUAL
1156
1157 This branches if the contents of D1<=2,whether D1 is 0,1 or 2.In
1158 this example,the BLE instruction would allow the program to branch
1159 even if D1 is negative.You can tell this by the fact that the V
1160 bit is used in the evaluation of this expression(see chart above).
1161 When the sign is changed during the operation,this V bit is
1162 compared with the N bit.Should both bits be cleared(N bit=0 and V
1163 bit=0)after the CMP subtraction(D1-2),the result has remained
1164 positive:the condition as not been met.
1165 The conditions EQ and NE are quite important for other uses,as
1166 well.For instance,they can be used to determine if particular bits
1167 in a data word are set,by writing the following sequence...
1168
1169 ...
1170 AND #%00001111,D1 ;masks bits out
1171 BEQ SMALLER ;branches when none of the four
1172 ; ;lower bits is set
1173 CMP #%00001111,D1
1174 BEQ ALL ;branches when all four bits set
1175
1176 The AND instruction causes all bits of D1 to be compared with the
1177 bits of the parameter(in this case #%00001111).If the same bits
1178 are set in both bytes,the corresponding bits are also set in the
1179 result.If one bit of the pair is cleared,the resulting bit is zero
1180 as well.Thus,in the result,the only bits that are set are those
1181 bits of the lowest four that were set in D1.
1182 The technique is known as masking.In the example above,only the
1183 lowest four bits were masked out,which meansthat in the resulting
1184 byte,only the lowest four appear in their original condition.All
1185 other bits are cleared with the AND operand.Of course you can use
1186 any bit combination with this method.
1187 If no bit at all is set in the result,the zeroflag is set,thus
1188 fullfilling the BEQ condition and branching the program.Otherwise,
1189 the next instruction is processed,in which D1 is compared with
1190 %00001111.When both are equal,at leastall of the four lowest bits
1191 of the original byte have been set,in which case the following BEQ
1192 instruction branches.
1193 Aside from CMP,the CC and CS conditions can also be used to
1194 determine whether a HI bit was pushed out of the data word during
1195 data rotation with the ROL and ROR instructions.
1196 Before you move on the instruction vocabulary of the MC68000,we'd
1197 like to give you another tip:
1198 The AssemPro assembler makes it quite easy to try every command in
1199 posible situations.Take the CMP command which we've been talking
1200 about,for example.To test this command with various values and to
1201 receive the results of the comparisons directly via the flags,try
1202 the following.
1203 Type the following into the Editor.
1204
1205 run:
1206 cmp $10,d1
1207 bra run
1208 end
1209
1210 Assemble it,save the resulting code and enter the debugger.After
1211 reloading the code you can then single step through the program
1212 observing the results the program has on the flags.Try changing
1213 the values in the register D1 and see how higher and lower values
1214 affect the flag.
1215 By the way,using the start command at this time causes it to run
1216 forever.Well,at least until reset is hit,which isn't exactly
1217 desirable,either...
1218 This procedure isn't limited to just the CMP instruction.You can
1219 use it to try any other instructions you're interested in.
1220
1221 2.4.The 68000 Instructions.
1222 --------------------------
1223 Its about time to explain the MC68000 instructions.You don't have
1224 room for an in-depth discussion of each instruction in this book;
1225 for that purpose we recommend PROGRAMMING THE 68000 from Sybex by
1226 Steve Williams.
1227 The following tables show the required parameters and arguments
1228 for each instruction.AssemPro have access to built in help tables
1229 covering effective addressing modes and many of the Amiga
1230 Intuition calls.The following notation is used for arguments:
1231
1232 Label a label or address
1233 Reg register
1234 An address register n
1235 Dn data register n
1236 Source source operand
1237 Dest destination operand
1238 <ea> address or register
1239 #n direct value
1240
1241 Here is a short list of the instructions for the MC68000 processor
1242 AssemPro owners can simply place the cursor at the beginning of
1243 the instruction and press the help key to see the addressing modes
1244 allowed:
1245
1246 Mnemonic Meaning
1247 ---------------------------------------------------
1248 Bcc Label conditional branch,depends on condition
1249 BRA Label unconditional branch(similar to JMP)
1250 BSR Label branch to subprogram.Return address is
1251 deposited on stack,RTS causes return to that
1252 address.
1253 CHK <ea>,Dx check data register for limits,activate the
1254 CHK instruction exception.
1255 DBcc Reg,Label check condition,decrement and branch
1256 JMP Label jump to address(similar to BRA)
1257 JSR Label jump to subroutine.Return address is
1258 deposited on stack,RTS causes return to that
1259 address.
1260 NOP no operation
1261 RESET reset peripherals(caution!)
1262 RTE return from exception
1263 RTR return with loading of flags
1264 RTS return from subroutine(after BSR and JSR)
1265 Scc <ea> set a byte to -1 when condition is met
1266 STOP stop processing(caution!)
1267 TRAP #n jump to an exception
1268 TRAPV check overflow flag,the TRAPV exception
1269
1270 Here are a few important notes...
1271 When a program jumps(JSR)or branches(BSR)to subroutine,the return
1272 address to which the program is to return is placed on the stack.
1273 At the RTS instruction,the address is pulled back off the stack,
1274 and the program jumps to that point.
1275 Lets experiment a little with this procedure.Please enter the
1276 following short program:
1277
1278 run:
1279 pea subprogram ;address on the stack
1280 jsr subprogram ;subprogram called
1281 move.l (sp)+,d1 ;get a long word from stack
1282 ; illegal ;for assemblers without
1283 ;debuggers
1284
1285 subprogram:
1286 move.l (sp),d0 ;return address in D0
1287 rts ;and return
1288 end
1289
1290 The first instruction,PEA,places the address of the subprogram on
1291 the stack.Next,the JSR instruction jumps to the subprogram.The
1292 return address,or the address at which the main program is to
1293 continue after the completion of the subprogram,is also deposited
1294 on the stack at this point.
1295 In the subprogram,the long word pointed to by the stack pointer is
1296 now loaded into the data register D0.After that,the RTS
1297 instruction pulls the return address from the stack,and the
1298 program jumps to that address.
1299 Back in the main program,the long word which is on the top of the
1300 stack,is pulled from the stack and written in D1.Assemblers that
1301 do not have the debugging features of AssemPro may need the
1302 ILLEGAL instruction so they can break the program and allow you to
1303 view the register contents.
1304 Assemble the program and load the resulting code into the debugger
1305 Single step thru the program and examine the register contents.
1306 Here you can see that D0 contains the address at which the program
1307 is to continue after the RTS command.Also,D1 contains the address
1308 of the subprogram which you can verify by comparing the debugger
1309 listing.
1310 The STOP and RESET instructions are so powerful that they can only
1311 be used in supervisor mode.Even if you do switch to the supervisor
1312 mode,you should NOT use these instructions if there is any data in
1313 memory that has not been saved and you wish to retain.
1314 The TRAP instruction receives a number between 0 and $F,which
1315 determines the particular TRAP vector(addresses $0080-$00BF)and
1316 thus the corresponding exception routine.Several operating systems
1317 for the 68000 utilize this instruction to call operating system
1318 functions.You'll deal more with this instruction later.
1319 In the short sample program that compared two numbers,the CMP
1320 instruction performed an arithmetic function,namely a subtraction.
1321 This subtraction could be performed with an actual result as well
1322 using the SUB instruction.The counterpart to this is in addition,
1323 for which the ADD instruction is used.In 8 bit processors,like the
1324 6502,these arithmetic functions are the only mathematical
1325 operations.The MC68000 can also multiply,divide,and perform these
1326 operations with a variety of data sizes.
1327 Most of the functions require two parameters.For instance the ADD
1328 instruction...
1329
1330 ADD source,destination
1331
1332 where source and destination can be registers or memory addresses.
1333 Source can also be a direct value(#n).The result of the opoeration
1334 is placed in the destination register or the destination address.
1335 This is same for all operation of this type.These instructions can
1336 be tried out with the AssemPro assembler.In this case we recommend
1337 the use of a register as the destination.
1338 Heres an overview of the arithmetic operations with whole numbers:
1339
1340 Mnemonic Meaning
1341 --------------------------------------------------------------
1342 ADD source,dest binary addition
1343 ADDA source,An binary addition to a address register
1344 ADDI #n,<ea> addition with a constant
1345 ADDQ #n,<ea> fast addition of a constant which can
1346 be only from 1-8
1347 ADDX source,dest addition with transfer in X flag
1348 CLR <ea> clear an operand
1349 CMP source,dest comparison of two operands
1350 CMPA <ea>,An comparison with an address register
1351 CMPI #n,<ea> comparison with a constant
1352 CMPM source,dest comparison of two memory operands
1353 DIVS source,dest sign-true division of a 32 bit
1354 destination by a 16 bit source operand.
1355 The result of the division is stored in
1356 the LO word of the destination,the
1357 remainder in the HI word.
1358 DIVU source,dest division without regard to sign,similar
1359 to DIVS
1360 EXT Dn sign-true expansion to twice original
1361 size(width)data unit
1362 MULS source,dest sign-true multiplication of two words
1363 into one long word
1364 MULU source,dest multiplication without regard to sign,
1365 similar to MULS
1366 NEG <ea> negation of an operand(twos complement)
1367 NEGX <ea> negation of an operand with transfer
1368 SUB source,dest binary subtraction
1369 SUBA <ea>,An binary subtraction from an address
1370 register
1371 SUBI #n,<ea> subtraction of a constant
1372 SUBQ #n,<ea> fast subtraction of a 3 bit constant
1373 SUBX source,dest subtraction with transfer in X flag
1374 TST <ea> test an operand and set N and Z flag
1375
1376 For the processing of whole numbers,the processor can operate with
1377 BCD numbers.These are Binary Coded Decimal numbers,which means
1378 that the processor is working with decimals.In this method,each
1379 halfbyte contains only numbers from 0 to 9,so that these numbers
1380 can be easily processed.For this method,the following instructions
1381 are available:
1382
1383 Mnemonic Meaning
1384 -----------------------------------------------------------------
1385 ABCD source,dest addition of two BCD numbers
1386 NBCD source,dest negation of a BCD number(nine
1387 complement)
1388 SBCD source,dest subtraction of two BCD numbers
1389
1390 Again,we recommend that you try this out yourself.Although
1391 handling the BCD numbers is relatively easy,it can be rather
1392 awkward at first.Be sure that you enter only BCD numbers for
1393 source and destination,since the results are not correct
1394 otherwise.
1395 Next are the logical operations,which you might know from BASIC.
1396 With these functions,you can operate on binary numbers bit for
1397 bit.
1398
1399 Mnemonic Meaning
1400 -----------------------------------------------------------------
1401 AND source,dest logic AND
1402 ANDI #n,<ea> logic AND with a constant
1403 EOR source,dest exclusive OR
1404 EORI #n,<ea> exclusive OR with a constant
1405 NOT <ea> inversion of an operand
1406 OR source,dest logic OR
1407 ORI #n,<ea> logic OR wuth a constant
1408 TAS <ea> check a byte and set bit 7
1409
1410 Single bits can also be manipulated by the following set of
1411 instructions:
1412
1413 Mnemonic Meaning
1414 ----------------------------------------------------------------
1415 BCHG #n,<ea> change bit n(0 is changed to 1 and vice
1416 versa)
1417 BCLR #n,<ea> clear bit n
1418 BSET #n,<ea> set bit n
1419 BTST #n,<ea> test bit n,result is displayed in Z
1420 flag
1421
1422 These instructions are particularly important from the
1423 manipulation and evaluation of data from peripherals.After all,in
1424 this type of data,single bits are often very significant.You'll
1425 come across this more in later chapters.
1426 The processor can also shift and rotate an operand within itself
1427 ('n'indicates a register,'#'indicates a direct value which
1428 specifies the number of shiftings)...
1429
1430 Mnemonic Meaning
1431 ----------------------------------------------------------------
1432 AS n,<ea> arithmetic shift to the left(*2^n)
1433 ASR n,<ea> arithmetic shift to the right(/2^n)
1434 LSL n,<ea> logic shift to the left
1435 LSR n,<ea> logic shift to the right
1436 ROL n,<ea> rotation left
1437 ROR n,<ea> rotation right
1438 ROXL n,<ea> rotation left with transfer in X flag
1439 ROXR n,<ea> rotation right with transfer in X flag
1440
1441 All these instructions allow you to shift a byte,a word or a long
1442 word to the left or right.Its not too surprising that this is the
1443 equivalentof multipling(dividing)the number by a power of 2.Here's
1444 a little example to demonstrate why
1445 Lets take a byte containing the value 16 as an example.In binary,
1446 it looks like this:
1447
1448 %00010000 =16
1449
1450 Now,if you shift the byte to the left by inserting a 0 at the
1451 right,you'll get the following result...
1452
1453 %00010000 shifted to the left equals
1454 %00100000 =32,in effect 16*2
1455
1456 Repeated shifting results in repeated doubling of the number.Thus
1457 if you shift the number n times,the number is multiplied by 2^n.
1458 The same goes for shifting to the right.However,this operation as
1459 a slight quirk:here's a sample byte with the value 5:
1460
1461 %00000101 =5,shifted once to the right equals
1462 %00000010 =2
1463
1464 The answer in this case is not 2.5 as you might expect.The result
1465 such a division is always a whole number,since any decimal places
1466 are discarded.If you use the DIV instruction instead of shifting,
1467 you'll retain the digits to the right of the decimal point.However
1468 shifting is somewhat faster,and shifting can also receive long
1469 words as results.
1470 After explaining the principle of shifting,you still need to know
1471 why more than two instructions are required for the procedure.Well
1472 this is because there are several different types of shifting.
1473 First,you must differentiate between shifting and rotating.In
1474 shifting,the bit that is added to the left or the right side is
1475 always a zero.In rotating,it is always a specific value that is
1476 inserted.This means that with the ROR or the ROL instructions,the
1477 bit that is taken out on one side is the one that is inserted on
1478 the other.With the ROXR and the ROXL instructions this bit takes a
1479 slight detour to the X flag.Thus,the content of the flag is
1480 inserted into the new bit,while the old bit is loaded into the
1481 flag.
1482 Shifting as well,has two variations:arithmetic and logical
1483 shifting.You've already dealt with logical shifting.In this
1484 variation,the inserted bit is always a zero,and the extracted bit
1485 is deposited in the C flag and in the X flag.
1486 Although the highest bit,which always represents the sign,is
1487 shifted in arithmetic shifting,the sign is still retained by ASR.
1488 This has the advantage that when these instructions are used for
1489 division,the operation retains the correct sign(-10/2 equals-5).
1490 However,should an overflow or underflow cause the sign to change,
1491 this change is noted in the V flag,which always indicates a change
1492 in sign.With logical shifting this flag is always cleared.
1493 Now to the instructions that allow you to move data.These are
1494 actually the most important instructions for any processor,for how
1495 else could you process data?
1496
1497 Mnemonic Meaning
1498 ------------------------------------------------------------------
1499 EXG Rn,Rn exchange of two register contents(don't
1500 confuse with swap)
1501 LEA <ea>,An load an effective address in address
1502 register An
1503 LINK An,#n build stack range
1504 MOVE source,dest carry value over from source to dest
1505 MOVE SR,<ea> transfer the status register contents
1506 MOVE <ea>,SR transfer the status register contents
1507 MOVE <ea>,CCR load flags
1508 MOVE USP,<ea> transfer the user stack point
1509 MOVE <ea>,USP transfer the user stack point
1510 MOVEA <ea>,An transfer a value to the address
1511 register An
1512 MOVEM Regs,<ea> transfer several registers at once
1513 MOVEM <ea>,Regs transfer several registers at once
1514 MOVEP source,dest transfer data to peripherals
1515 MOVEQ #n,Dn quickly transfer a 8 bit constant to
1516 the data register Dn
1517 PEA <ea> deposit an address on the stack
1518 SWAP Dn swap the halves of the register(the
1519 upper 16 bits with the lower)
1520 UNLK An unlink the stack
1521
1522 The LEA or PEA instructions are often used to deposit addresses in
1523 an address register or on the stack.The instruction
1524
1525 LEA label,A0
1526
1527 loads the address of the label'label' into the address register
1528 A0.In practice,this corresponds to
1529
1530 MOVE.L #label,A0
1531
1532 which is equivalent to
1533
1534 PEA label
1535
1536 All these instructions deposit the address of 'label' on the stack
1537 The following instruction also does this:
1538
1539 MOVE.L #label,-(SP)
1540
1541 The LEA instruction becomes much more interesting when the label
1542 is replaced by indirect addressing.Here's an example:
1543
1544 LEA 1(A0,D0),A1
1545
1546 The address that's produced by the addition of 1(direct value
1547 offset)+A0+D0 is located in A1.To duplicate this instruction with
1548 MOVE would be quite cumbersome.Take a look:
1549
1550 MOVE.L A0,A1
1551 ADD.L D0,A1
1552 ADDQ.L #1,A1
1553
1554 As you can see,the LEA instruction offers you quite some
1555 interesting possibilities.
1556 Those are all the instructions of the MC68000.Through their
1557 combination using the diverse methods of addressing,you can create
1558 a great number of different instructions,in order to make a
1559 program as efficent as possible.
1560 The following table is an overview of all MC68000 instructions
1561 along with their possible addressing types and the influence of
1562 flags.The following abbreviations are used:
1563
1564 x=legal s=source only d=destination only
1565 -=not effected 0=cleared *=modified accordingly
1566 1=set u=undermined P=privileged
1567
1568 Mnemonic 1 2 3 4 5 6 7 8 9 10 11 12 X N Z V C P
1569 -----------------------------------------------------------------
1570 ABCD x
1571 ADD s s x x x x x x x s s s * * * * *
1572 ADDA x x x x x x x x x x x x - - - - -
1573 ADDI x x x x x x x x * * * * *
1574 ADDQ x x x x x x x x x * * * * *
1575 ADDX x x * * * * *
1576 AND s x x x x x x x s s s - * * 0 0
1577 ANDI x x x x x x x x - * * 0 0
1578 ASL, ASR x x x x x x x x * * * * *
1579 Bcc - - - - -
1580 BCHG x x x x x x x x - - * - -
1581 BCLR x x x x x x x x - - * - -
1582 BRA - - - - -
1583 BSET x x x x x x x x - - * - -
1584 BSR - - - - -
1585 BTST x x x x x x x x z x x - - * - -
1586 CHK x x x x x x x x x x x - * u u u
1587 CLR x x x x x x x x - 0 1 0 0
1588 CMP x x x x x x x x x x x x - * * * *
1589 CMPA x x x x x x x x x x x x - * * * *
1590 CMPI x x x x x x x x - * * * *
1591 CMPM x x x x x x x - * * *
1592 cpGEN - - - - -
1593 DBcc - - - - -
1594 DIVS x x x x x x x x x x x - * * * 0
1595 DIVU x x x x x x x x x x x - * * * 0
1596 EOR x x x x x x x x - * * 0 0
1597 EORI x x x x x x x x - * * 0 0
1598 EORI CCR * * * * *
1599 EORI SR * * * * *
1600 EXG - - - - -
1601 EXT - * * 0 0
1602 EXTB - * * 0 0
1603 ILLEGAL - - - - -
1604 JMP x x x x x x x - - - - -
1605 JSR x x x x x x x - - - - -
1606 LEA x x x x x x x - - - - -
1607 LINK x - - - - -
1608 LSL, LSR x x x x x x x * * * 0 *
1609 MOVE x s x x x x x x x s s s - * * 0 0
1610 MOVEA x x x x x x x x x x x x - - - - -
1611 MOVE to CCR x x x x x x x x x x x * * * * *
1612 MOVE from SR x x x x x x x x - - - - - P
1613 MOVE to SR x x x x x x x x x x x * * * * * P
1614 MOVE USP x - - - - - P
1615 MOVEM x s d x x x x s s - - - - -
1616 MOVEP s d - - - - -
1617 MOVEQ d - * * 0 0
1618 MULS x x x x x x x x x x x - * * 0 0
1619 MULU x x x x x x x x x x x - * * 0 0
1620 NBCD x x x x x x x x * u * u *
1621 NEG x x x x x x x x * * * * *
1622 NEGX x x x x x x x x * * * * *
1623 NOP - - - - -
1624 NOT x x x x x x x x - * * 0 0
1625 OR s x x x x x x x s s s - * * 0 0
1626 ORI x x x x x x x x - * * 0 0
1627 PEA x x x x x x x - - - - -
1628 RESET - - - - - P
1629 ROL, ROR x x x x x x x - * * 0 *
1630 ROXL, ROXR x x x x x x x - * * 0 *
1631 RTE - - - - - P
1632 RTR * * * * *
1633 RTS - - - - -
1634 SBCD x x * u * u *
1635 Scc x x x x x x x x - - - - -
1636 STOP x - - - - -
1637 SUB s s x x x x x x x s s s * * * * *
1638 SUBA x x x x x x x x x x x x - - - - -
1639 SUBI x x x x x x x x * * * * *
1640 SUBQ x x x x x x x x x * * * * *
1641 SUBX x x * * * * *
1642 SWAP x - * * 0 0
1643 TAS x x x x x x x x - * * 0 0
1644 TRAP x - - - - -
1645 TRAPV - - - - -
1646 TST x x x x x x x x - * * 0 0
1647 UNLK x - - - - -
1648
1649
1650
1651
1652 Chapter 3.
1653 ---------
1654 3.Working With Assemblers.
1655 -------------------------
1656 The instructions that you've learned so far are incomprehensible
1657 to the MC68000 processor.The letters MOVE mean absolutely nothing
1658 to the processor-it needs the instructions in binary form.Every
1659 instruction must be coded in a word-which normally takes a lot of
1660 work.
1661 An assembler does this work for you.An assembler is a program that
1662 translates the instructions from text into the coresponding binary
1663 instructions.The text that is translated is called Mnemonic or
1664 Memcode.Its a lot easier working with text instructions-or does
1665 $4280 mean more to you than CLR.L D0?
1666 This chapter is about working with assemblers.We'll describe the
1667 following three:
1668 ASSEM;
1669 This is the assembler from the Amiga's development package.This
1670 assembler is quite powerful,but it is clearly inferior to its two
1671 fellow compilers in some areas.
1672 AssemPro;
1673 This is the Abacus assembler.It has a debugger in addition to the
1674 assembler.This lets you test and correct programs.In our opinion,
1675 it is the best one to use for writing and testing practice
1676 programs.For this reason,we wrote the programs in this book with
1677 this assembler.
1678 KUMA-SEKA;
1679 This is a popular assembler which also has a debugger.
1680
1681 All assemblers perform a similar task-they translate memcode,so
1682 that you can write a runable program to disk.To test the program
1683 directly,you need a debugger which is something Assem doesn't
1684 have.
1685
1686 3.1.The Development Assembler.
1687 -----------------------------
1688 This assembler is a plain disk assembler.That means that it can
1689 only assemble text files that are on disk and write the result
1690 back to disk.You can't make direct input or test run the new
1691 program.
1692 You can call ASSEM from the CLI by typing ASSEM followed by
1693 parameters that specify what you wish the assembler to do.
1694 In the simplest case,you call it like this:
1695
1696 ASSEM Source -O Destination
1697
1698 Source is the filename of the file containing the program text.
1699 Destination is the name of the file that contains the results of
1700 assembling after the process is over.The "-O"means that the
1701 following name is used for the object file.
1702 There are several other parameters that can be passed.These are
1703 written with their option(ie-O),so that the assembler knows what
1704 to do with the file that you've told it to use.The following
1705 possible options must be followed by a filename.
1706
1707 -O Object file
1708 -V Error messages that occur during assembling are written
1709 to a file.If this isn't given,the error messages appear
1710 in the CLI window.
1711 -L The output of the assembled program lines are sent to
1712 this file.You can also use"PRT:"to have it printed.
1713 -H This file is read in at the beginning of the assembled
1714 file and assembled along with it.
1715 -E A file is created that contains lines which have EQU
1716 instructions.
1717 -C This option isn't followed by a filename but by another
1718 option.You can also use OPT to do this.The following
1719 options are available:
1720
1721 OPT S A symbol table is created which contains all the
1722 labels and their values.
1723 OPT X A cross reference list is created(where labels
1724 are used).
1725 OPT W A number must follow this option.It sets the
1726 ammount of workspace to be reserved.
1727
1728 The assembler creates an object file.This is not runnable.To make
1729 it runnable,you need to call the linker,ALINK.This program can
1730 link several assembled or compiled object files together to make a
1731 runnable program.In the simplest case,you enter the following
1732 instruction in the CLI:
1733
1734 ALINK Source TO Destination
1735
1736 Source is the object file produced by the assembler.Destination is
1737 the name of the program.It can be started directly.
1738
1739 3.2.AssemPro.
1740 ------------
1741 Abacus's AssemPro is a package which combines editor,assembler and
1742 debugger in an easy to use package.
1743 The AssemPro Program is divided into several windows-one for the
1744 assembler,the editor,the debugger and several help functions.
1745 Producing a program is very easy:
1746
1747 1) Write the program with the editor and then store it to disk.
1748 2) Start the assembler,so that the program is translated.
1749 3) If desired,start the debugger,load the program and test it.
1750
1751 Within the debugger you can work through parts of the program or
1752 even through single commands.As after each one of these steps the
1753 debugger shows you the state of the registers and flags in the
1754 status register,you can easily try the programs presented in this
1755 book.
1756 You need to load AssemPro only once when working with machine
1757 language programs.Thus you don't need to save back and to between
1758 editor,assembler,linker and debugger.
1759 AssemPro has an especially interesting function:the reassembler.
1760 With this debugger function you are able to convert runnable
1761 programs into the source text of the program.Once you have made
1762 the source text,you can edit the program using the editor and
1763 assemble it again.AssemPro is equipped with functions other
1764 assemblers miss.There are however,some differences you should know
1765 about.As many programs you see were written for the K-SEKA,be
1766 aware of one difference:the EVEN command.AssemPro uses the ALIGN
1767 instruction.
1768 Note,that when entering and assembling one of the programs in
1769 AssemPro you must make sure that you place an END directive at the
1770 end of the source text.
1771 The following is an introduction into working with AssemPro and
1772 the programs in this book.
1773
1774 Start AssemPro normally,next click on the editor window and start
1775 typing in your program.If the program is on disk already,load it
1776 by selecting the appropriate menu or by using the key combination
1777 right <AMIGA> key and <o>.To do this you only need to ckick on the
1778 filename in the displayed requester and click on the OK gadget.
1779 Once you have typed in or loaded the program into the editor,you
1780 can assemble it.It is best to save your source before assembling.
1781 You assemble your program by clicking on the assembler window
1782 displayed above the editor window and pressing <AMIGA> and <a>.You
1783 can then choose how to locate your program in the memory.Remember
1784 that data used by the co-processors must be located in CHIP RAM.
1785 By clicking OK you start the assembler process.If you additionally
1786 select "breakable",you can cancel the process by pressing both
1787 shift keys.If any error occurs during assembling,AssemPro uses a
1788 window to tell you this.Use this window to correct the error and
1789 continue with "Save and try again".
1790 Now the runnable program is located in the Amiga's memory.Use the
1791 menu item "Save as"to save it on disk.If you want to store it on
1792 RAM disk,click the given filename and enter RAM: in front of this
1793 name.In addition you can click on the menu item "ICON"and choose
1794 if you only want the program itself on disk but the icon too.Use
1795 this icon to start the program at a later time from Workbench.
1796 To test-run the program,you move the debugger window to the
1797 foreground of the screen(for instance by clicking on the back
1798 gadget).Use "Load"in the debugger menu or <AMIGA> <o> to call the
1799 select file window,where you select the saved program.The program
1800 is then loaded into the memory and its shown disassembled.
1801 The highlighted line(orange)represents the current state of the
1802 program counter.This is the line where the processor reads its
1803 next instruction,provided you tell the processor so.There are
1804 three ways to do so.
1805 The first one is to start the program with "Start".This
1806 alternative does not enable you to stop the program if anything
1807 goes wrong.
1808 The second possibility,"Start breakable"is better in this respect.
1809 After the program starts,it continuously displays the registers
1810 contents on the left side of the window.In addition to that you
1811 can cancel the process by pressing <ESC>.Note that this only works
1812 if your program doesn't use the <ESC>key itself.
1813 The third possibility enables you to only partly run your program.
1814 You can do this by stepping through the program or by placing
1815 breakpoints throughout the program.You place these by clicking on
1816 the desired address and then pressing <AMIGA> <b>."BREAKPOINT"is
1817 displayed where the command was displayed before.If you start the
1818 program now,it stops whenever it comes across any breakpoints.
1819 You can start a small part of the program by moving the mouse
1820 pointer to the orange line,clicking the left button and holding it
1821 down while you drag the mouse pointer downward.If you release the
1822 button,the processor works through this part of the program,
1823 stopping at the line,where you positioned the mouse pointer.This
1824 is a very useful method to step by step test a program.
1825 AssemPro as another helpful window:the Table.This window lists the
1826 valid address methods for instructions and the parameters of Amiga
1827 functions.This is extremely helpful whenever you are not sure
1828 about one of the instructions.
1829
1830 3.3.The K-SEKA Assembler.
1831 ------------------------
1832 The SEKA assembler,from KUMA,has a simple text editor and a
1833 debugger in addition to the assembler.This program is controlled
1834 by simple instructions and it is easy to use.It is also multi-
1835 functional and quick,so it is great for small test and example
1836 programs.You can use it to write bigger programs once you've got
1837 use to the editor.Now lets look at the editor.
1838 To load a program as source code(text)into the editor,enter"r"
1839 (read).The program asks you for the name of the file with the
1840 "<FILENAME>"prompt.You then enter the name of the text file.If you
1841 created the file with SEKA,the file is stored on disk with".s" on
1842 the end of its name.You don't need to include the".s"when you load
1843 the file.Thats taken care of automatically.("s"stands for source.)
1844 You can store programs you've just written or modified by using
1845 the"w"instruction.The program asks you for the name.If you enter
1846 "Test",the file is written to the disk with"Test.s"as its name.
1847 This is a normal text file in ASCII format.
1848 There are two ways to enter or change a programs:using the line
1849 editor or the screen editor.You can enter the second by hitting
1850 the <ESC>key.The upper screen section is then reserved for the
1851 editor.You can move with the cursor keys and change the text
1852 easily.The lines that you enter are inserted into the existing
1853 text and automatically numbered.By hitting the <ESC>key again,you
1854 leave the screen editor.
1855 There's really not much to say about this editor.It's really just
1856 for simple insertions and changes.Other functions are called in
1857 normal instruction mode,the mode in which">"is the input prompt.
1858 The following instructions are available to you for text editing
1859 (<n>stands for a number.The meaning of the instructions is in
1860 parenthesis.)
1861
1862 Instruction Function
1863 ----------------------------------------------------------------
1864 t(Target) Puts the cursor on the highest line in the
1865 text.
1866 t<n> Puts the cursor on line n.
1867 b(Bottom) Puts the cursor on the last line in the text.
1868 u(Up) Go up one line.
1869 u<n> Go up n lines.
1870 d(Down) Go down one line.
1871 d<n> Go down n lines.
1872 z(Zap) Deletes the current line.
1873 z<n> Deletes n lines starting at the cursor line.
1874 e(Edit) Lets you edit the current line(and only that
1875 line).
1876 e<n> Edit from line n.
1877 ftext(Find) Searches for the text entered starting at the
1878 current line.The case of a letter makes a
1879 difference,so make sure to enter it correctly.
1880 Blanks that appear after the f are looked for
1881 as well!
1882 f Continues searching beyond the text that was
1883 previously given.
1884 i(Insert) Starts the line editor.Now you can enter a
1885 program line by line.However,you can't use the
1886 cursor to move into another line.Line numbers
1887 are generated automatically.The lines that
1888 follow are moved down,not erased.
1889 ks(Kill Source) The source text is deleted if you answer"y"
1890 when the program asks if you are sure.Otherwise
1891 nothing happens.
1892 o(Old) Cancels the "ks"function and saves the old text
1893 p(Print) Prints the current line.
1894 p<n> Prints n lines starting at cursor line.
1895
1896 Those are the K-SEKA's editor functions.In combination with the
1897 screen editor,they allow for simple text editing.You can,for
1898 example,delete the current line(and other lines)while working in
1899 the screen editor by hitting <ESC> to get into instruction mode
1900 and then entering"z"(or "z<n>").
1901 If you'd like to edit all lines that contain "trap",for example,
1902 you can do the following:
1903
1904 -Jump to the beginning of the text using "t"
1905 -Search for a "trap"instruction by entering "ftrap" in the
1906 first line.
1907 -Press <ESC> and edit the line.
1908 -Press <ESC> again to get into instruction mode.
1909 -Search using "f",<ESC>,etc.until you get to the end of the
1910 text.
1911
1912 This sounds very clumsy,but in practise it works quite well and
1913 goes quickly.Experiment with the editor bit,so you can get use to
1914 it.
1915 Now here are the instructions for working with disks:
1916
1917 Instruction Function
1918 -----------------------------------------------------------------
1919 v(View files) Look at the disk's directory.You can also
1920 include the disk drive or subdirectory
1921 that interests you.For example,"vc"causes
1922 the "c"subdirectory to be listed and makes
1923 it the current directory.
1924 kf(Kill file) The program asks for the name of the file.
1925 The file is deleted(and you aren't asked
1926 if your sure either-so be careful).
1927 r(Read) After inputting this instruction,you'll be
1928 asked which file to load(FILENAME>).The
1929 file that you specify is then loaded.If
1930 only "r"is entered,a text file is loaded
1931 in the editor.
1932 ri(Read Image) Loads a file into memory.After you've
1933 entered the filename,SEKA asks for the
1934 address the file should begin at in memory
1935 (BEGIN>)and the highest address that
1936 should be used for the file(END>).
1937 rx(Read from Auxillary) This works just like the "ri"function
1938 except that it reads from the serial port
1939 instead of from disk(You don't need a file
1940 name).
1941 rl(Read Link file) This instruction reads in a SEKA created
1942 link file.First you'll be asked if you are
1943 sure,because the text buffer is erased
1944 when the link file is loaded.
1945 w(Write) After entering this instruction,you'll be
1946 asked for the name of the file the text
1947 should be written to.A".s"is automatically
1948 appended to the name,so that it can be
1949 recognized as a SEKA file.
1950 wi(Write Image) Stores a block of memory to disk after the
1951 name,beginning and end are entered.
1952 wx(Write to Auxillary) This is similar to"wi";the only difference
1953 is that the output is to the serial inter-
1954 face.
1955 wl(Write Link file) Asks for the name and then stores a link
1956 file that was assembled with the"I"option
1957 to disk.If this isn't available,the
1958 message "* * Link option not specified"
1959 appears.
1960
1961 Once you've typed in or loaded a program,you can call the
1962 assembler and have the program translated.Just enter"a"to do so.
1963 You'll then be asked which options you want to use.If you enter a
1964 <RETURN>,the program is assembled normally-ie the results of
1965 translating a program in memory is stored in memory.Then the
1966 program can be executed straight away.
1967 You can enter one or more of the following options,however:
1968
1969 v The output of the results goes to the screen.
1970 p or
1971 e goes to the printer with a title line.
1972 h The output stops after every page and waits for a key
1973 stroke.This is useful for controlling output to the screen
1974 or for putting new sheets of paper in the printer.
1975 o This option allows the assembler to optimize all possible
1976 branch instructions.This allows the program code to be
1977 shorter than it would otherwise be.Several messages appear
1978 but you can ignore them.
1979 l This option causes linkable code to be produced.You can
1980 save it with the"wl"instruction and read it with the "rl"
1981 instruction.
1982
1983 A symbol table is included at the end of the listing if desired.
1984 The table contains all labels and their values.It also contains
1985 macro names.A macro allows several instructions to be combined in
1986 to a single instruction.
1987 For example,suppose you wrote a routinethat outputs the text that
1988 register A0 points to.Every time you need to use the routine,you
1989 must type:
1990
1991 lea text,a0 ;pointer to text in A0
1992 bsr pline ;output text
1993
1994 You can simplify this by defining a macro for this function.To do
1995 this,put the following at the beginning of the program:
1996
1997 print:macro ;Macro with the name "Print"
1998 lea ?1,a0 ;Parameter in A0
1999 bsr pmsg ;Output text
2000 endm ;End of macro
2001
2002 Now,you can simply write the following in your program:
2003
2004 print text ;Output text
2005
2006 This line is replaced using the macro during assembly.The
2007 parameter "text"is inserted where "?1"appears in the macro.You can
2008 have several parameters in a macro.You give them names like "?2",
2009 "?3",etc...
2010 You can also decide whether you'd like to see the macros in the
2011 output listing of the assembler.This is one of the pseudo-ops that
2012 are available in the assembler.The SEKA assembler has the
2013 following pseudo-ops:
2014
2015 dc Defines one or more data items that should appear in
2016 this location in the program.The word length can be
2017 specified with .B,.W,or .L-and if this is left off, .B
2018 is used.Text can be entered in question marks or
2019 apostrophes.For example:dc.b "Hello",10,13,0
2020 blk Reserves a number of bytes,words or long words,depending
2021 on whether .B,.W,or .L is chosen.The first parameter
2022 specifies the number of words to be reserved.The second
2023 (which is optional)is used to fill the memory area.For
2024 example:blk.w 10,0
2025 org The parameter that follows the org instruction is the
2026 address from which the (absolute) program should be
2027 assembled.For example: org $40000
2028 code Causes the program to be assembled in relative mode,the
2029 mode in which a program is assembled starting at address
2030 0.The Amiga takes care of the new addressing after the
2031 program is loaded.
2032 data This means that from here on only data appear.This can
2033 be left out.
2034 even Makes the current address even by sometimes inserting a
2035 fill byte.
2036 odd The opposite of even-it makes the address odd.
2037 end Assembling ends here.
2038 equ or Used for establishing the value of a label
2039 = For example: Value=123 or Value:equ 123
2040 list Turns the output on again(after nlist).You can use the
2041 following parameters to influence the output:
2042 c Macro calls
2043 d Macro definitions
2044 e Macro expansion of the program
2045 x Code expansions
2046 For example: list e
2047 nlist Turns off output.You can use the same parameters here as
2048 with "list".
2049 page Causes the printer to execute a page feed,so that you'll
2050 start a new page.
2051 if The following parameter decides whether you should
2052 continue assembling.If it is zero,you won't continue
2053 assembling.
2054 else If the "if"parameter is zero,you'll begin assembling
2055 here.
2056 endif End of conditional assembling.
2057 macro Start of a macro definition.
2058 endm End of macro definition.
2059 ?n The text in the macro that is replaced by the nth
2060 parameter in the calling line.
2061 ?0 Generates a new three digit number for each macro call-
2062 this is very useful for local labels.
2063 For example: x?0:bsr pmsg
2064 illegal Produces an illegal machine language instruction.
2065 globl Defines the following label as globel when the "I"option
2066 of the assembler is chosen.
2067
2068 Once you've assembled your program,the program code is in memory.
2069 Using the "h"instruction,you can find out how large the program is
2070 and where it is located in memory.The beginning and end address is
2071 given in hex and the length in decimal(according to the last
2072 executed operations):
2073
2074 Work The memory area defined in the beginning
2075 Src Text in memory
2076 RelC Relocation table of the program
2077 RelD Relocation table of the memory area
2078 Code Program code produced
2079 Data The program's memory area
2080
2081 You'll find program in memory at the location given by Code.It's a
2082 pain to have to enter this address whenever you want to start the
2083 program.It make's good sense to mark the beginning of the program
2084 with a label(for example,"run:").You can use the "g"instruction to
2085 run the program as follows:
2086
2087 g run
2088
2089 The"g"(GO)instruction is one of SEKA's debugger instrucions.Heres
2090 an overview:
2091
2092 x Output all registers.
2093 xr Output and change of registers(ie xd0)
2094 gn Jump to address n.You`ll be asked for break points,addresses
2095 at which the program should be terminate.
2096 jn This is similar to the one above-a JSR is used to jump into
2097 the program.The program must end with a RTS instruction.
2098 qn Output the memory starting at address n.You can also specify
2099 the word length.For example: q.w $10000
2100 nn Disassembled output starting at address n.
2101 an Direct assembling starting at address n.Direct program
2102 instructions are entered.
2103 nn Modify the contents of memory starting at address n.Here too
2104 the word length can be given.You can terminate input with
2105 the <ESC> key.
2106 sn Executes the program instruction that the PC points to.After
2107 you enter this instruction,n program steps are executed.
2108 f Fill a memory area.You can choose the word width.All the
2109 needed parameters are asked for individually.
2110 c Copies one memory area to another.All the needed parameters
2111 are asked for individually.
2112 ? Outputs the value of an expression or a label.
2113 For example: ?run+$1000-256
2114 a Sets an instruction sequence that is passed to the program
2115 when it starts as if it were started from CLI with this
2116 sequence.
2117 ! Leaves the SEKA assembler after being asked if your sure.
2118
2119 You saw some of the calculations like SEKA can make in the "?"
2120 example.You can also use them in programming.The folowing
2121 operations work in SEKA:
2122
2123 + Addition
2124 - Subtraction
2125 * Multiplication
2126 / Division
2127 & Logic AND
2128 ! Logic OR
2129 ~ EXclusive OR (XOR)
2130
2131 These operations can also be combined.You can choose the counting
2132 system.A "$"stands for hexadecimal,"@"for octal,and "%"for binary.
2133 If these symbols aren`t used,the number is interpreted as a
2134 decimal number.
2135 Lets go back to the debugger.As mentioned,after entering "g
2136 address",you`ll be asked for break points.You can enter up to 16
2137 addresses at which the program halts.If you don`t enter break
2138 points,but instead hit <RETURN>,the program must end with an
2139 ILLEGAL instruction.If it ends instead with a RTS,the next return
2140 address from the stack is retrieved and jumped to.This is usually
2141 address 4 which causes SEKA to come back with "**Illegal
2142 Instruction at $000004",but theres no guarantee that it will.Your
2143 computor can end up so confused that it can`t function.
2144 The SEKA program puts an ILLEGAL instruction in the place
2145 specified as break points after saving the contents of these
2146 locations.If the processor hits an illegal instruction,it jumps
2147 back to the debugger by using the illegal instruction vector that
2148 SEKA set up earlier.Then SEKA repairs the modified memory
2149 locations and then displays the status line.Here you can find out
2150 where the program terminated.
2151 Using break points is a good technique for finding errors in the
2152 program.You can,for example,put a break point in front of a
2153 routine that you`re not sure about and start the program.When the
2154 program aborts at this spot,you can go through the routine step by
2155 step using the "s"option.Then you can watch what happens to the
2156 status line after each instruction and find the mistake.
2157 Program errors are called bugs.That`s why the program that finds
2158 them is called a debugger.
2159
2160
2161
2162
2163 Chapter 4.
2164 ---------
2165 4.Our First Programs.
2166 --------------------
2167 You`re getting pretty far along in your knowledge of machine
2168 language programming.In fact,you`re to the point where you can
2169 write programs,and not just programs for demonstration purposes,
2170 but ones that serve a real function.We`re assuming that you have
2171 the AssemPro assembler and have loaded it.
2172 If you`re using a different assembler,a few things must be done
2173 differently.We covered those differences already in the chapter on
2174 the different assemblers.
2175 We`ve written the example programs as subroutines so they can be
2176 tried out directly and used later.After assembling the program,you
2177 can put the desired values in the register.Then you can either
2178 single-step thru the programs or run the larger programs and
2179 observe the results in the registers directly.(using the SEKA
2180 assembler you can type "j program_name"to start the program.Then
2181 you can read the results from the register directly,or use "q
2182 address"to read it from memory.)
2183 Lets start with an easy example,adding numbers in a table.
2184
2185 4.1.Adding Tables.
2186 -----------------
2187 Imagine that you have numbers in memory that you'd like to add.
2188 Lets assume that you have five numbers whose length is one word
2189 each.You want their sum to be written in register D0.The easiest
2190 way to do this is:
2191
2192 ;(4.1A)
2193 adding1:
2194 clr.l D0 ;Erase D0 (=0)
2195 move table,d0 ;First entry in D0
2196 add table+2,d0 ;Add second entry
2197 add table+4,d0 ;Add third entry
2198 add table+6,d0 ;Add fourth entry
2199 add table+8,d0 ;add fifth entry
2200 rts ;Return to main program
2201 table: dc.w 2,4,6,8,10,
2202 end
2203
2204 Try out the program using the debugger by single stepping thru the
2205 program until you get to the RTS instruction(left Amiga T).(SEKA
2206 owners use "j adding1").You see that data register D0 really
2207 contains the sum of the values.
2208 The method above only reads and adds numbers from a particular set
2209 of addresses.The Amigas processor has lots of different sorts of
2210 addressing modes that give us a shorter and more elegant solution.
2211 Lets add a variable to the address of the table,so that the
2212 program can add different tables.
2213 Lets put the addresses of the table in an address register(for
2214 example, A0)instead.This register can be used as a pointer to the
2215 table.You must use move.l since only long words are relocatable.By
2216 using a pointer to a table you can use indirect addressing.You can
2217 change the expression "table+x" to"x(A0)".
2218
2219 ;(4.1B)
2220 adding1:
2221 clr.l D0 ;Erase D0 (=0)
2222 move.l #table,a0 ;Put table addresses in A0
2223 move 0(a0),d0 ;Put first entry in d0
2224 add 2(a0),d0 ;Add second entry
2225 add 4(a0),d0 ;Add third entry
2226 add 6(a0),d0 ;Add forth entry
2227 add 8(a0),d0 ;Add fifth entry
2228 rts ;Return to main program]
2229 table: dc.w 2,4,6,8,10
2230 end
2231
2232 Assemble this program,load it into the debugger.Then single step
2233 (left Amiga T)thru this program and you'll see that this program
2234 adds five numbers in order just like the last one.The reason you
2235 used a step size of two for the ofset is that words are two bytes
2236 long.AssemPro also defaults to relocate code so that you must move
2237 #table as a long word.
2238 Lets improve the program more by using "(a0)+"instead of "x(a)".
2239 This way,every time you access elements of the table,the address
2240 register A0 is automatically incremented by the number of bytes
2241 that are read(in this case two).The difference between this and
2242 the last example is that here the registers contents are modified.
2243 The pointer is to the next unused byte or word in memory.
2244 Lets make it even better.Lets make the number of words to be added
2245 to a variable.You'll pass the number in register D1.Now you need
2246 to do a different sort of programming,since you can't do it with
2247 the old methods.
2248 Lets use a loop.You need to add D1 words.You can use(a0)+ as the
2249 addressing method(address register indirect with post increment),
2250 since this automatically gets you to the next word.
2251 Now for the loop.You'll have D1 decremented by one every time the
2252 contents of the pointer are added.If D1 is zero,then you're done.
2253 Otherwise,you need another addition.The program looks like this:
2254
2255 ;(4.1C)
2256 adding2:
2257 clr.l d0 ;Erase D0
2258 move.l #table,a0 ;Put table addresses in A0
2259 move #$5,d1 ;Put number of entries in D1
2260
2261 loop: ;Label for loop beginning
2262 add (a0)+,d0 ;Add a word
2263 subq #1,d1 ;Decrement counter
2264 bne loop ;Continue if non-zero
2265 rts ;Else done
2266
2267 table: dc.w 2,4,6,8,10
2268 end
2269
2270 Lets take a close look at this program.Load the pointer A0 with
2271 the addresses of the data and the counter D1 with the number of
2272 elements.Then you can single step thru the program and watch the
2273 results.Make sure not to run the final command,the RTS command,
2274 because otherwise a return address is popped from the stack,and
2275 the results of this are unpredictable.(SEKA owners can use"x pc"
2276 to point the program counter to "adding2".You can then step thru
2277 the program by using the "s"command and watch the results).
2278 To finish up this example,your assigning a little homework.Write
2279 the program so that it adds single bytes or long words.Try to
2280 write a program that takes the first value in a table and
2281 subtracts the following values.For example,the table
2282
2283 table: dc.w 50,8,4,6
2284
2285 should return the value 50-8-4-6, ie 32 ($20).
2286
2287 4.2.Sorting a Table.
2288 -------------------
2289 Lets keep working with tables.You don't want to just read data
2290 from one this time.You want to change it.You'll assort the table
2291 in assending order.
2292 You need to decide how to do the sorting.The simplest method is to
2293 do the following.
2294 Compare the first and the second value.If the second value is
2295 larger than the first one,things are OK so far.Do the next step,
2296 compare the second and third values,and so on.If you come to the
2297 final pair and in each case the preceding value was smaller than
2298 the following value,then the sorting is done(it was unnescessary).
2299 If you find a pair where the second value is smaller than the
2300 first,the two values are exchanged.You then get a flag(here let's
2301 use a register)that is checked once you're done going thru the
2302 table.If it is set,the table probably isn't completely sorted.You
2303 then erase the flag and start again from the beginning.If the flag
2304 is still zero at the end,the sorting is complete.
2305 Now let's write a program to do this.First let's figure out the
2306 variables you need.You'll use registers for the variables.You need
2307 a pointer to the table you're sorting(A0),a counter(D0)and a flag
2308 (D1).While the program is running,change these values,so you'll
2309 need two more registers to store the starting values(address and
2310 the number of the table entries).You'll use A1 and D2.
2311 Let's start writing the program,each section will be written and
2312 then explained.Then the complete program will be given.You put the
2313 tables address in A1 and the number of entries in D2.
2314
2315 ;(4.2A) part of sort routine
2316 sort: ;Start address of the program
2317 move.l #table,a1 ;Load pointer with address
2318 move.l a1,a0 ;Copy pointer to working register
2319 move.l #5,d2 ;Number in the counter
2320 move.l d2,d0 ;Copy number of elements
2321 subq #2,d0 ;Correct conter value
2322 clr d1 ;Erase flag
2323
2324 table: dc.w 3,6,9,5
2325
2326 end
2327
2328 Now the preparations are complete.The pointer and the counter are
2329 ready and the flag is cleared.The counter is decremented by two
2330 because you want to use the DBRA command(take one off)and only X-1
2331 comparrisons are needed for X numbers(take off one more).
2332 Next let's write the loop that compares the values.You compare one
2333 word with another.It looks like this:
2334
2335 loop:
2336 move 2(a0),d3 ;Next value in register D3
2337 cmp (a0),d3 ;Compare values
2338
2339 You need to use register D3 because CMP (A0),2(A0) isn't a legal
2340 choice.If the second value is greater than or equal to the first
2341 value,you can skip an exchange.
2342
2343 bcc noswap ;Branch if greater than or equal
2344 ;to
2345
2346 Now you need to do the exchanging(unfortunatly you can't use EXC
2347 2(a0),(a0) since this form of addressing does not exist).
2348
2349 doswap:
2350 move (a0),d1 ;Save first valus
2351 move 2(a0),(a0) ;Copy second into first word
2352 move d1,2(a0) ;Move first into second
2353 moveq #1,d1 ;Set flag
2354 noswap:
2355
2356 Now increment the counter and continue with the next pair.You do
2357 this until the counter is negative.
2358
2359 addq.l #2,a0 ;Pointer+2
2360 dbra d0,loop ;Continuing looping until the end
2361
2362 Now you'll see if the flag is set.You start again at the beginning
2363 if it is.
2364
2365 tst d1 ;Test flag
2366 bne sort ;Not finished sorting yet!
2367 rts ;Otherwise done.Return
2368
2369 If the flag is zero,you're done and the subroutine ends.You jump
2370 back to the main program using the RTS command.
2371 Now a quick overview of the complete program.
2372
2373 ;(4.2B)
2374 sort: ;Start address of the program
2375 move.l #table,a1 ;Load pointer with address
2376 move.l a1,a0 ;Copy pointer to working register
2377 move.l #5,d2 ;Number in the counter
2378 move.l d2,d0 ;Copy number of elements
2379 subq #2,d0 ;Correct counter value
2380 clr d1 ;Erase flag
2381
2382 loop:
2383 move 2(a0),d3 ;Next value in register D3
2384 cmp (a0),d3 ;Compare values
2385 bcc noswap ;Branch if greater than or equal to
2386
2387 doswap:
2388 move (a0),d1 ;Save first value
2389 move 2(a0),(a0) ;Copy second into first word
2390 move d1,2(a0) ;Move first into second
2391 moveq #1,d1 ;Set flag
2392
2393 noswap:
2394 addq.l #2,a0 ;Pointer+2
2395 dbra do,loop ;Continue looping until the end
2396 tst d1 ;Test flag
2397 bne sort ;Not finished sorting yet!
2398 rts ;Otherwise done.Return
2399
2400 table:
2401 dc.w 10,8,6,4,2 ;When finished acceding
2402
2403 end
2404
2405 To test this subroutine,assemble the routine with AssemPro,save it
2406 and then load it into the debugger.The table is directly after the
2407 RTS,notice its order.Set a breakpoint at the RTS,select the
2408 address with the mouse and press left-Amiga-B sets a breakpoint in
2409 AssemPro.Start the program the redisplay the screen by selecting
2410 "Parameter-Display-Dissassem-bled"and examine the order of the
2411 numbers in the table,they should now be ascending order.
2412 You use several registers in this example for storing values.
2413 Usually in machine language programming your subroutines cannot
2414 change any register or can only change certain registers.For this
2415 reason,there is a machine language command to push several
2416 registers onto the stack at the same time.This is the MOVEM ("MOVE
2417 multiple")command.If you insert this command twice in your program
2418 then you can have the registers return to the main program with
2419 the values they had when the subroutine was called.To do this,you
2420 need one more label.Let's call it"start";the subroutine is started
2421 from here.
2422
2423 start:
2424 movem.l d0-d7/a0-a6,-(sp) ;save registers
2425
2426 sort:
2427 etc...
2428 ...
2429 ...
2430 bne sort ;not finished sorting yet!
2431
2432 movem.l (sp)+,d0-d7/a0-a6 ;retrieve registers
2433 rts ;finished
2434
2435 The powerful command moves several registers at the same time.You
2436 can specify which registers should be moved.If you want to move
2437 the D1,D2,D3,D7,A2 and A3 registers,just write
2438
2439 movem.l d1-d3/d7/a2-a3,-(sp)
2440
2441 Before you quit sorting,do one little homework assignment.Modify
2442 the program,so that it sorts the elements in descending order.
2443
2444 4.3.Converting Number Systems.
2445 -----------------------------
2446 As we mentioned in the chapter on number systems,converting
2447 numbers from one base to another can be rather difficult.There is
2448 another form of numeric representation-as a string that can be
2449 entered via the keyboard or output on the screen.
2450 You want to look at some of the many conversions possible and
2451 write programs to handle the task.You'll start by converting a hex
2452 number into a string using binary numbers and then print the value
2453 in hex.
2454
2455 4.3.1.Converting Hex To ASCII.
2456 -----------------------------
2457 First you need to set the start and finish conditions.In this
2458 example,let's assume that data register D1 contains a long word
2459 that should be converted into a 8-digit long string of ASCII
2460 characters.You'll write it to a particular memory location so that
2461 you can output it later.
2462 The advantage of using hex instead of decimal is pretty clear in
2463 this example.To find out the hexadecimal digit for a particular
2464 spot in the number,you just need to take the corresponting 4 bits
2465 (half byte)and do some work on it.A half byte(also called a
2466 nibble)contains one hex digit.
2467 You'll work on a half byte in D2.To convert this to a printable
2468 character,you need to use the correct ASCII code.The codes of the
2469 16 characters that are used as hex digits are the following:
2470
2471 0 1 2 3 4 5 6 7 8 9 A B C D E F
2472
2473 $30 $31 $32 $33 $34 $35 $36 $37 $38 $39 $41 $42 $43 $44 $45 $46
2474
2475 To convert the digits 0-9,you just need to add $30.For the letters
2476 A-F that correspond to the values 10-15,you need to add $37.The
2477 program to evaluate a half byte must make a destinction between
2478 values between 0 and 9 and those between A and F and add either
2479 $30 or $37.
2480 Now let's write a machine language subroutine that you'll call for
2481 each digit in the long words hex representation.
2482
2483 nibble:
2484 and #$0f,d2 ;just keep low byte
2485 add #$30,d2 ;add $30
2486 cmp #$3a,d2 ;was it a digit?
2487 bcs ok ;yes:done
2488 add #7,d2 ;else add 7
2489
2490 ok:
2491 rts ;done
2492
2493 This routine converts the nibble in D2 to an ASCII character that
2494 corresponds to the hex value of the nibble.To convert an entire
2495 byte,you need to call the routine twice.Here is a program to do
2496 this.The program assumes that A0 contains the address of the
2497 buffer that the characters are to be put in and that D1 contains
2498 the byte that is converted.
2499
2500 ;(4.3.1a) bin-hex
2501 ; ;your program
2502 lea buffer,a0 ;pointer to buffer
2503 move #$4a,d1 ;byte to be converted(example)
2504 bsr byte ;and convert
2505 rts
2506 ; ... ;more of your program
2507 byte:
2508 move d1,d2 ;move value into d2
2509 lsr #4,d2 ;move upper nibble into lower nibble
2510 bsr nibble ;convert d2
2511 move.b d2,(a0)+ ;put character into buffer
2512 move d1,d2 ;value in d2
2513 bsr nibble ;convert lower nibble
2514 move.b d2,(a0)+ ;and put it in buffer
2515 rts ;done
2516 nibble:
2517 and #$0f,d2 ;just keep low byte
2518 add #$30,d2 ;add $30
2519 cmp #$3a,d2 ;was it a digit?
2520 bcs ok ;yes:done
2521 add #7,d2 ;else add 7
2522 ok:
2523 rts ;done
2524 buffer:
2525 blk.b 9,0 ;space for long word data
2526
2527 end
2528
2529 To test this subroutine,use AssemPro to assemble the routine,save
2530 the program and load it intoi the debugger.Next set a breakpoint
2531 at the first RTS,to set the breakpoint in AssemPro select the
2532 correct address with the mouse and press the right-Amiga-B keys.
2533 Start the program and watch the contents of D2,it is first $34
2534 (ASCII 4)and finally $41(ASCII A).Select "Parameter-Display-HEX-
2535 Dump"and you'll see that 4A has been moved into the buffer.
2536 This is how the routine operates.First,you move the value that you
2537 wish to convert into D2.Then you shift the register four times to
2538 the right to move the upper nibble into the lower four bits.After
2539 the subroutine call,you use "move.b d2,(a0)+"to put the HI nibble
2540 in the buffer.Then the original byte is put in D2 again.It is
2541 converted.This gives us the LO nibble as an ASCII character in D2.
2542 You put this in the next byte of the buffer.
2543 The buffer is long enough to hold a long word in characters and
2544 closing the null byte.The null byte is usually required by screen
2545 output routines.Screen output will be discussed in a later
2546 chapter.Now let's worry about converting a long word.
2547 When converting a long word,you need to be sure to deal with the
2548 nibbles in the right order.Before calling the "nibble"routine for
2549 the first time,you need to move the upper nibble into the lower 4
2550 bits of the long word.You need to do this without losing anything.
2551 The LSR command isn't very good for this application.If you use it
2552 you'll lose bits.Its better to use the rotation commands like ROR
2553 or ROL,since they move the bits that are shifted out,back in on
2554 the other side.
2555 If you shift the original long word in D1 four times to the left,
2556 the upper four bits are shifted into the lower four bits.Now you
2557 can use our "nibble"routine to evaluate it and then put the
2558 resulting ASCII character in the buffer.You repeat this eight
2559 times and the whole long word has been converted.You even have D1
2560 looking exactly the way it did before the conversion process began
2561
2562 ;(4.3.1B) bin-hex-2
2563 hexlong:
2564 lea buffer,a0 ;pointer to the buffer
2565 move.l #$12345678,d1 ;data to convert
2566 move #7,d3 ;counter for the nibbles:8-1
2567
2568 loop:
2569 rol #4,d1 ;move upper nibble into lower
2570 move d1,d2 ;write in d2
2571 bsr nibble ;and convert it
2572 move.b d2,(a0)+ ;character in buffer
2573 dbra d3,loop ;repeat 8 times
2574 rts ;finished!
2575
2576 nibble:
2577 and #$0f,d2 ;just keep low byte
2578 add #$30,d2 ;add $30
2579 cmp #$3a,d2 ;was it a digit?
2580 bcs ok ;yes:done
2581 add #7,d2 ;else add 7
2582
2583 ok:
2584 rts ;done
2585
2586 buffer:
2587 blk.b 9,0 ;space for long word,null byte
2588
2589 end
2590
2591 To test this subroutine,use AssemPro to assemble the routine,save
2592 the program and load it into the debugger.Next set a breakpoint at
2593 the first RTS,to set the breakpoint in AssemPro select the correct
2594 address with the mouse and press the right-Amiga-B keys.Start the
2595 program and when it is finished redisplay the output by selecting
2596 "Parameter-Display-HEX-dump"so you can examine the new buffer
2597 contents.
2598 You'll find that there's an error in the program-the buffer
2599 contains the digits "56785678"instead of "12345678".Try to find
2600 the error.
2601 Have you found it?This is the sort of error that causes you to
2602 start pulling your hair out.This sort is hard to find.The
2603 assembler assumes that the rotation operation should be done on a
2604 word,because the ".l"was left off.As a result,only the lower word
2605 of D1 was rotated-so you get the same value twice.If you change
2606 the "rol.l",things work just right.
2607 The error shows how easy it is to convert the program above into
2608 one that converts four digit hex numbers into ASCII characters.
2609 Just leave off the ".l"on the "rol"command and change the counter
2610 from seven to three.The program is done.
2611 Now for a little homework:change the program so that it can handle
2612 six digit hex numbers(D1 doesn't nescessarily have to stay the
2613 same...)!
2614 Now lets look at a different conversion problem:converting a four
2615 digit decimal number.
2616
2617 4.3.2.Converting Decimal To ASCII.
2618 ---------------------------------
2619 It's not quite as easy to convert decimal as hex.You can't group
2620 the bits to form individual digits.You need to use another method.
2621 Lets look at how a decimal number is constructed.In a four digit
2622 number,the highest place is in the thousands place,the next is the
2623 hundreds place,etc...
2624 If you have the value in a register and divide by 1000,you'll get
2625 the value that goes in the highest place in the decimal number.
2626 Since the machine language command DIV not only gives us the
2627 result of the division but also gives us the remainder,you can
2628 work out the remainder quite easily.You divide the remainder by
2629 100 to find the hundreds place,divide the remainder by 10 and get
2630 the tens place,and the final remainder is the ones place.
2631 This isn't so hard after all!Heres the program that follows the
2632 steps above to fill the buffer with D1's ASCII value.
2633
2634 main:
2635 lea buffer,a0 ;pointer to the buffer
2636 move #1234,d1 ;number to convert
2637 jsr deci_4 ;test subroutine
2638 illegal ;room for breakpoint
2639
2640 deci_4: ;subroutine-four digit numbers
2641
2642 divu #1000,d1 ;divide by 1000
2643 bsr digit ;evaluate result-move remainder
2644
2645 divu #100,d1 ;divide by 100
2646 bsr digit ;evaluate result and move
2647
2648 divu #10,d1 ;divide by 10
2649 bsr digit ;evaluate result-move remainder
2650
2651 ;evaluate the remainder directly
2652
2653 digit:
2654 add #$30,d1 ;convert result into ASCII
2655 move.b d1,(a0)+ ;move it into buffer
2656 clr d1 ;erase lower word
2657 swap d1 ;move the remainder down
2658 rts ;return
2659
2660 buffer:blk.b 5,0 ;reserve bytes for result
2661
2662 end
2663
2664 To test this subroutine,use AssemPro to assemble the routine,save
2665 the program and load it into the debugger.Next set a breakpoint at
2666 the illegal instruction.To set the breakpoint in AssemPro select
2667 the correct address with the mouse and press the right-Amiga-B
2668 keys.This breakpoint stops the program.Start the program and when
2669 it is finished redisplay the output by selecting"Parameter-Display
2670 -HEX-dump"so you can examine the ASCII values now in the buffer.
2671 You use a little trick in this program that is typical for machine
2672 language programming.After calling"digit"three times from the sub-
2673 routine"deci_4",you go right into the"digit"subroutine.You don't
2674 use a BSR or JSR command.Once the processor hits the RTS command,
2675 it returns to the main program,not the "deci_4"subroutine.Doing
2676 this,you save a fourth "bsr digit"command and an "rts"command for
2677 the "deci_4"routine.
2678 Try the program out.Make sure that you use values that are smaller
2679 than 9999,because otherwise strange things can happen.
2680 Now let's reverse what you've been doing and convert strings into
2681 binary numbers.
2682
2683 4.3.3.Converting ASCII To Hex.
2684 -----------------------------
2685 In a string,each hex digit represents a half byte.You just need to
2686 write a program that exactly reverses what the hex conversion
2687 program did.
2688 You have two choices
2689
2690 1. The number of hex digits is known in advance
2691 2. The number is unknown
2692
2693 The first is easier to program,but has the disadvantage that if,
2694 you assume the strings are four digits in length and want to enter
2695 the value 1,you must enter 0001.That is rather awkward,so you'll
2696 use the second method.
2697 Let's convert a single digit first.You'll pass a pointer to this
2698 digit in address register A0.You want the binary value to come
2699 back in data register D0.
2700 The program looks like this:
2701
2702 move.l #string,a0 ;this example
2703 jsr nibblein ;test routine
2704 nop ;set breakpoint here
2705
2706 nibblein: ;*convert the nibble from (A0)
2707 clr.l d0 ;erase D0
2708 move.b (a0)+,d0 ;get digit,increment A0
2709 sub #'A',d0 ;subtract $41
2710 bcc ischar ;no problem:in the range A-F
2711
2712 add #7,d0 ;else correct value
2713 ischar:
2714 add #10,d0 ;correct value
2715 rts
2716
2717 string:dc.b 'B',0 ;character to convert
2718
2719 end
2720
2721 To test this subroutine,use AssemPro to assemble the routine,save
2722 the program and load it into the debugger.Next set a breakpoint at
2723 the first NOP,to set the breakpoint in AssemPro select the correct
2724 address with the mouse and press the right-Amiga-B keys.Start the
2725 program and watch the contents of D0.
2726 Let's see how the program works.A0 points to a memory location
2727 that contains the character "B"that is represented by the ASCII
2728 value $42.This number is loaded into D0 right after this register
2729 is erased.
2730 After subtracting $41,you end up with the value $1.Now you're
2731 almost done.Before returning to the main program,you add 10 to get
2732 the correct value 11,$B.
2733 If the buffer has a digit in it,the subtraction causes the
2734 register to become negative.The C flag is set.Let's take the digit
2735 5 as an example.
2736 The ASCII value of 5 is $35.After subtracting $41,you end up with
2737 -12 and the C flag is set.In this case,you won't branch with the
2738 BCC command.Instead you'll add 7 to get -5.Then 10 is added,and
2739 you end up with 5.Done!
2740 The routine as a disadvantage.If an illegal character is given,one
2741 that doesn't represent a hex digit,you'll get some nonsense result
2742 Let's ignore error checking for the moment though.
2743 Let's go on to multi-digit hex numbers.The first digit that you
2744 convert has the highest value and thus represents the highest
2745 nibble.To allow for this and to allow for an arbitrarily long
2746 number(actually not arbitrarily long,the number should fit in a
2747 long word-so it can only be eight digits long),you'll use a trick.
2748 Take a look at the whole program.It handles the calculations and
2749 puts the result in D1.It assumes that A0 is a pointer to a string
2750 and that this string is ended by null byte.
2751
2752 hexin: ;converting a hex number
2753 clr.l d1 ;first erase D1
2754 move.l #string,a0 ;address of the string in A0
2755 jsr hexinloop ;test subroutine
2756 nop ;set breakpoint here
2757
2758 hexinloop:
2759 tst.b (a0) ;test digit
2760 beq hexinok ;zero,then done
2761 bsr nibblein ;convert digit
2762 lsl.l #4,d1 ;shift result
2763 or.b d0,d1 ;insert nibble
2764 bra hexinloop ;and continue
2765
2766 hexinok:
2767 rts
2768
2769 nibblein:
2770 clr.l d0 ;convert the nibble from (A0)
2771 move.b (a0)+,d0 ;get digit,increment A0
2772 sub #'A',d0 ;subtract $41
2773 bcc ischar ;no problem:in range A-F
2774 add #7,d0 ;else correct value
2775
2776 ischar:
2777 add #10,d0 ;correct value
2778 rts
2779
2780 string:DC.B "56789ABC',00 ;eight digit string,null byte
2781 ;to be converted
2782 end
2783
2784 To test this subroutine,use AssemPro to assemble the routine,save
2785 the program and load it into the debugger.Next set a breakpoint at
2786 the NOP,to set the breakpoint in AssemPro select the correct
2787 address with the mouse and press the right-Amiga-B keys.Start the
2788 program and watch the contents of D1,the hex value is placed in
2789 this register.
2790 The trick is to shift left four times,to shift one nibble.In this
2791 way,the place of the last digit is incremented by one and there is
2792 room for the nibble that comes back from the "nibblein"routine.The
2793 program uses the TST.B instruction to check for the null byte at
2794 the end of the string,when it encounters the null byte the program
2795 ends.The result is in the D1 long word already!
2796 To do some error checking,you need to make some changes in the
2797 program.You'll do this right after you come back from the"nibblin"
2798 routine with the value of the current character.
2799 If the value in D0 is bigger than $F,there is an error.You can
2800 detect this in several ways.You chose the simplest one-you'll use
2801 CMP #$10,D0 to compare D0 with $10.If it smaller,then the C flag
2802 is set(since CMP uses subtraction)and everything is fine.If C is
2803 zero,there is an error.
2804 You can use this trick to skip the test for a null byte,since its
2805 an invalid character as well.The program looks like this:
2806
2807 ;(4_3_3C) hex-conv2 optional disk name
2808 hexin: ;converting a hex number
2809 clr.l d1 ;first erase D1
2810 move.l #string,a0 ;address of string in A0
2811 jsr hexinloop ;test subroutine
2812 nop ;set breakpoint here
2813
2814
2815 hexinloop:
2816 bsr nibblein ;convert digit
2817 cmp $10,d0 ;test if good
2818 bcc hexinok ;no,then done
2819 lsl.l #4,d1 ;shift result
2820 or.b d0,d1 ;insert nibble
2821 bra hexinloop ;and continue
2822
2823 hexinok:
2824 rts
2825
2826 nibblein: ;convert the nibble from (A0)
2827 clr.l d0 ;erase D0
2828 move.b (a0)+,d0 ;get digit,increment A0
2829 sub #'A',d0 ;subtract $41
2830 bcc ischar ;no problem:in the range A-F
2831 add #7,d0 ;else correct value
2832
2833 ischar:
2834 add #10,d0 ;correct value
2835 rts
2836
2837 string:DC.B "56789ABC',00 ;8 digit string ending with a
2838 ;null byte to be converted
2839 end
2840
2841 To test this subroutine,use AssemPro to assemble the routine,save
2842 the program and load it into the debugger.Next set a breakpoint at
2843 the NOP,to set the breakpoint in AssemPro select the correct
2844 address with the mouse and press the right-Amiga-B keys.Start the
2845 program and watch the contents of D1,the hex value is placed in
2846 this register.
2847 This is the method for converting hex to binary.If you convert
2848 decimal to binary,the conversion is not much harder.
2849
2850 4.3.4.Converting ASCII To Decimal.
2851 ---------------------------------
2852 You can use a very similar method to the one used above.Since you
2853 are not sure how many digits there are,you'll use a similar method
2854 for putting digits of a number in the next place up.You can't do
2855 this with shifting,but you can multiply by 10 and add the value of
2856 the digit.
2857 Heres the program for converting decimal numbers.
2858
2859 decin: ;converting a decimal number
2860 clr.l d1 ;first erase D1
2861 move.l #string,a0 ;the string to convert
2862 jsr decinloop ;test subroutine
2863 nop ;breakpoint here
2864
2865 decinloop:
2866 bsr digitin ;convert digit
2867 cmp #10,d0 ;test,if valid
2868 bcc decinok ;no,then done
2869 mulu #10,d1 ;shift result
2870 add d0,d1 ;insert nibble
2871 bra decinloop ;and continue
2872
2873 decinok:
2874 rts ;end of conversion
2875
2876 digitin: ;converting the nibble from (A0)
2877
2878 clr.l d0 ;erase D0
2879 move.b (a0)+,d0 ;get digit,increment A0
2880 sub #'0',d0 ;subtract $30
2881 rts
2882
2883 string:dc.b '123456' ;ASCII decimal string to convert
2884
2885
2886 end
2887
2888 To test this subroutine,use AssemPro to assemble the routine,save
2889 the program and load it into the debugger.Next set a breakpoint at
2890 the NOP,to set the breakpoint in AssemPro select the correct
2891 address with the mouse and press thr right-Amiga-B keys.Select
2892 "Parameter-Output-numbers-Decimal"so the registers are displayed
2893 as decimal numbers.Then start the program and watch the contents
2894 of D1,the decimal value is placed in this register.
2895 This program can ONLY convert numbers upto 655350,although the hex
2896 conversion routine can go higher.Thats because the MULU command
2897 can only multiply 16-bit words.The last multiplication that can be
2898 done correctly is $FFFF*10--65535*10,which gives us the value
2899 655350.Normally this is a large enough range,so you won't
2900 complicate the program further.
2901
2902 CHAPTER 5.
2903 ---------
2904 5.Hardware Registers.
2905 --------------------
2906 You can get information about hardware functions without using
2907 library functions.You can use the hardware registers instead.These
2908 are memory locations at particular addresses that are neither in
2909 RAM nor in ROM.They are direct interfaces between the processor
2910 and its peripheral devices.
2911 Each device has a number of hardware registers that the processor
2912 accesses to control graphics,sound and input/output.There are lots
2913 of possibilities for assembly language programmers.We'll only be
2914 able to go into a few examples.
2915 The registers are generally used in byte-wise fashion.You'll find
2916 an example in the next chapter.
2917
2918 5.1.Checking For Special Keys.
2919 -----------------------------
2920 Load AssemPro and enter the debugger,select "Parameter-Display-
2921 From-Address"and enter $BFEC00.Next select "Parameter-Display-Hex
2922 -Dump"to display the memory.(To use the SEKA assembler or a similar
2923 monitor program,enter "q $bfec00".)
2924 Yoy'll see a byte-wise listing of the addresses starting at
2925 $BFEC00 in which two bytes always repeat.These two bytes represent
2926 the status of the two hardware registers.
2927 The mirroring occurs because not all the address bits are used in
2928 decoding the address.In addressing this register,only the upper
2929 two bytes of the address and the low bit,bit 0,are used.The
2930 address of the two registers goes like this:$BFECxx,where the
2931 lower address byte xx doesn't contain any information in bits 1-7.
2932 Only bit 0 contains information about the desired register.You'll
2933 find this odd form of addressing with most hardware registers.
2934 Let's look at the information in these registers.Let's look at the
2935 second register,$BFEC01.Hold down the<ALT>key and select"Parameter
2936 -Display-HEX-Dump"to redisplay the screen.(SEKA owners must enter
2937 "q $bfec00"and press the<ALT>key right after pressing the<Return>
2938 key.)You'll see that contents of every two bytes($BFEC01,$BFEC03,
2939 etc...)have been changed to $37.This is the status of the special
2940 keys.This is also true for the other special keys.The following
2941 keys produce the bytes:
2942
2943 Shift left $3F
2944 Shift right $3D
2945 Control $39
2946 Alternate $37
2947 Amiga left $33
2948 Amiga right $31
2949
2950 You can use this register to have a machine language program check
2951 if one of these keys was pressed and then respond by calling or
2952 ending a function.A program section might look like this:
2953
2954 skeys=$bfec01
2955 ...
2956 cmp.b #$37,skeys ;Alternate pressed?
2957 beq function1 ;Yes!
2958 cmp.b #$31,skeys ;or right Amiga?
2959 beq function2 ;Yes!
2960 ... ;and so on...
2961
2962 5.2.Timing.
2963 ----------
2964 If you want to find out how much time elapsed between two events,
2965 you can use a hardware register to keep track of time quickly and
2966 precisely.The Amiga contains just such a timekeeper:the I/O port
2967 componant.The chip has a 24 bit wide counter that has a 60 Hertz
2968 clock.
2969 These 24 bits can't be read at once,for instance with a MOVE.L
2970 command,because the register is divided into three bytes.The low
2971 byte is at address $BFE801,the middle at $BFE901,and the high byte
2972 with bits 16-23 at $BFEA01.
2973 Here's an example of a way to use this register:finding out how
2974 long a subroutine takes to run.
2975
2976 test:
2977 bsr gettime ;put current time in D7
2978 move.l d7,d6 ;save it in D6
2979 bsr routine ;routine to be timed
2980 bsr gettime ;get the time again
2981 sub.l d6,d7 ;elapsed time in
2982 ... ;1/50 seconds in D7!
2983 nop ;set break point here to stop
2984
2985 routine: ;test routine
2986 move #500,d0 ;delay counter
2987
2988 loop:
2989 dbra d0,loop ;count down
2990 rts
2991
2992 gettime:
2993 move.b $bfea01,d7 ;hi-byte in D0
2994 lsl.l #4,d7 ;shift twice by 4 bits
2995 lsl.l #4,d7 ;(8 bits shifted)
2996 move.b $bfe901,d7 ;get mid-byte
2997 lsl.l #4,d7
2998 lsl.l #4,d7 ;shift again
2999 move.b $bfe801,d7 ;get the lo-byte
3000 rts ;done
3001
3002 5.3.Reading The Mouse-Joystick.
3003 -------------------------------
3004 There are two hardware registers for the mouse and the joystick.
3005 They contain the state(or the position)of these input devices.Its
3006 interesting that the same port is used with both the mouse and the
3007 joystick even through they work completely different.
3008 The joystick as four switches that are closed during movement and
3009 give off a potential(-)that is related to the movement of the
3010 joystick/mouse.The mouses movements give off lots of quick signals
3011 -two for horizontal and two for vertical movements.
3012 The computor must keep an eye on the ports so that it can evaluate
3013 the signals and calculate the new mouse position.This isn't the
3014 work of the processor though;it already has too much to do.
3015 You find the status of the mouse/joystick port at address $DFF00A
3016 for port 1 and $DFF00C for port 2.The information in these words
3017 is for vertical mouse movement in the lower byte and for
3018 horizontal movement in the upper byte.
3019 AssemPro owners be careful!Don't read these addresses,because for
3020 some reason that causes the computor to crash.This looks
3021 interesting(the screen begins to dance)but you can only recover by
3022 pressing <RESET>and losing all your data.
3023 To read this register,lets write a short program:
3024
3025 ;(5.3A) mouse
3026
3027 test:
3028 jsr run ;test subroutine
3029 jmp test ;continue until broken
3030 nop ;breakpoint here
3031
3032 joy= $dff00a
3033
3034 run:
3035 move joy,d6 ;data item 1 in D6
3036 move joy+2,d7 ;data item 2 in D7
3037 jmp run ;rts for SEKA and other
3038
3039 end
3040
3041 If you assemble the program and start breakable in the debugger
3042 (SEKA-"j run"),D6 and D7 contain the contents of the two registers
3043 Move the mouse a bit and watch the register contents.
3044 As you see,the value in D6 is different.If you just move the mouse
3045 horizontaly,only the upper bytes value is different,if just moved
3046 vertically only the upper byte is different.
3047 You are not getting the absolute position of the mouse pointer on
3048 the screen.You can see that easily by moving the mouse in the
3049 upper left corner,then reading the value by restarting the program
3050 and moving the mouse left again.As you can see,the registers
3051 contents are always relative.
3052 Change the program as follows:
3053
3054 ;(5.3B) mouse difference
3055
3056 test:
3057 jsr run ;test subroutine
3058 jmp test ;continue until broken
3059 nop ;breakpoint here
3060
3061 joy= $dff00a
3062
3063 run:
3064 move d7,d6 ;old position in D6
3065 move joy,d7 ;new position in D7
3066 sub d7,d6 ;difference in D6
3067 jmp run ;rts for SEKA and other
3068
3069 end
3070
3071 Start Breakable(right-Amiga-A)in the AssemPro debugger and watch
3072 D6,the result is zero or D7.(SEKA owners have to start the program
3073 two times.The result in D6 is zero.)If you move the mouse,D6
3074 contains the difference between the old and new positions since
3075 the start.You'll find the vertical and horizontal positions of the
3076 mouse relative to the last time you looked.In this way,you can use
3077 this register to find the relative mouse movement between two
3078 checks.
3079 Now to check the joysticks.Put a joystick in port 2 and change the
3080 address $DFF00A to $DFF00C in the program.Start Breakable in the
3081 AssemPro debugger and watch D6,the result is zero or D7.(SEKA
3082 owners have to start the program two times.The result in D6 is
3083 zero.)
3084 Move the joystick up.You'll get the value $FF00.One was subtracted
3085 from the upper byte.Let the joystick loose.This time you get the
3086 value $100-one is added.You'll get the same effect if you move the
3087 joystick left-after you let go,one is subtracted.
3088 The individual movements and their effects on the joystick program
3089 are:
3090
3091 UP $FF00 HI-BYTE -1
3092 DOWN $FFFF LO-BYTE -1
3093 LEFT $0100 HI-BYTE +1
3094 RIGHT $0001 LO-BYTE +1
3095
3096 These values aren't terribly reliable.If you move the joystick a
3097 lot and then look at the value,you'll find a crazy value in D6.
3098 This is because the input driver thinks that a mouse is attached.
3099 Nevertheless,this is the quickest way to read a joystick.In this
3100 way,an external device that gives off evaluatable TTL signals can
3101 be connected to the port and watched by a machine language
3102 program.
3103 Now you just need to find out whether the fire button has been
3104 pressed,and you'll know how to get all the information you need
3105 from the joystick.The buttons state is in bit 7 of the byte that
3106 is in memory location $BFE001.If the bit is set,the button was'nt
3107 pressed.That's true for the joystick connected to port 2.Bit 6 of
3108 this byte contains the buttons state when the joystick is in port
3109 1 or the state of the left mouse button.
3110 Let's stay on port 2.You can test bit 7 to execute a function when
3111 the joystick button is pressed without any problems.Bit 7 is the
3112 sign bit.You can use this program segment:
3113
3114 tst.b $bfe001 ;was fire button 2 hit?
3115 bpl fire ;yes!branch
3116
3117 The TST.B instruction tests the addressed byte and sets the Z and
3118 the N flag.If the N flag is set,you know that bit 7 of the tested
3119 byte is set.Since the fire button turns on LO potential,the bit is
3120 erased when the button is pressed.The N flag works that way with
3121 the TST command as well.The BPL command in the program above
3122 branches if the button was pressed.The PL stands for plus and is
3123 set when the sign bit is cleared.
3124 Here is the complete program to check the fire button and joystick
3125 difference:
3126
3127 ;(5.3C) fire button and joy difference
3128
3129 test:
3130 jsr run ;test subroutine
3131 tst.b $bfe001 ;was fire button 2 hit?
3132 bpl fire ;yes! branch
3133 jmp test ;continue until broken
3134
3135 joy = $dff00a
3136 run:
3137 move d7,d6 ;old position in D6
3138 move joy,d7 ;new position in D7
3139 sub d7,d6 ;difference in D6
3140 jmp run ;rts for SEKA and other
3141
3142 fire:
3143 nop ;breakpoint here
3144
3145 end
3146
3147 5.4.Tone Production.
3148 -------------------
3149 It's fun to make noises and sounds.The Amiga lets you use Audio
3150 Devices and various I\O structures to play tones,noises and/or
3151 music pieces in the background.You'll leave this method to C or
3152 Basic programmers,since you can use short machine language
3153 programs to directly program the audio hardware.
3154 The Paula chip has all the capabilities needed for tone production
3155 This chip can be accessed using the hardware registers of the
3156 processor.No library of any high level language can do more than
3157 you can-program the chip.
3158 How does it work?Since the disk uses Direct Memory Access(DMA)to
3159 get information,you just need to tell it where to look for the
3160 tone or tone sequences that you would like played.You also need to
3161 tell it how to interpret the data.
3162 Lets start with the easiest case-producing a constant tone.A tone
3163 like this consists of a single oscillation that is repeated over
3164 and over.If you make a diagram of the oscillation,you see the wave
3165 form of the oscillation.There are several standard waves: sine,
3166 square,triangle and saw tooth.The simplest is the square wave.
3167 To produce a square wave,you just need to turn the loud speaker on
3168 and off.The frequency that occurs here is the frequency of the
3169 tone.
3170 You want to produce such a tone using the Amiga.First you need to
3171 make a table that contains the amplitude of the tone you wish to
3172 produce.For a square wave,you only need two entries in the table,a
3173 large and a small value.Since the sound chip in the Amiga has
3174 amplitude values between -128 and +127,our table looks like this:
3175
3176 soundtab:
3177 dc.b -100,100
3178
3179 You need to give the address of the table to the sound chip.You
3180 have four choices,since the Amiga as four sound channels.The
3181 address of the hardware register in which the table address for
3182 channel 0 must be written is $DFF0A0;for channel 1 it is $DFF0B0;
3183 for channel 2 its $DFF0C0;for channel 3 its $DFF0D0.For stereo
3184 output,channels 0 and 3 control the left loud speaker.Channels 1
3185 and 2 control the right loud speaker.For example,choose channel 0
3186 and write the following:
3187
3188 move.l #soundtab,$DFF0A0 ;address of the table
3189
3190 Next you need to tell the sound chip how many items there are in
3191 the table.The data is read from beginning to end and sent to the
3192 loud speaker.Once it reaches the end,it starts over at the
3193 beginning.Since the sound chip gets this one word at a time,even
3194 though the data is in bytes,the table must always have an even
3195 number of bytes.The length that you give it is the number of words
3196 the number of bytes/2.
3197 You put the length for channel 0 in the register at address
3198 $DFF0A4(for channel x just add x*$10!):
3199
3200 move #1,$dff0a4 ;length of table in words
3201
3202 Now you have to tell it how quickly to read the data and output it
3203 to the loud speaker.This word determines the frequency.However,it
3204 does this "backwards".The larger the value,the lower the frequency
3205 Choose the value 600 for this example:
3206
3207 move #600,$dff0a6 ;read in rate
3208
3209 Now you need to decide the loudness level for the tone or noise.
3210 You have 65 different levels to choose from.Lets choose the middle
3211 value 40 for our example:
3212
3213 move #40,$dff0a8 ;loudness level
3214
3215 Thats the data that the sound chip needs to produce the tone.
3216 However nothing happens yet.What next?The chip can't tell if the
3217 data thats in the registers is valid,so it doesn't know if it
3218 should use the data.
3219 You need to work with the DMA control register at address $DFF096
3220 to let it know.You only need six bits of this word for your
3221 purposes:
3222
3223 Bit 15 ($8000) If this bit is set,every bit that is written to
3224 this internal register is set.Otherwise the bits
3225 are erased.Zero bits aren't affected.This is very
3226 useful because this word also contains DMA
3227 information for disk operations that should'nt be
3228 changed.
3229
3230 Bit 9 ($200) This bit makes it posible for the chip to access
3231 DMA memory.If you want to start playing the tone,
3232 you need to set this bit.
3233
3234 Bit 0-3 Turn channel 0-3 on when bits are set.
3235
3236 You'll start your tone by setting bits 15,9 and 0:
3237
3238 move #$8000+$200+1,$dff096 ;start DMA
3239
3240 Heres an example of tone production-this time with tone using a
3241 sine wave:
3242
3243 ;**Sound Generation using hardware registers** (5.5A)
3244
3245 ctlw = $dff096 ;DMA control
3246 cothi = $dff0a0 ;table address HI
3247 c0tlo = $c0thi+2 ;table address LO
3248 c0tl = $c0thi+4 ;table length
3249 c0per = $c0thi+6 ;read in rate
3250 c0vol = $c0thi+8 ;loudness level
3251
3252 run: ;*Produce a simple tone
3253 move.l #table,c0thi ;table beginning
3254 move #8,c0tl ;table length--8 words
3255 move #400,c0per ;read in rate
3256 move #40,c0vol ;loudness level (volume)
3257 move #$8201,ctlw ;DMA/Start sound
3258 rts
3259
3260 data ;>500K place in CHIP memory
3261 table: ;sound table:sine
3262 dc.b -40,-70,-40,0,40,70,40,0
3263
3264 end
3265
3266 To test this subroutine,use AssemPro to assemble the routine,save
3267 the program and load it into the debugger.Next set a breakpoint at
3268 the RTS,to set the breakpoint in AssemPro select the correct
3269 address with the mouse and press the right-Amiga-B keys.Start the
3270 program and listen to the tone.You need another routine to turn
3271 the tone off,turn your sound down for now.
3272 To turn the tone off,you just need to erase bit 0 of the DMA
3273 control register.To do this,you just need to write a 0 in bit 15
3274 and all the set bits in this register are erased.To erase bit 0,
3275 just write a one to the memory location:bit 15=0=> bit 0 is erased
3276 Heres a small routine to stop the tone coming from channel 0:
3277
3278 still: ;*turn off tone
3279 move #1,ctlw ;turn off channel 1
3280 rts
3281
3282 Now lets use the routine in a program to produce a short peep tone
3283 that you culd,for instance,use as a key click:
3284
3285 ;** Producing a Peep Tone **
3286 ctlw = $dff096 ;DMA control
3287 c0thi = $dff0a0 ;HI table address
3288 c0tlo = $c0thi+2 ;LO table address
3289 c0tl = $c0thi+4 ;table length
3290 c0per = $c0thi+6 ;read in rate
3291 c0vol = $c0thi+8 ;volume
3292
3293 beep: ;*Produce a short peep tone
3294 move.l #table,c0thi ;table beginning
3295 move #8,c0tl ;table length
3296 move #400,c0per ;read in rate
3297 move #65,c0vol ;volume
3298 move #$8201,ctlw ;Start DMA (sound)
3299 move.l #20000,d0 ;delay counter
3300
3301 loop:
3302 dbra d0,loop ;count down
3303
3304 still:
3305 move #1,ctlw ;turn off tone
3306 rts
3307
3308 table:
3309 dc.b 40,70,90,100,90,70,40,0,-4,0
3310 end
3311
3312 You can play upto four tones at the same time in such a way that
3313 they are independant of each other.The Amiga also offers another
3314 method of making the sound more interesting:you can modulate the
3315 tone.
3316 Lets produce a siren tone.You could do this by figuring out the
3317 entire sequence and programming it.However,as you can well imagine
3318 thats a lot of work.
3319 Its much easier to use two tone channels.Lets use channel 1 for
3320 the bass tone and channel 0 for its modulation.Channel 0 needs to
3321 hold the envelope of the siren tone.It needs to give the expanding
3322 and contracting of the tone at the right speed.
3323 You then have two ways that you can have channel zero work with
3324 channel one.You can control the volume via channel 0,the read in
3325 rate(frequency),or both.For our example,you'll use frequency
3326 modulation.
3327
3328 Change the program as follows:
3329
3330 ;** Modulated sound generation via hardware registers **
3331 ctlw = $dff096 ;DMA control
3332 adcon = $dff09e ;Audio/Disk control
3333 c0thi = $dff0a0 ;HI table address
3334 c0tlo = c0thi+2 ;LO table address
3335 c0tl = c0thi+4 ;table length
3336 c0per = c0thi+6 ;read in rate
3337 c0vol = c0thi+8 ;volume
3338
3339 run:
3340 move.l #table,c0thi+16 ;table start for channel 1
3341 move #8,c0tl+16 ;table length--8 words
3342 move #300,c0per+16 ;read in rate
3343 move #40,c0vol+16 ;volume
3344
3345 move.l #table2,c0thi ;table start for channel 0
3346 move #8,c0tl ;table length
3347 move #60000,c0per ;read in rate
3348 move #30,c0vol ;volume
3349
3350 move #$8010,adcon ;modulation mode:FM
3351 move #$8203,ctlw ;start DMA
3352 rts
3353
3354 still: ;*Turn Off Tone
3355 move #$10,adcon ;no more modulations
3356 move #3,ctlw ;turn off channels
3357 rts
3358
3359 table: ;data for basic tone
3360 dc.b -40,-70,-90,-100,-90,-70,-40,0
3361 dc.b 40,70,90,100,90,70,40,0
3362
3363 table2: ;data for modulation
3364 dc.w 400,430,470,500,530,500,470,430
3365
3366 end
3367
3368 When you start the program,you'll here a siren.You can change this
3369 tone to your hearts content.
3370 Did you notice the added "adcon"register.This register controls
3371 the modulation of the audio channel as well as handling disk
3372 functions.The same technique is used here as for the DMA control
3373 register,bits can only be set if bit 15 is.As a result,you don't
3374 have to worry about the disk bits.I'd recommend against
3375 experimentation.
3376 Control bit 15 isn't the only one of interest to you.You can also
3377 use bits 0-7,because they determine which audio channel modulates
3378 another channel.There is a restriction,though.A channel can only
3379 modulate the next higher numbered channel.For this reason you use
3380 channel 1 for the basic tone and channel 0 for the modulation in
3381 the example.You can't for example,modulate channel three with
3382 channel zero.Channel 3 can't be used to modulate any other
3383 channel.
3384
3385 Here is an overview of bits 0-7 of the "adcon"register.
3386
3387 Bit Function
3388 -----------------------------------------------------------------
3389 0 Channel 0 modulates the volume of channel 1
3390 1 Channel 1 modulates the volume of channel 2
3391 2 Channel 2 modulates the volume of channel 3
3392 3 Turn of channel 3
3393 4 Channel 0 modulates the frequency of channel 1
3394 5 Channel 1 modulates the frequency of channel 2
3395 6 Channel 2 modulates the frequency of channel 3
3396 7 Turn off channel 3
3397
3398 In the example,you set bit 4,which put channel 0 in charge of
3399 channel one's frequency modulations.
3400 When you've chosen a channel for use in modulating another channel
3401 some of the parameters of the channel change.You don't need to
3402 give volume for this channel,so you can omit it.Now the tables
3403 data is looked at as words instead of as bytes.These words are
3404 read into the register of the modulated register at a
3405 predetermined rate.The Read in Rate Register determines the rate.
3406 If you want to modulate the frequency and the volume of another
3407 channel,(In the example,set bits 0 and 4 of "adcon"),the data is
3408 interpreted a little differently.The first word in the table is
3409 the volume,the second is the read in rate,and so on.It alternates
3410 back and forth.In this way,you can for instance,produce the siren
3411 tone.
3412
3413 5.5.Hardware Registers Overview.
3414 -------------------------------
3415 The following tables should give you an overview of the most
3416 important hardware registers.Theres not enough room to describe
3417 each register,so I'd recommend getting a hold of the appropriate
3418 literature.If you experiment with these registers,you should keep
3419 in mind that this can cause the computor to crash.Save your data
3420 to disk and then take the disk out of the drive,because you might
3421 cause the disk drive to execute some wierd functions.
3422 Lets start with the PIA's.This covers the PIA type 8520.You should
3423 keep in mind that some functions and connection of the 8520 are
3424 integrated into the Amiga and so there are limitations on what you
3425 can do with the PIA's.
3426
3427 PIA A PIA B Registers Meaning
3428 ------------------------------------------------------------------
3429 BFE001 BFE000 Data register A
3430 BFE101 BFE100 Data register B
3431 BFE201 BFE200 Data direction register A
3432 BFE301 BFE300 Data direction register B
3433 BFE401 BFE400 Timer A LO
3434 BFE501 BFE500 Timer A HI
3435 BFE601 BFE600 Timer B LO
3436 BFE701 BFE700 Timer B HI
3437 BFE801 BFE800 Event register Bits 0-7
3438 BFE901 BFE900 Event register Bits 8-15
3439 BFEA01 BFEA00 Event register Bits 16-23
3440 BFEB01 BFEB00 Unused
3441 BFEC01 BFEC00 Serial data register
3442 BFED01 BFED00 Interrupt control register
3443 BFEE01 BFEE00 Control register A
3444 BFEF01 BFEF00 Control register B
3445
3446 Some internal meanings:
3447
3448 $BFE101 Data register for parallel interface
3449 $BFE301 Data direction register for the parallel interface
3450 $BFEC01 State of the keyboard,contains the last special key
3451 pressed(Shift,Alternate,Control,Amiga)
3452
3453 Now come the registers that are used for tone production.The first
3454 two registers should be treated especially carefully-if they are
3455 used wrong,very nasty effects can occur.
3456 These registers can be either read or written only.This
3457 information is included under R/W in the table.
3458
3459 Address R/W Meaning
3460 ------------------------------------------------------------------
3461 DFF096 W Write DMA Control
3462 DFF002 R Read DMA Control and Blitter Status
3463 --Audio Channel 0--
3464 DFF0AA W Data register
3465 DFF0A0 W Pointer to table beginning Bits 16-18
3466 DFF0A2 W Pointer to table beginning Bits 0-15
3467 DFF0A4 W Table length
3468 DFF0A6 W Read in Rate
3469 DFF0A8 W Volume
3470 --Audio Channel 1--
3471 DFF0BA W Data register
3472 DFF0B0 W Pointer to table beginning Bits 16-18
3473 DFF0B2 W Pointer to table beginning Bits 0-15
3474 DFF0B4 W Table length
3475 DFF0B6 W Read in Rate
3476 DFF0B8 W Volume
3477 --Audio Channel 3--
3478 DFF0CA W Data register
3479 DFF0C0 W Pointer to table beginning Bits 16-18
3480 DFF0C2 W Pointer to table beginning Bits 0-15
3481 DFF0C4 W Table length
3482 DFF0C6 W Read in Rate
3483 DFF0C8 W Volume
3484 --Audio Channel 4--
3485 DFF0DA W Data register
3486 DFF0D0 W Pointer to table beginning Bits 16-18
3487 DFF0D2 W Pointer to table beginning Bits 0-15
3488 DFF0D4 W Table length
3489 DFF0D6 W Read in Rate
3490 DFF0D8 W Volume
3491
3492 Now for the registers that contain information about the joystick,
3493 mouse or potentiometer.These addresses have been gone over in part
3494 previously.
3495
3496 Address R/W Meaning
3497 ------------------------------------------------------------------
3498 DFF00A R Joystick/Mouse Port 1
3499 DFF00C R Joystick/Mouse Port 2
3500 DFF012 R Potentiometer pair 1 Counter
3501 DFF014 R Potentiometer pair 2 Counter
3502 DFF018 R Potentiometer connection
3503 DFF034 W Potentiometer port direction
3504
3505
3506
3507
3508 Chapter 6
3509 ---------
3510 6.The Operating System.
3511 -----------------------
3512 Now lets take a step forward in your ability to write assembly
3513 language programs.Its not enough to put a piece of text in memory
3514 someplace.You want to be able to put it on the screen.Do you know
3515 how to write a character on the screen?Do you know how to draw a
3516 window on the screen that can be modified by the mouse?Actually
3517 you don't have to have terribly precise knowledge about such
3518 topics.
3519 Fortunately,the Amigas operating system supplies routines that
3520 take care of common tasks like this.It can seem quite complicated
3521 due to the number of routines necessary.These routines are in
3522 libraries.We'll look at the libraries in some depth now.
3523
3524 6.1.Load Libraries.
3525 -------------------
3526 Before you can use a library,it must be available.It has to be
3527 loaded into memory.Unfortunately,the whole library must be loaded,
3528 even if you only need one of the functions.
3529 First you need to decide what the program must be able to do,so
3530 you can see which libraries you'll need.For simple I/O text,you
3531 don't need a library that contains routines for moving graphics!
3532 There are a number of libraries onj a normal Workbench disk.Heres
3533 an overview of the names and the sort of functions they do:
3534
3535 Exec.Library;
3536 This library is needed to load the other libraries.It is already
3537 in memory and doesn't need to be loaded.Its in charge of basic
3538 functions like reserving memory and working with I/O channels.
3539
3540 Dos.Library;
3541 Contains all the functions for normal I/O operations,for instance
3542 screen or disk access.
3543
3544
3545 Intuition.Library;
3546 Used for working with screens,windows,menus,etc...
3547
3548 Clist.Library;
3549 This contains routines for working with the Copper lists that are
3550 used for controlling the screen.
3551
3552 Console.Library;
3553 Contains graphics routines for text output in console windows.
3554
3555 Diskfont.Library;
3556 Used for working with the character fonts that are stored on the
3557 disk.
3558
3559 Graphics.Library;
3560 This library contains functions to control the Blitter(or graphics
3561 )chip.Its used for basic graphics functions.
3562
3563 Icon.Library;
3564 Used in the development and use of workbench symbols(icons).
3565
3566 Layers.Library;
3567 Used for working with screen memory (layers).
3568
3569 Mathffp.Library;
3570 Contains basic math floating point operations.
3571
3572 Mathieeedoubbas.Library;
3573 Contains basic math functions for integers.
3574
3575 Mathtrans.Library;
3576 Contains higher level mathmatical functions.
3577
3578 Potgo.Library;
3579 Used for evaluating analog input to the Amiga.
3580
3581 Timer.Library;
3582 Contains routines for time critical programs.They can be used to
3583 program exact time intervals.
3584
3585 Translator.Library;
3586 Contains the single function "Translate",that translates normal
3587 text written phonetically for the narrator,the speech synthesisor.
3588
3589 You can open(load)all these libraries of course.You should
3590 remember that this takes time and memory.For this reason,you
3591 should always think about which functions you need and which
3592 libraries they are in.
3593 For example,lets say you want to write a program that does text
3594 input/output.You need the "Dos.Library",so it can be loaded.
3595 The "exec.library"is in charge of loading.This library contains
3596 the OpenLib function that can be called once you've passed the
3597 needed parameters.AssemPro Amiga includes all the libraries
3598 necessary for the Amiga,it also includes files that contain the
3599 offsets for the operating system calls.The macros contained in
3600 AssemPro ease assembly language programming considerably.To make
3601 the programs in this book useful to the largest audience the
3602 following examples are written for generic assemblers and do not
3603 include AssemPro's macros.We have used the AssemPro ILABEL and the
3604 macros INIT_AMIGA and EXIT_AMIGA so AssemPro owners can start the
3605 programs from the desktop.(If you are using a different assembler
3606 check your documentation for instructions on linking programs).
3607
3608 6.2.Calling Functions.
3609 ----------------------
3610 Since this chapter is rather complex we'll first describe the
3611 fundamental routines necessary to use the Amiga's operating system
3612 after a description a complete program is listed.Every library
3613 begins in memory with a number of JMP commands.These JMPs branch
3614 to the routines that are in the library.To call a function,you
3615 need to find the beginning of this JMP table and call function x
3616 by going to the xth JMP command.Usually you use an offset to get
3617 to the right JMP command.Normally,you don't start at the beginning
3618 but at the end of the JMP table,so use negative offsets.
3619 It works out very easily.Now lets open the "dos.library"by using
3620 "exec.library's"base address.This address is $000004.To call a
3621 fuction from another library,you need to use another base address.
3622 Now you need the offset for the function that you want.You want
3623 the OpenLib function that has -408 as an offset.You'll find a list
3624 of function offsets in the appendix.
3625 You need a pointer to the name of the library you are loading for
3626 the OpenLib function(in this case "dos.library")and a long word in
3627 memory that you can use to store the base address of the DOS
3628 library.You get this back from the OpenLib function.You need to be
3629 sure to write the library name in lower case letters(dos.library),
3630 otherwise you can't open it.I entered a name in capitol letters
3631 once and spent a lot of time finding this error.
3632
3633 The routine looks like this:
3634
3635 ;** Load the DOS library 'dos.library' (6.2A) **
3636 Execbase = 4 ;base address of the EXEC library
3637 OpenLib = -408 ;offset for the OpenLib function
3638
3639 IoErr = -132 ;offset for IoErr information
3640
3641 init:
3642 move.l Execbase,a6 ;base address in A6
3643 lea dosname,a1 ;address of library name
3644 moveq #0,d0 ;version number
3645 jsr OpenLib(a6) ;open DOS library
3646 move.l d0,dosbase ;save DOS base address
3647 beq error ;if zero,then error!
3648 ... ;your program goes here
3649 ... ;more program...
3650
3651
3652 error: ;error
3653 move.l dosbase,a6 ;address of library name
3654 jsr IoErr(a6) ;call IoErr for error info
3655 move.l d0,d5
3656 ... ;your error routine goes here
3657 rts
3658
3659
3660 dosname: ;name of library to open
3661 dc.b 'dos.library',0,0
3662 align ;SEKA uses-even
3663
3664 dosbase: ;storage for DOS base address
3665 blk.l 1
3666
3667 end
3668
3669 This is the way to load the DOS library so that you can use it.All
3670 library functions are called this way.Parameters are put in
3671 registers and passed to the function.When there is an error,when
3672 the function doesn't run correctly,a zero is usually put in data
3673 register D0.
3674 Once your program is done with its work,you need to close the
3675 libraries that are still open before you return to the CLI or
3676 Workbench.The CloseLib function (offset -414)takes care of this
3677 job.This function is in the EXEC library just like the OpenLib.The
3678 only parameter it needs is the base address of the library that is
3679 closed.To close "dos.library",do the following:
3680
3681 CloseLib = -414 ; (6.2B)
3682 ...
3683 move.l Execbase,a6 ;EXEC base address
3684 move.l dosbase,a1 ;DOS base address
3685 jsr CloseLib(a6) ;close library
3686
3687 6.3.Program Initialization.
3688 ---------------------------
3689 Before you can start a program,you need to initialize many things
3690 so that the program can run.
3691 Lets take an example program that does some text editing.A program
3692 like this must be able to store text,so it needs to be able to
3693 access memory.It also needs to be able to accept keyboard input
3694 and do screen output,so it needs an output window.
3695 To do this,you need to open one or more of the libraries that we
3696 talked about earlier.Lets assume that you've loaded the DOS
3697 library,so that you can do the next steps.
3698
3699 6.3.1.Reserve Memory.
3700 ---------------------
3701 There are several ways to get the operating system to assign you a
3702 chunk of memory.You need to use one of them,so that during multi-
3703 tasking,you don't have one program overwriting another programs
3704 memory area.
3705 Lets look at the function that is normally used.This function is
3706 in the resident EXEC library and has the name AllocMem (offset
3707 -$c6).It reserves a memory area,using the value in D0 as the
3708 length.The address that the memory area begins at is returned in
3709 the D0 data register.If it returns zero,the program could'nt give
3710 you that much memory.
3711 You can also use a mode word in D1 to determine whether the memory
3712 area that is reserved should be erased or not.
3713 The routine looks like this:
3714
3715 ExecBase = 4 ; (6.3.1A)
3716 AllocMem = -$c6
3717 ...
3718 move.l #number,d0 ;number of bytes to reserve
3719 move #mode,a6 ;mode word
3720 move.l ExecBase,a6 ;DOS base address in A6
3721 jsr AllocMem(a6) ;call function
3722 move.l d0,address ;save memory's start address
3723 beq error ;memory not reserved
3724 ...
3725
3726 The second way to reserve memory is to use the AllocAbs function
3727 (offset -$CC).This function in contrast to the AllocMem function
3728 reserves a particular memory area.The D0 register contains the
3729 number of bytes that should be reserved.Address register A1
3730 contains the desired start address.This function returns a zero in
3731 D0 if the memory area can't be reserved.
3732
3733 ExecBase = 4 ; (6.3.1B)
3734 AllocAbs = -$cc
3735 ...
3736 move.l #number,d0 ;number of bytes to reserve
3737 lea address,a1 ;desired start address
3738 move.l execbase,a6 ;EXEC base address
3739 jsr AllocAbs(a6) ;reserve memory
3740 tst.l d0 ;everything ok?
3741 beq error ;no!
3742 ...
3743
3744 When the program has done its work and must return to the CLI or
3745 the Workbench,it needs to return the memory it as reserved to the
3746 system.The FreeMem function (offset -$D2) handles this.
3747 The function works like AllocAbs in that the number of bytes is
3748 put in D0 and the start address of the memory area is put in A1.
3749 If you try to free up a memory area that was'nt reserved,you'll
3750 usually crash the computor.
3751 The routine to free up a memory area looks like this:
3752
3753 ExexBase = 4 ; (6.3.1C)
3754 FreeMem = -$d2
3755 ...
3756 move.l #number,d0 ;number of bytes released
3757 lea address,a1 ;start address from AllocAbs
3758 move.l ExecBase,a6 ;ExecBase address
3759 jsr FreeMem(a6) ;free up memory
3760 tst.l d0 ;everything ok?
3761 beq error ;no!
3762 ...
3763
3764 6.3.2.Opening a Simple Window.
3765 ------------------------------
3766 The title of this chapter may sound a bit strange.However,the
3767 differences between the two different methods of opening a window
3768 are so great that they should be handled in seperate chapters.
3769 The method of opening a window presented here is very simple,but
3770 it doesn't allow you to work with all the gadgets.These gadgets
3771 include the close symbol in the upper left corner of a window and
3772 the size symbol in the lower left corner.
3773 If you open the window in the simple manner,almost all the gadgets
3774 are present.However,the close symbol is not.As a result,this
3775 method isn't appropriate for every application.Now lets look at
3776 the method.
3777 To open a window,use a function from the DOS library,so you need
3778 to open the library first (see the section "Load Library").This
3779 open function is an all purpose function that can be used for many
3780 things.For this reason,it makes good sense to put a "open"
3781 subroutine in your program.You can use it a lot.Lets do the basic
3782 steps:
3783
3784 ;** Load the DOS Library 'dos.library' (6.3.2A) **
3785 ExecBase = 4 ;base addres of the EXEC library
3786 OpenLib = -408 ;offset of OpenLib function
3787 Open = -30 ;Offset of the DOS function OPEN
3788
3789 init:
3790 move.l ExecBase,a6 ;base address in A6
3791 lea dosname(pc),a1 ;address of library name
3792 move.q #0,d0 ;version number:unimportant
3793 jsr OpenLib(a6) ;call the function
3794 move.l d0,dosbase ;save DOS base address
3795 beq error ;if zero,then error!
3796 ... ;more of your program
3797 ... ;now open window,etc...
3798
3799
3800 error:
3801 ... ;error occured
3802 ... ;your error routine
3803
3804
3805 openfile: ;general open function
3806 move.l dosbase,a6 ;DOS base address in A6
3807 jsr Open(a6) ;call OPEN function
3808 tst.l d0 ;test if ok
3809 rts ;done,evaluate test later
3810
3811 dosname: ;name of library to be opened
3812 dc.b 'dos.library',0,0
3813 align ;even
3814
3815 dosbase: ;spot for DOS base address
3816 blk.l 1
3817
3818 You call the Openfile routine,because the label "Open"is already
3819 being used for the offset.This routine calls the Open function
3820 that is in the DOS library.
3821 This isn't everything.The function must be given some parameters
3822 so that it knows what to open.The parameters are sent in registers
3823 D1 and D2.D1 points to a definition block what specifies what
3824 should be opened.You need to have a filename ended with a null
3825 byte there.D1 must be passed as a long word like all addresses.D2
3826 contains the mode that the function should run in.There is an old
3827 (1005) and a new (1006) mode.This number must be passed in D2's
3828 long word.
3829 Heres an overview of how windows are opened.Fortunately,AmigaDos
3830 allows you to use input and output channels in the same way.The
3831 standard channels are disk files,the console (keyboard and screen)
3832 the printer interface and the serial RS232 interface.
3833 The console input/output is what you'll work with now.When you
3834 specify the console as the filename of the channel to be opened,a
3835 window is opened automatically.
3836 The name must begin with CON:to do this.Its similar to DF0:for
3837 disk operations.A little more infotmation about the window is
3838 still needed.
3839 You need to specify the X and Y coordinates of the upper left and
3840 lower right corners of the window as well as the name that should
3841 appear in the title line of the window.A complete definition block
3842 for a window like this would appear like the following line:
3843
3844 consolname: dc.b 'CON:0/100/640/100/**Window**',0
3845
3846 To open this window,the line above needs to be inserted in the
3847 following program:
3848
3849 mode_old = 1005
3850
3851 lea consolname(pc),a1 ;consol definition
3852 move.l #mode_old,d0 ;mode
3853 bsr openfile ;console open
3854 beq error ;didn't work
3855 move.l d0,conhandle
3856
3857 rts
3858 ...
3859 conhandle: dc.l 1 ;space for handle
3860
3861 There are two points to clear up yet.
3862 You should use mode_old as the the mode when you open a window.
3863 Logically the window doesn't exist before opening so this seems
3864 wierd but it doesn't hurt anything.
3865 The parameter that returns from "openfile"in D0 is zero in the
3866 case of an error,in the case that opening didn't work.Otherwise
3867 the value is the identification number (handle number) of the
3868 opened channel.You need to store it away,because every function
3869 that wants to use this channel must give the handle number.In the
3870 example,you stored this number in the "conhandle"long word.
3871 As mentioned,the window you've opened doesn't have a close symbol
3872 but it can be made bigger and smaller and moved forward and back.
3873 The manipulations that are carried out using the mouse are
3874 completely taken care of by the Amiga (in contrast to the ATARI ST
3875 where the programmer has to take care of these things).
3876 An important function that uses the handle number is the one that
3877 closes the channel (in your case the window).This function is also
3878 in the DOS library and is called "Close".Its offset is -36 and it
3879 only needs one parameter;the handle number of the channel that is
3880 closed must be in the D1 register.
3881 After your work is done,you need to put the following lines in
3882 your program to close the window:
3883
3884 Close = -36 ; (6.3.2C)
3885 ...
3886 move.l conhandle,d1 ;handle number in D1
3887 move.l dosbase,a6 ;DOS base address in A6
3888 jsr Close(a6) ;close channel!
3889
3890 The window disappears!
3891
3892 Now for a few remarks about opening and closing the window in this
3893 way.If you open several windows in the same way,you'll get several
3894 windows and thus several handle numbers.In this way,you can put as
3895 many windows on the screen as you like.You can do your work with
3896 them and close them individually.
3897 Here is the complete program to open and close a simple window in
3898 AssemPro format (We have used the AssemPro ILABEL and the macros
3899 INIT_AMIGA and EXIT_AMIGA so AssemPro owners can start the program
3900 from desktop.If you are using a different assembler check your
3901 documentation for instructions on starting and exiting programs):
3902
3903 ;***** 6.3.2 S.D *****
3904
3905 OpenLib =-30-378
3906 closelib =-414
3907 ;execbase =4 ;defined in AssemPro macros
3908
3909
3910 *calls to Amiga DOS:
3911
3912 open =-30
3913 close =-30-6
3914 IoErr =-132
3915 mode_old = 1005
3916 alloc_abs =-$cc
3917
3918 ILABEL AssemPro:includes/Amiga.l ;AssemPro only
3919
3920 INIT_AMIGA ;AssemPro only
3921
3922 run:
3923 bsr init ;initialization
3924 bra test ;system-test
3925
3926 init: ;system initialization and open
3927 move.l execbase,a6 ;number of execute-library
3928 lea dosname(pc),a1
3929 moveq #0,d0
3930 jsr openlib(a6) ;open DOS-Library
3931 move.l d0,dosbase
3932 beq error
3933
3934 lea consolname(pc),a1 ;consol definition
3935 move.l #mode_old,d0
3936 bsr openfile ;consol open
3937 beq error
3938 move.l d0,conhandle
3939
3940 rts
3941
3942 test:
3943
3944 bra qu ;quit and exit
3945
3946
3947 error:
3948 move.l dosbase,a6
3949 jsr IoErr(a6)
3950 move.l d0,d5
3951
3952 move.l #-1,d7 ;flag
3953
3954 qu:
3955 move.l conhandle,d1 ;window close
3956 move.l dosbase,a6
3957 jsr close(a6)
3958 move.l dosbase,a1 ;DOS.Lib close
3959 move.l execbase,a6
3960 jsr closelib(a6)
3961
3962 EXIT_AMIGA ;AssemPro only
3963
3964 openfile: ;open file
3965 move.l a1,d1 ;pointer to I/O-Definition-Text
3966 move.l d0,d2
3967 move.l dosbase,a6
3968 jsr open(a6)
3969 tst.l d0
3970 rts
3971
3972 dosname: dc.b 'dos.library',0,0
3973 Align.w
3974
3975 dosbase: dc.l 0
3976
3977 consolname: dc.b 'CON:0/100/640/100/**CLI-Test**',0
3978 Align.w
3979
3980 conhandle: dc.l 0
3981
3982
3983 end
3984
3985 There is another way to open a window easily.Just use RAW:instead
3986 of CON:as the channel designator.All the other parameters and
3987 operations remain the same.
3988 If you try them both out,you won't see any differences between the
3989 two windows.They both look the same and can be worked with in the
3990 same way with the mouse.The difference comes when you input to the
3991 window.In the RAW:window,the cursor keys are ignored.In the CON:
3992 window and in CLI,they do work.
3993
3994 6.4.Input/Output.
3995 -----------------
3996 Besides managing and making calculations with data,the most
3997 important work of a program is to input and output the data.There
3998 are many methods of data transfer in and out of the computor,for
3999 instance screen or printer output,keyboard input,using the serial
4000 or the parallel interface,tone or speech output and finally disk
4001 operations.
4002 You want to learn about all these methods of data input and output
4003 for programming and applications.We've written some programs as
4004 subroutines that should be useful for later programs.It makes good
4005 sense to make a library of these subroutines that can either be
4006 directly integrated in a new program or linked to a program.At the
4007 end of the sections there is a list of a complete program so you
4008 can see how the subroutines are used.
4009 To prepare for input/output,you need to have data to output and
4010 space to input data.To get this ready,you need a correct program
4011 beginning in which the EXEC and DOS libraries are opened and
4012 memory is reserved.After this,you begin most programs by outputing
4013 some text.The text can be a program title or the instruction to
4014 input data over the keyboard.Lets start looking at screen output.
4015
4016 6.4.1.Screen Output.
4017 --------------------
4018 For a computor like the Amiga the first question is where should
4019 the screen output be sent?The answer is simple for many computors;
4020 they only have one screen,and output goes there.You need to
4021 specify which window to write to when you use the Amiga,however.
4022
4023 There are two possibilites:
4024
4025 1.Output to CLI
4026
4027 2.Output to another window
4028
4029 The first posibillity only exists if the program that makes the
4030 output was started from CLI.If not,you need to open your own
4031 custom window for your program.If so,you can use the window that
4032 was opened by the CLI for output.
4033 If you use the second method,you need to open a window.As you've
4034 already seen,there are three methods.For simple text and character
4035 output,the difference between the three sorts of windows isn't
4036 very great.Here you have a free hand in determining which sort of
4037 window to use.Lets open a CON:window and put its handle number in
4038 "conhandle".
4039 You've opened your window and want to output a title.You choose
4040 text to output and then put it in memory using a code segment like
4041 this:
4042
4043 title: dc.b "** Welcome to this Program! **"
4044 titleend:
4045 align ;even
4046
4047 The "align"(even) is a pseudo-op that should follow text when it
4048 is followed by either word data or program lines.It causes the
4049 assembler to insert a null byte if necessary to make the address
4050 even.
4051 To output this text you need another DOS function:Write.This has
4052 an offset of -48 and needs three parameters:
4053
4054 In D1 the handle of an opened output channel that should be
4055 written to (in your case,this is the handle number that
4056 you go back from the Open command when you opened your
4057 window.).
4058 In D2 the address of the text to be output (in the example,the
4059 address "title").
4060 In D3 the number of characters to be output in bytes.
4061
4062 To find the number of bytes to output,you need to count the number
4063 of characters in your text.Use "titleend"to calculate this.Using
4064 this label,the assembler can calculate the length of your text for
4065 itself (after all,why should you count when you have a computor?)
4066 if you write:
4067
4068 move.l #titleend-title,d3
4069
4070 The advantage of specifying the length is that you can put control
4071 characters between the beginning and end of the text.In this way,
4072 you can execute certain functions using text output.You'll learn
4073 about the control characters in a bit.
4074
4075 Heres the routine:
4076
4077 Write = -48 ; (6.4.1A)
4078 ... ;open window
4079 ...
4080 move.l dosbase,a6 ;DOS base address
4081 move.l conhandle,d1 ;pass handle
4082 move.l #title,d2 ;text address
4083 move.l #titleend-title,d3 ;and length
4084 jsr Write(a6) ;call function
4085 ...
4086
4087
4088 title: dc.b "** Welcome to this Program! **"
4089
4090 titleend:
4091
4092 align ;event
4093
4094 end
4095
4096 You'll certainly use this function a lot.You'll often want to
4097 output just one character though.To allow you to do this and
4098 similar text related tasks,there are four subroutines,each of
4099 which do a different sort of output:
4100
4101 Pmsg;
4102 Outputs the text from (D2) to the first null byte.
4103
4104 Pline;
4105 Is the same as the routine above except that the text is
4106 automatically followed by a CR,the cursor is positioned at the
4107 beginning of the next line.
4108
4109 Pchar;
4110 Outputs the character in D0
4111
4112 Pcrlf;
4113 Puts the cursor at the beginning of the next line.
4114
4115 Heres the subroutine package:
4116
4117 Write = -48 ; (6.4.1B)
4118 ...
4119
4120 pline: ;*output line and then a CR
4121 bsr pmsg ;output line
4122
4123 pcrlf:
4124 move #10,d0 ;line feed
4125 bsr pchar ;output
4126 move #13,d0 ;and CR
4127
4128 pchar:
4129 move.b d0,outline ;character in output buffer
4130 move.l #outline,d2 ;address of the character
4131
4132 pmsg: ;*output line (D2) upto null
4133 move.l d2,a0 ;address in A0
4134 clr d3 ;length = 0
4135
4136 ploop:
4137 tst.b (a0)+ ;null byte ?
4138 beq pmsg2 ;yes:length found
4139 addq.l #1,d3 ;else length + 1
4140 bra ploop ;and continue looking
4141
4142 pmsg2:
4143 move.l dosbase,a6 ;DOS base address in A6
4144 move.l conhandle,d1 ;our window handle
4145 jsr Write(a6) ;call write function
4146 rts ;done!
4147
4148 outline: dc.w 0 ;output buffer for 'pchar'
4149
4150 conhandle: dc.l 0 ;windows handle
4151
4152 Here is an example program to open and close a simple window and
4153 output a text message in AssemPro format (We have used the
4154 AssemPro macros INIT_AMIGA and EXIT_AMIGA so AssemPro owners can
4155 start the program from desktop.If you are using a different
4156 assembler check your documentation for instructions on starting
4157 and exiting programs.):
4158
4159 Here is the complete program in AssemPro format:
4160
4161 ;***** 6.4.1C.asm S.D. *****
4162
4163 Openlib =-30-378
4164 closelib =-414
4165 ;execbase = 4 ;Defined in AssemPro
4166 ;Macros
4167
4168 * calls to Amiga Dos:
4169
4170 open =-30
4171 close =-30-6
4172 write =-48
4173 IoErr =-132
4174 mode_old = 1005
4175 alloc_abs =-$cc
4176
4177 ILABEL AssemPro:include/Amiga.l ;AssemPro only
4178
4179 INIT_AMIGA ;AssemPro only
4180
4181 run:
4182 bsr init ;initialization
4183 bsr test ;system test
4184 nop
4185 bra qu ;quit and exit
4186
4187 test:
4188 move.l #title,d0
4189 bsr pmsg
4190 bsr pcrlf
4191 bsr pcrlf
4192
4193 rts
4194
4195 init: ;system initialization and
4196 ;open
4197 move.l execbase,a6 ;number of execute-library
4198 lea dosname(pc),a1
4199 moveq #0,d0
4200 jsr openlib(a6) ;open DOS-library
4201 move.l d0,dosname
4202 beq error
4203
4204 lea consolname(pc),a1 ;console definition
4205 move.l #mode_old,d0
4206 bsr openfile ;console open
4207 beq error
4208 move.l d0,conhandle
4209
4210 rts
4211
4212 pmsg: ;print message (D0)
4213 movem.l d0-d7/a0-a6,-(sp)
4214 move.l d0,a0
4215 move.l a0,d2
4216 clr.l d3
4217
4218 ploop:
4219 tst.b (a0)+
4220 beq pmsg2
4221 addq.l #1,d3
4222 bra ploop ;length calculate
4223
4224 pmsg2:
4225 move.l conhandle,d1
4226 move.l dosbase,a6
4227 jsr write(a6)
4228 movem.l (sp)+,d0-d7/a0-a6
4229 rts
4230
4231 pcrlf:
4232 move #10,d0
4233 bsr pchar
4234 move #13,d0
4235
4236 pchar: ;output char in D0
4237 movem.l d0-d7/a0-a6,-(sp) ;save all
4238 move.l conhandle,d1
4239
4240 pch1:
4241 lea outline,a1
4242 move.b d0,(a1)
4243 move.l a1,d2
4244 move.l #1,d3 ;1 letter
4245 move.l dosbase,a6
4246 jsr write(a6)
4247 movem.l (sp)+,d0-d7/a0-a6 ;restore all
4248
4249 error:
4250 move.l dosbase,a6
4251 jsr IoErr(a6)
4252 move.l d0,d5
4253
4254 move.l #-1,d7 ;flag
4255
4256 qu:
4257 move.l conhandle,d1 ;window close
4258 move.l dosbase,a6
4259 jsr close(a6)
4260
4261 move.l dosbase,a1 ;DOS.Lib close
4262 move.l execbase,a6
4263 jsr closelib(a6)
4264
4265 EXIT_AMIGA ;AssemPro only
4266
4267 openfile: ;open file
4268 move.l a1,d1 ;pointer to I/O-definition-
4269 ;text
4270 move.l d0,d2
4271 move.l dosbase,a6
4272 jsr open(a6)
4273 tst.l d0
4274 rts
4275
4276 dosname: dc.b 'dos.library',0,0
4277 align.w
4278
4279 dosbase: dc.l 0
4280
4281 consolname: dc.b 'CON:0/100/640/100/** CLI-Test **',0
4282 align.w
4283
4284 conhandle: dc.l 0
4285
4286 title: dc.b '** Welcome to this Program! **'
4287
4288 titleend:
4289 align
4290
4291 outline: dc.w 0 ;output buffer for char
4292
4293 end
4294
4295 Using this program,you can very easily put whatever you want in
4296 the CON:window.These functions also work in RAW:window.You should
4297 rename "conhandle"as "rawhandle",so that you don't get things
4298 mixed up later.
4299 Lets stay with the CON:window.As mentioned earlier,you can output
4300 special characters that execute functions or change parameters for
4301 output.These characters are called control characters.
4302 You've already learned about one of these control characters,Line
4303 Feed ($A).This character isn't just output;instead,it calls a
4304 function that moves the cursor into the next line and moves the
4305 screen up.This is very useful,but there are much more interesting
4306 control characters.
4307 Here's a list of control characters that execute functions.These
4308 characters are given in hex.
4309
4310 Control Sequence;
4311
4312 Sequence Function
4313 ------------------------------------------------------------------
4314 08 Backspace
4315 0A Line Feed,Cursor down
4316 0B Move Cursor up a line
4317 0C Clear screen
4318 0D Carrige return,cursor in the first column
4319 0E Turn on normal characters (Cancel Of Effects)
4320 0F Turn on special characters
4321 1B Escape
4322
4323 The following sequences begin with $9B,the CSI (Control Sequence
4324 Introducer).The characters that follow execute a function.The
4325 values in square brackets can be left off.The n's you see
4326 represent one or more digit decimal numbers given using ASCII
4327 characters.The value that is used when n is left off,is given in
4328 the parenthesis that follow n in the description of the function
4329 in the table.
4330
4331 Control Sequence Introducer;
4332
4333 Sequence Function
4334 ------------------------------------------------------------------
4335 9B[n]40 Insert n blanks
4336 9B[n]41 Move cursor n (1) lines up
4337 9B[n]42 Move cursor n (1) lines down
4338 9B[n]43 Move cursor n (1) characters to the right
4339 9B[n]44 Move cursor n (1) characters to the left
4340 9B[n]45 Move cursor down n (1) lines into column 1
4341 9B[n]46 Move cursor up n (1) lines and into column 1
4342 9B[n][3B n]48 Cursor in line;Set column
4343 9B 4A Erase screen from cursor
4344 9B 4B Erase line from the cursor
4345 9B 4C Insert line
4346 9B 4D Delete line
4347 9B[n]50 Delete n characters starting at cursor
4348 9B[n]53 Move up n lines
4349 9B[n]54 Move down n lines
4350 9B 32 30 68 Line feed => Line feed + return
4351 9B 32 30 6C Line feed => just Line feed
4352 9B 6E Sends the cursor position!A string of the following
4353 form is returned:
4354 9B (line) 3B (column) 52
4355 9B(style);(foreground colour);(Background Colour)6D
4356 The three parameters are decimal numbers in ASCII
4357 format.They mean:
4358 Style: 0 = normal
4359 1 = bold
4360 3 = italic
4361 4 = underline
4362 7 = inverse
4363 Foreground colour: 30-37
4364 Colour 0-7 for Text
4365 Background colour: 40-47
4366 Colour 0-7 for background
4367 9B(length)74 sets the maximum number of lines to be displayed
4368 9B(width)75 sets the maximum line length
4369 9B(distance)78 defines the distance in pixels from the left border
4370 of the window to the place where output should
4371 begin
4372 9B(distance)79 defines the distance in pixels from the upper
4373 border of the window to the place where output
4374 should begin
4375 The last four functions yield the normal values if
4376 you leave off the parameters.
4377
4378 9B 30 20 70 Make cursor invisible
4379 9B 20 70 Make cursor visible
4380 9B 71 Sends window construction.A string of the following
4381 form is returned:
4382 9B 31 3B 31 3B (lines) 3B (columns) 73
4383
4384 To see how the control characters work,have "pmsg"output this text
4385 to your window:
4386
4387 mytext: dc.b $9b,"4;31;40m" ; (6.3.2D)
4388 dc.b "underline"
4389 dc.b $9b,"3;33;40m",$9b,"5;20H"
4390 dc.b "** Hello World! **",0
4391
4392 The parameters for the control sequence are put in quotation marks
4393 so they are treated as an ASCII string.Now you see,just how easy
4394 it is to do text output!
4395 Here is the complete program to open and output the text and
4396 control codes to your window in AssemPro format (We have used the
4397 AssemPro macros INIT_AMIGA and EXIT_AMIGA so AssemPro owners can
4398 start the programs from desktop.If you are using a different
4399 assembler check your documentation for instructions on starting
4400 and exiting programs):
4401
4402 ; ***** 6.4.1D.ASM S.D. *****
4403
4404
4405 openlib =-30-378
4406 closelib =-414
4407 ;execbase = 4 ;defined in AssemPro macros
4408
4409 * calls to Amiga Dos:
4410
4411 open =-30
4412 close =-30-6
4413 write =-48
4414 IoErr =-132
4415 mode_old = 1005
4416 alloc_abs =-$cc
4417
4418 ILABEL AssemPro:includes/Amiga.l ;AssemPro only
4419
4420 INIT_AMIGA ;AssemPro only
4421
4422 run:
4423 bsr init ;initialization
4424 bsr test ;system test
4425 nop
4426 bra qu ;quit and exit
4427
4428 test:
4429 move.l #mytext,d0
4430 bsr pmsg
4431 bsr pcrlf
4432 bsr pcrlf
4433
4434 rts
4435
4436 init: ;system initialization and open
4437 move.l execbase,a6 ;number of execute-library
4438 lea dosname(pc),a1
4439 moveq #0,d0
4440 jsr openlib(a6) ;open DOS-Library
4441 move.l d0,dosbase
4442 beq error
4443
4444 lea consolname(pc),a1 ;console definition
4445 move.l #mode_old,d0
4446 bsr openfile ;console open
4447 beq error
4448 move.l d0,conhandle
4449
4450 rts
4451
4452 pmsg: ;print message (D0)
4453 movem.l d0-d7/a0-a6,-(sp)
4454 move.l d0,a0
4455 move.l a0,d2
4456 clr.l d3
4457
4458 ploop:
4459 tst.b (a0)+
4460 beq pmsg2
4461 addq.l #1,d3
4462 bra ploop
4463
4464 pmsg2:
4465 move.l conhandle,d1
4466 move.l dosbase,a6
4467 jsr write(a6)
4468 movem.l (sp)+,d0-d7/a0-a6
4469 rts
4470
4471 pcrlf:
4472 move #10,d0
4473 bsr pchar
4474 move #13,d0
4475
4476 pchar: ;output char in D0
4477 movem.l d0-d7/a0-a6,-(sp) ;save all
4478 move.l conhandle,d1
4479
4480 pch1:
4481 lea outline,a1
4482 move.b d0,(a1)
4483 move.l a1,d2
4484 move.l #1,d3 ;one letter
4485 move.l dosbase,a6
4486 jsr write(a6)
4487 movem.l (sp)+,d0-d7/a0-a6 ;restore all
4488 rts
4489
4490 error:
4491 move.l dosbase,a6
4492 jsr IoErr(a6)
4493 move.l d0,d5
4494
4495 move.l #-1,d7 ;flag
4496
4497 qu:
4498 move.l conhandle,d1 ;window close
4499 move.l dosbase,a6
4500 jsr close(a6)
4501
4502 move.l dosbase,a1 ;DOS.Lib close
4503 move.l execbase,a6
4504 jsr closelib(a6)
4505
4506 EXIT_AMIGA ;AssemPro only
4507
4508 openfile: ;open file
4509 move.l a1,d1 ;pointer to I/O-definition-
4510 ;text
4511 move.l d0,d2
4512 move.l dosbase,a6
4513 jsr open(a6)
4514 tst.l d0
4515 rts
4516
4517 dosname: dc.b 'dos.library',0,0
4518 align.w
4519
4520 dosbase: dc.l 0
4521
4522 consolname: dc.b 'CON:0/100/640/100/ ** CLI-Test **',0
4523 align.w
4524
4525 conhandle: dc.l 0
4526
4527 mytext:
4528 dc.b $9b,'4;31;40m'
4529 dc.b 'underline'
4530 dc.b $9b,'3;33;40m',$9b,'5;20H'
4531 dc.b '** Hello World !! **',0
4532
4533 align
4534
4535 outline: dc.w 0 ;output buffer for pchar
4536
4537 end
4538
4539 Now that you've done text and character output,its time to move on
4540 to text input.
4541
4542 6.4.2.Keyboard Input.
4543 ---------------------
4544 You can read keyboard input very easily.You just need to open the
4545 I/O channel of the CON:window and read from it.You need the read
4546 function from the DOS library to do this.Its offset is -42.
4547 The function has three parameters just like the WRITE function.
4548
4549 In D1 the handle number that you get from the WRITE function.
4550 In D2 the address that the data read in is to start.
4551 In D3 the number of bytes to read.
4552
4553 Here is a subroutine that reads the number of characters from the
4554 keyboard that it finds in D3.It puts them in a buffer.
4555
4556 read = -42 ; (6.4.2A)
4557 ...
4558
4559 getchr: ;* Get (D3) characters from the
4560 ;keyboard
4561 move.l #inbuff,d2 ;address of buffer in D2
4562 move.l dosbase,a6 ;DOS base address in A6
4563 move.l conhandle,d1 ;our window handle
4564 jsr read(a6) ;call read function
4565 rts ;done!
4566
4567 inbuff: blk.b 80,0 ;buffer for keyboard input
4568
4569 This routine returns to the main program when <Return> is entered.
4570 If more than D3 characters are entered,"inbuff"only gets the first
4571 characters.The routine gets the remaining characters when called a
4572 second time.
4573 This sort of input is fairly easy.You can backspace,because only
4574 the characters that should be there are put in the memory block
4575 starting at "inbuff".The number of characters moved into "inbuff"
4576 is put in D0.
4577
4578 Try the program out as follows:
4579
4580 After opening the CON:window,put the following lines in the main
4581 program:
4582
4583 move #80,d3 ;read 80 characters (6.4.2B)
4584 bsr readchr ;get line from keyboard
4585 lea inline,a0 ;address of line in A0
4586 clr.b 0(a0,d0) ;null byte on the end
4587 bsr pmsg ;output line again
4588
4589 bp:
4590
4591 After this comes the code segment that closes the window again.
4592 After loading the program into the AssemPro debugger,make "bp"a
4593 breakpoint and start the program.(SEKA users start the program
4594 with "g run"and enter "bp"as the breakpoint).The program quits at
4595 the breakpoint and you can take a look at the results on the
4596 screen.Then you can continue the program (SEKA with "j bp") and
4597 let the window close.
4598 After starting the program and opening the window,the cursor
4599 appears in the upper left corner of the window.Enter some text and
4600 press <Return>.The string that you just entered is output again on
4601 the screen.
4602 You use the "pmsg"routine from the previous chapter to do this
4603 output.This routine needs a null byte at the end of the text to be
4604 output.You put a null byte there by putting the address of the
4605 input buffer in A0 and then erasing the byte at A0+D0 using the
4606 CLR.B command.Since D0 contains the number of characters that were
4607 entered,this byte is the first unused byte.
4608 Since you're in the debugger you can redisplay the disassembled
4609 output when the program ends to see what "getchr"put in "inbuff"
4610 (SEKA owners can use "q inbuff"when the program ends to see what
4611 "getchr"put there.)You'll find the characters that you typed plus
4612 a closing $A.The $A stands for the <Return> key and its counted
4613 too,so if you entered a 12 and then hit <Return>,for example,D0
4614 will contain a 3.
4615 Try this again with a RAW:window.Change the window definition from
4616 CON: to RAW:and reassemble the program.You'll notice the diference
4617 right away.After you've entered one character,a return is executed
4618 D0 always as one bit in it.
4619 The advantage of this form of input is that cursor and function
4620 keys can be recognized.Using your own routine,you can repeatedly
4621 accept input of characters using "getchr"and then work with the
4622 special characters.
4623 Theres another form of keyboard input:checking for a single key.
4624 This is important when a program is about to execute an important
4625 function and the user must say he wants it executed by entering
4626 "Y"for yes.This can be treated as normal input,but in some cases,
4627 there is a better method.
4628 There is a function in the DOS library that waits a certain
4629 specified length of time for a key to be pressed,and returns a
4630 zero (FALSE) if no key was hit in this time period.It returns a -1
4631 ($FFFFFFFF = TRUE) if one was.To find out which key it takes
4632 another function.The WaitForChar function,is only good for tasks
4633 like waiting for the user to let the program know that it can
4634 continue scrolling text.
4635
4636 The function needs two parameters:
4637
4638 In D1 the handle number of the window or file from which the
4639 character should be read.It can also wait for a character
4640 from an interface.
4641 In D2 you pass the length of time in microseconds that you
4642 should wait for a key stroke.
4643
4644 To wait one second for one key to be hit,you can use the following
4645 routine:
4646
4647 WaitForCh=-30-174 ; (6.4.2C)
4648 ...
4649
4650 scankey: ;* Wait for a key stroke
4651 move.l conhandle,d1 ;in our window
4652 move.l #1000000,d2 ;waiting time 1 second
4653 move.l dosbase,a6 ;DOS base address
4654 jsr waitforch(a6) ;wait...
4655 tst.l d0 ;test result
4656 rts
4657
4658 The TST command at the end of the program allows the calling
4659 routine to use a BEQ or BNE command to evaluate the results of the
4660 routine-BEQ branches if no key was hit.BNE doesn't.
4661 Heres an example program in AssemPro format covering what you have
4662 learned so far.Opening and closing a window,displaying text in the
4663 window and inputting text:
4664
4665 ;***** 6.4.2A.ASM S.D *****
4666
4667 openlib =-30-378
4668 closelib =-414
4669 ;execbase =4 ;defined in AssemPro
4670 ;Macros
4671
4672 * call to Amiga.Dos:
4673
4674 open =-30
4675 close =-30-6
4676 read =-42
4677 write =-48
4678 IoErr =-132
4679 mode_old =1005
4680 alloc_abs =-$cc
4681
4682 ILABEL AssemPro:include/Amiga.l ;AssemPro only
4683
4684 INIT_AMIGA ;AssemPro only
4685
4686 run:
4687 bsr init ;initialization
4688 bsr test ;system test
4689 nop
4690 bra qu ;quit and exit
4691
4692 test:
4693 move.l #mytext,d0
4694 bsr pmsg
4695 bsr pcrlf
4696 bsr pcrlf
4697 move.l #80,d3 ;80 characters to read in (D3)
4698 bsr getchr ;get character
4699 bsr pmsg ;output line
4700
4701 rts
4702
4703 init: ;system initialization and open
4704 move.l execbase,a6 ;number of execute-library
4705 lea dosname(pc),a1
4706 moveq #0,d0
4707 jsr openlib ;open DOS-Library
4708 move.l d0,dosbase
4709 beq error
4710
4711 lea consolname(pc),a1 ;console definition
4712 move.l #mode_old,d0
4713 bsr openfile ;console open
4714 beq error
4715 move.l d0,conhandle
4716
4717 rts
4718
4719 pmsg: ;print message (D0)
4720 movem.l d0-d7/a0-a6,-(sp)
4721 move.l d0,a0
4722 move.l a0,d2
4723 clr.l d3
4724
4725 ploop:
4726 tst.b (a0)+
4727 beq pmsg2
4728 addq.l #1,d3
4729 bra ploop ;check length
4730
4731 pmsg2:
4732 move.l conhandle,d1
4733 move.l dosbase,a6
4734 jsr write(a6)
4735 movem.l (sp)+,d0-d7/a0-a6
4736 rts
4737
4738 pcrlf:
4739 move #10,d0
4740 bsr pchar
4741 move #13,d0
4742
4743 pchar: ;character in D0 output
4744 movem.l d0-d7/a0-a6,-(sp) ;save all
4745 move.l conhandle,d1
4746
4747 pch1:
4748 lea outline,a1
4749 move.b d0,(a1)
4750 move.l a1,d2
4751 move.l #1,d3 ;1 letter
4752 move.l dosbase,a6
4753 jsr write(a6)
4754 movem.l (sp)+,d0-d7/a0-a6 ;restore all
4755 rts
4756
4757 getchr: ;get character for keyboard
4758 move.l #1,d3 ;1 character
4759 move.l conhandle,d1
4760 lea inbuff,a1 ;buffer address
4761 move.l a1,d2
4762 move.l dosbase,a6
4763 jsr read(a6)
4764 clr.l d0
4765 move.b inbuff,d0
4766 rts
4767
4768 error:
4769 move.l dosbase,a6
4770 jsr IoErr(a6)
4771 move.l d0,d5
4772
4773 move.l #-1,d7 ;flag
4774
4775 qu:
4776 move.l conhandle,d1 ;window close
4777 move.l dosbase,a6
4778 jsr close(a6)
4779
4780 move.l dosbase,a1 ;DOS.Lib close
4781 move.l execbase,a6 jsr ;close lib (A6)
4782
4783 EXIT_AMIGA ;AssemPro only
4784
4785
4786 openfile: ;open file
4787 move.l a1,d1 ;pointer to I/O-Definition-
4788 ;Text
4789 move.l d0,d2
4790 move.l dosbase,a6
4791 jsr open(a6)
4792 tst.l d0
4793 rts
4794
4795 dosname: dc.b 'dos.library',0,0
4796 align.w
4797
4798 dosbase: dc.l 0
4799
4800 consolname: dc.b 'CON:0/100/640/100/** CLI-TEST **',0
4801 align.w
4802
4803 conhandle: dc.l 0
4804
4805 mytext: dc.b '** Hello World !! **',0
4806
4807 align
4808
4809 outline: dc.w 0 ;output buffer for pchar
4810
4811 inbuff: blk.b 8 ;input buffer
4812
4813 end
4814
4815
4816 6.4.3.Printer Control.
4817 ----------------------
4818 Now that you've looked at console I/O,lets look at outputting data
4819 from the computor.The first device that we'll discuss is the
4820 printer.
4821 Its very easy to use the printer.You just need to open another
4822 channel.It goes just the way you learned it with CON: and RAW:
4823 windows;the only difference is you enter PRT:instead.
4824 You open this channel using the same lines that you used above for
4825 the window except that the pointer is to the channel name PRT:in
4826 D1.You pass the mode "new"(1006) in D2 in the "do_open"routine as
4827 well.Save the handle number that comes back at a label called
4828 "prthandle".
4829 Now you can use the same output routines that you used with the
4830 windows to send text to the printer.You need to put "prthandle"
4831 instead of "conhandle"in the line with the "move.l conhandle,d1"
4832 command.
4833 Actually it would be better to eliminate this line from the
4834 routine totally.Then you can use the same routine for window and
4835 printer output.The calling procedure would then need to put
4836 "conhandle"in D1 for window output.It would put "prthandle" in D1
4837 for printer output.This is a very flexible output routine that can
4838 be used for window and printer output now.You can't accept input
4839 from the printer,because the printer doesn't send data.It just
4840 accepts it and prints it.
4841
4842 6.4.4.Serial I/O.
4843 -----------------
4844 Its just as easy to use the serial interface as the printer.Just
4845 enter SER:as the filename.Now you can use the DOS functions READ
4846 and WRITE just as before to do I/O channels you've just opened.
4847 You can set the parameters for the interface (like Hand shake and
4848 Transfer rate) with the Preferences program.
4849
4850 6.4.5.Speech Output.
4851 --------------------
4852 The Amiga has a speech synthesizer built in.This isn't quite as
4853 easy to program as the I/O devices discussed earlier,however.You
4854 use the "narrator.device"to do this.
4855 This device requires several program steps to install it and then
4856 causes it to speak.You need to open the device,start the I/O,etc..
4857 Lets look at how to translate the text into the proper form and
4858 then output the text.
4859 First we need to do some initialization.Lets define the constants
4860 now.Some of them are new.
4861
4862 ;***** Narrator Basic Functions 3/87 S.D ***** (6.4.5A)
4863
4864 openlib =-408
4865 closelib =-414
4866 execbase = 4
4867
4868 open =-30 ;open file
4869 close =-36 ;close file
4870 mode_old = 1005 ;old mode
4871
4872 opendevice =-444 ;open device
4873 closedev =-450 ;close device
4874
4875 sendIo =-462 ;start I/O
4876 abortIO =-480 ;abort I/O
4877
4878 translate =-30 ;translate text
4879
4880 ;The initialization routine follows:
4881
4882 init: ;initialize and open system
4883
4884 ;* open DOS library *
4885
4886 move.l execbase,a6 ;pointer to execbase
4887 lea dosname,a1 ;pointer to DOS name
4888 moveq #0,d0 ;version unimportant
4889 jsr openlib(a6) ;open DOS library
4890 move.l d0,dosbase ;save handle
4891 beq error ;error handle
4892
4893 ;* Open translator.library *
4894
4895 lea transname,a1 ;pointer to translator name
4896 clr.l d0
4897 jsr openlib(a6) ;open translator
4898 move.l d0,transbase ;save handle
4899 beq error ;error handling
4900
4901 ;* Set up I/O area for Narrator *
4902
4903 lea talkio,a1 ;pointer to I/O area in A1
4904 move.l #nwrrep,14(a1) ;enter port address
4905 move.l #amaps,48+8(a1) ;pointer to audio mask
4906 move #4,48+12(a1) ;number of the mask
4907 move.l #512,36(a1) ;length of the output area
4908 move #3,28(a1) ;command:write
4909 move.l #outtext,40(a1) ;address of output area
4910
4911 ;* Open Narrator device *
4912
4913 clr.l d0 ;number 0
4914 clr.l d1 ;no flags
4915 lea nardevice,a0 ;pointer to device name
4916 jsr opendevice(a6) ;open narrator.device
4917 tst.l d0 :error?
4918 bne error ;Yes!
4919
4920 ;* Open Window *
4921
4922 move.l #consolname,d1 ;console definition
4923 move.l #mode_old,d2 ;old mode
4924 move.l dosbase,a6 ;DOS base address
4925 jsr open(a6) ;open window
4926 tst.l d0 ;error?
4927 beq error ;Yes!
4928 move.l d0,conhandle ;else save handle
4929
4930 After you've done this initialization,you can have the computor
4931 save the text you have prepared for it.To see what the Amiga is
4932 saying,use the "pmsg"function to have the text written to the
4933 window:
4934
4935
4936 move.l #intext,d2 ;text for the Amiga to say
4937 bsr pmsg ;output in window also
4938
4939 sayit: ;have the text said
4940
4941 ;*Translate the text into a form that the computor can use *
4942
4943 lea intext,a0 ;address of the text
4944 move.l #outtext-intext,d0 ;length of the text
4945 lea outtext,a1 ;address of output area
4946 move.l #512,d1 ;length of output area
4947 move.l tranbase,a6 ;translator base address
4948 jsr translate(a6) ;translate text
4949
4950 ;* Speech output *
4951
4952 lea talkio,a1 ;address of I/O structure
4953 move.l #512,36(a1) ;length of output area
4954 move.l execbase,a6 ;EXEC base address
4955 jsr sendIO(a6) ;start I/O (speech output)
4956
4957
4958 Once the program ends,the I/O stops as well,so you need to put in
4959 something that keeps the program going longer.You'll use the
4960 "getchr"function that you programmed earlier to take care of this:
4961
4962
4963 bsr getchr ;wait for keyboard input
4964
4965 The computor waits until the <Return> key is pressed.Now you can
4966 listen to what the Amiga as to say.Once the <Return> key is
4967 pressed,the program stops.
4968
4969
4970 qu: ; (6.4.5C)
4971 move.l execbase,a6 ;EXEC base address
4972 lea talkio,a1 ;pointer to I/O area
4973 jsr abortio(a6) ;stop the I/O
4974
4975 move.l conhandle,d1
4976 move.l dosbase,a6
4977 jsr close(a6) ;close window
4978
4979 move.l dosbase,d1
4980 move.l execbase,a6
4981 jsr closelib(a6) ;close DOS library
4982
4983 lea talkio,a1
4984 jsr closedev(a6) ;close narrator.device
4985
4986 move.l tranbase,a1
4987 jsr closelib(a6) ;close translator library
4988
4989 rts ;* end of program
4990
4991
4992 Now comes the data that you need for the program above:
4993
4994
4995 mytext: dc.b 'This is a test text !',10,13,10,13,0,0
4996 dosmame: dc.b 'dos.library',0,0
4997 transname: dc.b "translator.library",0
4998 consolname: dc.b 'RAW:0/100/640/100/** Test window',0
4999 nardevice dc.b 'narrator.device',0
5000 align
5001 dosbase: dc.l 0
5002 tranbase dc.l 0
5003 amaps: dc.b 3,5,10,12
5004 align
5005 conhandle: dc.l 0
5006 talkio: blk.l 20,0
5007 nwrrep: blk.l 8,0
5008 intext: dc.b 'hello,i am the amiga talking to you',0
5009 align
5010 outtext: blk.b 512,0
5011
5012
5013 This is quite a bit of work,but its worth it because it opens so
5014 many possibilities for you.There are a lot of variations possible
5015 if you modify parameters.These parameters are entries in the I/O
5016 area starting at the "talkio"label.The area is built as follows:
5017
5018 Offset Length Meaning
5019 ----------------------------------------------------------------
5020 ** Port Data **
5021 0 L Pointer to next block
5022 4 L Pointer to last block
5023 8 B I/O type
5024 9 B Priority
5025 10 L Pointer to I/O name
5026 14 L Pointer to port
5027 18 W Length
5028 ** I/O Data **
5029 20 L Pointer to device
5030 24 L Pointer to device unit
5031 28 W Command word
5032 30 B I/O flags
5033 31 B I/O status
5034 32 L I/O pointer
5035 36 L I/O length
5036 40 L Pointer to Data
5037 44 L I/O offset
5038 ** Narrator data items **
5039 48 W Speech speed
5040 50 W Highness of voice
5041 52 W Speech mode
5042 54 W Sex (male/female voice)
5043 56 L Pointer to audio mask
5044 60 W Number of mask
5045 62 W Volume
5046 64 W Read in rate
5047 66 B Flag for producing graphics (0=off)
5048 67 B Actual mask (internal use)
5049 68 B Channel used (internal use)
5050
5051 We would'nt recommend experimenting with the data in the first two
5052 blocks.If you do,you can easily cause a system crash.You can use
5053 the last entries of the structure to produce some interesting
5054 effects though.
5055 Heres an overview of the parameters you can use to vary the speech
5056 output.The value in parenthesis is the standard value,the value
5057 set when narrator.device is opened.
5058
5059 Speech speed (150);
5060 You can use this to set the speed of speech.The pitch of the voice
5061 is not affected by this value.
5062
5063 Pitch of voice (110);
5064 You can choose a value between 65 and 320 for the pitch (from
5065 Goofy to Mickey Mouse).
5066
5067 Speech mode (0);
5068 The zero gives half-way naturel speech.A one lets the Amiga speak
5069 in monotone like a robot.
5070
5071 Sex (0);
5072 A zero means masculine and a one means feminine (more or less..)
5073
5074 Volume (64);
5075 The volume can range from 0 to 64.The standard value is the
5076 loudest possible.
5077
5078 Read in rate (22200);
5079 By lowering this value,the voice is lowered.If you change this
5080 very much,you'll get some wierd voices!
5081
5082 You can experiment a bit until you find a interesting voice.Have
5083 fun!
5084 Here is a complete talking program in AssemPro format:
5085
5086 ;***** Speech output S.D. *****
5087
5088 openlib =-30-378
5089 closelib =-414
5090 ;execbase =4 ;defined by AssemPro
5091
5092 * calls to Amiga Dos:
5093
5094 open =-30
5095 close =-30-6
5096 opendevice =-444
5097 closedev =-450
5098 addport =-354
5099 remport =-360
5100 ;DoIo =-456
5101 sendIo =-462
5102 abortIo =-480
5103 read =-30-12
5104 write =-30-18
5105 ;myinput =-30-24
5106 ;output =-30-30
5107 ;currdir =-30-96
5108 ;exit =-30-114
5109 waitforch =-30-174
5110 findtask =-294
5111 translate =-30
5112 mode_old = 1005
5113 ;mode_new = 1006
5114 ;alloc_abs =-$cc
5115 ;free_mem =-$d2
5116
5117 ;!!!when>500KB !!! or place in chip memory
5118 ;org $40000
5119 ;load $40000
5120 ;!!!!!!!!!!!!!!!!!!!!!!!
5121
5122
5123 ILABEL AssemPro:includes/Amiga.l ;AssemPro only
5124
5125 INIT_AMIGA ;AssemPro only
5126
5127 run:
5128 bsr init ;initialization
5129 bra test ;system-test
5130
5131 init: ;system initialization and
5132 ;open
5133 move.l execbase,a6 ;pointer to exec library
5134 lea dosname(pc),a1 ;pointer to dos name
5135 moveq #0,d0 ;version:not important
5136 jsr openlib(a6) ;open DOS-Library
5137 move.l d0,dosbase ;save handle
5138 beq error ;error routine
5139
5140 ;* ;open translator library
5141 move.l execbase,a6 ;pointer to exec library
5142 lea transname,a1 ;pointer to translator library
5143 clr.l d0
5144 jsr openlib(a6) ;open translator
5145 move.l d0,tranbase ;save handle
5146 beq error ;error routine
5147
5148 ;* ;set up
5149 sub.l a1,a1
5150 move.l execbase,a6
5151 jsr findtask(a6) ;find task
5152 move.l d0,nwrrep+2
5153
5154 lea nwrrep,a1
5155 jsr addport(a6) ;add port
5156
5157 ;* ;open narrator device
5158 lea talkio,a1 ;pointer to I/O area in A1
5159 move.l #nwrrep,14(a1) ;enter port address
5160 clr.l d0 ;number 0
5161 clr.l d1 ;no flags
5162 lea nardevice,a0 ;pointer to device name
5163 jsr opendevice(a6) ;open narrator.device
5164 tst.l d0 ;error?
5165 bne error ;Yes!
5166
5167 ;* ;set up I/O for narrator
5168 ;device
5169
5170 bp:
5171 lea talkio,a1 ;pointer to I/O in A1
5172 move.l #nwrrep,14(a1) ;enter port address
5173 move.l #amaps,48+8(a1) ;pointer to audio mask
5174 move #4,48+12(a1) ;size of mask
5175
5176 lea consolname(pc),a1 ;console-definition
5177 move.l #mode_old,d0
5178 bsr openfile ;console open
5179 beq error
5180 move.l d0,conhandle
5181
5182 rts
5183
5184 test:
5185 move.l #mytext,d0
5186 bsr pmsg ;test-text output
5187
5188 bsr sayit ;say text
5189
5190 bsr readin ;input
5191 move #10,d0
5192 bsr pchar ;LF output
5193 move.l #inline+2,d0
5194 bsr pmsg ;and again
5195 bsr pcrlf
5196 bra qu
5197
5198 error:
5199 move.l #-1,d7 ;flag
5200
5201 qu:
5202 move.l execbase,a6
5203 lea talkio,a1
5204 jsr abortio(a6)
5205
5206 move.l conhandle,d1 ;window close
5207 move.l dosbase,a6
5208 jsr close(a6)
5209
5210 move.l dosbase,a1 ;DOS.Lib close
5211 move.l execbase,a6
5212 jsr closelib(a6)
5213
5214 lea nwrrep,a1
5215 jsr remport(a6) ;remove port
5216 lea talkio,a1
5217 jsr closedev(a6) ;close narrator device
5218 move.l tranbase,a1
5219 jsr closelib(a6) ;close translator library
5220
5221 EXIT_AMIGA ;AssemPro only
5222
5223 openfile: ;open file
5224 move.l a1,d1 ;pointer to I/O definition-
5225 ;text
5226 move.l d0,d2
5227 move.l dosbase,a6
5228 jsr open(a6)
5229 tst.l d0
5230 rts
5231
5232 pmsg: ;print message (D0)
5233 movem.l d0-d7/a0-a6,-(sp)
5234 move.l d0,a0
5235 move.l a0,d2
5236 clr.l d3
5237
5238 mess1:
5239 tst.b (a0)+
5240 beq mess2
5241 addq.l #1,d3
5242 bra mess1 ;length calculate
5243
5244 mess2:
5245 move.l conhandle,d1
5246 move.l dosbase,a6
5247 jsr write(a6)
5248 movem.l (sp)+,d0-d7/a0-a6
5249 rts
5250
5251 pcrlf:
5252 move #10,d0
5253 bsr pchar
5254 move #13,d0
5255
5256 pchar: ;output characters in D0
5257 movem.l d0-d7/a0-a6,-(sp) ;save all
5258 move.l conhandle,d1
5259
5260 pch1:
5261 lea chbuff,a1
5262 move.b d0,(a1)
5263 move.l a1,d2
5264 move.l #1,d3 ;1 letter
5265 move.l dosbase,a6
5266 jsr write(a6)
5267 movem.l (sp)+,d0-d7/a0-a6 ;restore all
5268 rts
5269
5270 scankey: ;test key
5271 move.l conhandle,d1
5272 move.l #500,d2 ;wait value
5273 move.l dosbase,a6
5274 jsr waitforch(a6)
5275 tst.l d0
5276 rts
5277
5278 readin: ;input from keyboard
5279 movem.l d0-d7/a0-a6,-(sp) ;save registers
5280 lea inline+2,a2 ;pointer to input buffer
5281 clr.l (a2)
5282
5283 inplop:
5284 bsr getchr
5285 cmp.b #8,d0
5286 beq backspace
5287 cmp.b #127,d0 ;delete?
5288 beq backspace
5289 bsr pchar ;character output
5290 cmp.b #13,d0
5291 beq inputx
5292 move.b d0,(a2)+
5293 bra inplop
5294
5295 inputx:
5296 clr.b (a2)+
5297 sub.l #inline,a2
5298 move a2,inline ;length in lines+1
5299 movem.l (sp)+,d0-d7/a0-a6 ;registers
5300 rts
5301
5302 backspace:
5303 cmp.l #inline,a2 ;at the beginning?
5304 beq inplop ;yes
5305 move.b #8,d0
5306 bsr pchar ;backspace
5307 move #32,d0
5308 bsr pchar ;blank
5309 move #8,d0
5310 bsr pchar ;backspace
5311 clr.b (a2)
5312 subq.l #1,a2
5313 bra inplop
5314
5315 getchr: ;get one character from
5316 ;keyboard
5317 move.l #1,d3 ;one character
5318 move.l conhandle,d1
5319 lea inbuff,a1 ;buffer address
5320 move.l a1,d2
5321 move.l dosbase,a6
5322 jsr read(a6)
5323 clr.l d0
5324 move.b inbuff,d0
5325 rts
5326
5327 sayit:
5328 lea intext,a0
5329 move.l #outtext-intext,d0
5330 lea outtext,a1
5331 move.l #512,d1
5332 move.l tranbase,a6
5333 jsr translate(a6)
5334
5335 p:
5336 lea talkio,a1
5337 move #3,28(a1) ;??
5338 move.l #512,36(a1)
5339 move.l #outtext,40(a1)
5340 move.l execbase,a6
5341 jsr sendio(a6)
5342
5343 rts
5344
5345 mytext: dc.b 'This is our Test-Text !',10,13,10,13,0,0
5346
5347 dosname: dc.b 'dos.library',0,0
5348
5349 transname: dc.b "translator.library",0
5350 align.w
5351
5352 dosbase: dc.l 0
5353
5354 tranbase: dc.l 0
5355
5356 consolname: dc.b 'CON:0/100/640/100/* Speech-Test S.D.* ',0
5357
5358 nardevice: dc.b 'narrator.device',0
5359
5360 amaps: dc.b 3,5,10,12,0,0
5361 align.w
5362
5363 conhandle: dc.l 0
5364
5365 inbuff: blk.b 8
5366
5367 inline: blk.b 180,0
5368
5369 chbuff: blk.b 82,0
5370
5371 narread: blk.l 20,0
5372
5373 talkio: blk.l 20,0
5374
5375 nwrrep: blk.l 8,0
5376
5377 intext: dc.b 'hello,i am the amiga computor',0
5378 align.w
5379
5380 outtext: blk.l 128,0
5381
5382
5383 end
5384
5385 6.5.Disk Operations.
5386 --------------------
5387 The most important peripheral device for a computor like the Amiga
5388 is the disk drive.You use it to save data,so that you don't lose
5389 it when you turn off the computor.We'll look at saving and
5390 retrieving data in this chapter.
5391 Lets first look at the simple disk operations that are used for
5392 data management.To gain access to a file,you must open it first.
5393 This is done using the OPEN function from the DOS library,a
5394 function that you're already familiar with.I'll assume in the
5395 following examples,that you've already opened the DOS library.
5396
5397 6.5.1.Open Files.
5398 -----------------
5399 The open function needs a parameter for the mode.The mode has a
5400 particular meaning.If the file is opened for reading,it must
5401 already exist.The mode for the OPEN function must be "old"(1005)
5402 in this case.
5403 If you want to produce a file,you must open it first.Since it does
5404 not exist,you use the "new"(1006) mode.If a file is opened for
5405 writing using this mode even though a file with this name already
5406 exists,the old file with this name is erased and replaced.To avoid
5407 loss of data,you should check if a file by that name already
5408 exists and then output an error message if it does.
5409 You're going to start with a subroutine that opens a file.Lets
5410 assume that the filename starts at the label "filename",and that
5411 it is closed with a null byte.You just need to pass the mode in
5412 register D2.
5413 The routine puts the file handle number in "filehd"and returns to
5414 the main program.Since the operation with the handle is the last
5415 one performed by the subroutine,the status of the operation can be
5416 evaluated once the return has been executed.If the operation went
5417 smoothly and the file is opened,the handle number has a non-zero
5418 value.If it is zero and "bsr openfile"is followed by "beq error",
5419 you can branch to an error handling routine when problems occur.
5420
5421 Here is a subroutine for opening and closing a file:
5422
5423 open =-30 ; (6.5.1A)
5424 close =-36
5425 mode_old = 1005
5426 mode_new = 1006
5427 ...
5428 openfile: ;*open file,mode in D0
5429 move.l dosbase,a6 ;DOS base address in A6
5430 move.l #filename,d1 ;pointer to filename
5431 jsr open(a6) ;open file
5432 move.l d0,filehd ;save handle
5433 rts
5434
5435 closefile: ;*close file
5436 move.l dosbase,a6 ;DOS base address in A6
5437 move.l filehd,d1 ;file handle in D1
5438 jsr close(a6) ;close file
5439 rts
5440
5441 filehd: dc.l 0 ;storage for file handle
5442 filename: dc.b "filename",0 ;file to be opened
5443 align ;even
5444
5445 To use these subroutines,you must look at how you can load and
5446 save data.
5447
5448 6.5.2.Reading and Writing Data.
5449 -------------------------------
5450 Lets write a new file.To start,write the following lines:
5451
5452 move.l #mode_new,d2 ;open new file (6.5.2A)
5453 bsr openfile ;open file
5454 beq error ;did'nt work!
5455
5456 For the filename,write a name like "Testfile"in the line labelled
5457 "filename".After calling the "openfile"routine,a file with this
5458 name is created on the disk.If one existed already,it is erased.
5459
5460 Lets assume you want to write a short text file.For the example
5461 lets use:
5462
5463 text: dc.b "This is a test text for the Testfile",0
5464 textend:
5465
5466 The "textend"label is used so that you can calculate the number of
5467 data bytes by subtracting "text".
5468 You want to write this text in the file.Use the WRITE function
5469 which needs three parameters:
5470
5471 In D1 the file handle that you got back from the OPEN function.
5472 In D2 a pointer to the data that should be written.
5473 In D3 the number of bytes to be written.
5474
5475 For the example,you'll need another segment of code to put the
5476 pointer to the data in D2 and the number of bytes in D3:
5477
5478 write =-48 ; (6.5.2B)
5479 ...
5480 writedata: ;*write data in the file
5481 move.l dosbase,a6 ;DOS base address
5482 move.l filehd,d1 ;file handle in D1
5483 jsr write(a6) ;write data
5484 rts
5485
5486 After opening the file,you can call the subroutine from the main
5487 program with the following lines:
5488
5489 move.l #text,d2 ;pointer to data
5490 move.l #textend-text,d3 ;number of bytes
5491 bsr writedata ;write data in the file
5492
5493 Then close the file with:
5494
5495 bsr closefile ;close file
5496 bra end ;end program
5497
5498 After running the program,look at the directory of the diskette,
5499 you should find the file "testfile".It is just as long as your
5500 text.You want to read this file in,to make sure it contains the
5501 right data.
5502 You need the DOS function READ,which needs the same parameters as
5503 the WRITE function.You can use parameters for the number of bytes
5504 to read just part of the file.If you give a larger number than the
5505 file contains,the whole file is loaded.You'll find the number of
5506 bytes read in D0.
5507 Lets set up a field that as enough space for the data you want to
5508 read.You can do this with the following line:
5509
5510 field: blk.b 100 ;reserve 100 bytes
5511
5512 For the example data,this is plenty.If you want to load another
5513 file,you may need to reserve more space.
5514 Now lets write a subroutine to read the data.You always want to
5515 load whole files.You just need to pass the address of the buffer
5516 so the data is loaded into the subroutine.In the example,its the
5517 address "field".
5518 Heres the subroutine that reads the entire opened file into the
5519 memory area pointed to by D2:
5520
5521 read = -42 ; (6.5.2C)
5522 ...
5523 readdata: ;*read file
5524 move.l dosbase,a6 ;DOS base address in A6
5525 move.l filehd,d1 ;file handle in D1
5526 move.l #$ffffff,d3 ;read an arbitrary number of bytes
5527 jsr read(a6) ;read data
5528 rts
5529
5530 To use this routine to load the file into the buffer "field",use
5531 the following main program:
5532
5533 move,l #mode_old,d2 ;old file
5534 bsr openfile ;open file
5535 beq error ;did'nt work!
5536 move.l #field,d2 ;pointer to data buffer
5537 bsr readdata ;read file
5538 move.l d0,d6 ;save number of bytes in D6
5539 bsr closefile ;close file
5540 bra end ;program end
5541
5542 After assembling and starting this program,you can use the
5543 debugger to look at the data buffer that you filled with data from
5544 the file.In D6,you'll find the number of bytes that were read from
5545 the file.
5546
5547 6.5.3.Erase Files.
5548 ------------------
5549 Once you've experimented enough with the program above,you'll
5550 certainly want to erase the "Testfile"file.The DELETEFILE function
5551 in the DOS library has an offset of -72.It only needs 1 parameter.
5552 The parameter is passed in D1.The parameter is a pointer to the
5553 filename.The name must be closed with a null byte.
5554
5555 To erase "Testfile",use the following lines:
5556
5557 deletefile =-72 ; (6.5.3)
5558 ...
5559 move.l dosbase,a6 ;DOS base address in A6
5560 move.l #filename,d1 ;pointer to filename in D1
5561 jsr deletefile(a6) ;erase file
5562
5563 The file is deleted.You can't save the file with normal methods if
5564 you accidently erase it!You can use a trick that saves the data.
5565 We'll take a look at this trick later.Its used in lots of programs
5566
5567 6.5.4.Rename Files.
5568 -------------------
5569 When a text editing program writes a text that as be altered back
5570 to the disk,the old file usually isn't erased.Often the old file
5571 is renamed.For example,it might get the name "Backup".The new file
5572 is written to disk with the old name.
5573 The function in the DOS library that allows you to change the
5574 names of programs is called RENAME and has -78 as an offset.You
5575 need to pass two parameters-D1 as a pointer to the old name and D2
5576 as a pointer to the new name of the file.
5577
5578 To rename "Testfile"as "Backup"(before you erase it),use the
5579 following lines:
5580
5581 rename =-78
5582 ...
5583 move.l dosbase,a6 ;DOS base address in A6
5584 move.l #oldname,d1 ;pointer to old name in D1
5585 move.l #newname,d2 ;pointer to new name in D2
5586 jsr rename(a6) ;rename file
5587 ...
5588 oldname: dc.b "testfile",0
5589 newname: dc.b "backup",0
5590
5591 6.5.5.CLI Directory.
5592 --------------------
5593 Lets pretend you've programmed a text editor and started it.Now
5594 you want to load a text from disk and edit it-but whats the name
5595 of that file?
5596 You need a function to read and display the directory of the disk.
5597 There are several ways to do this.First lets use the easiest
5598 method.It doesn't require much programming and can be quite
5599 useful.
5600 The trick is to call the Dir or List programs that are in the C
5601 directory.You'll use the CLI commands.The DOS library contains a
5602 command called "Execute"with offset -222 that allows you to
5603 execute CLI commands.
5604 The function needs three parameters:
5605
5606 In D1 a pointer to a string closed with a zero that contains the
5607 name of the command to be executed.This string must
5608 contain the same command that you would give in the CLI.It
5609 can be a null pointer as well.
5610 In D2 the input file is determined.Normally theres a zero here.
5611 If however,you give the file handle of a text file,though,
5612 this file is read and interpreted as a command sequence.If
5613 you define a window as the input medium,you've programmed
5614 a new CLI window!
5615 In D3 the output file is determined.If there a zero here,the
5616 output of the commands (for example,DIR output) is sent to
5617 the standard CLI window.
5618
5619 To try this out,insert this subroutine in a program that has
5620 already opened the DOS library and a window.
5621
5622 execute = -222 ; (6.5.5)
5623 ...
5624 dir:
5625 move.l dosbase,a6 ;DOS base address in A6
5626 move.l #command,d1 ;pointer to command line
5627 clr.l d2 ;no input (CLI window)
5628 move.l conhandle,d3 ;output in our window
5629 jsr execute(a6) ;execute command
5630 rts
5631
5632 command:
5633 dc.b "dir",0
5634
5635 This program works with the List command as well.The disadvantage
5636 of this method is that the disk that the Workbench is loaded from
5637 must be in the drive or the system requests you to put it in.The
5638 Dir command is just a program,and the Amiga must load it before it
5639 can run.
5640 The disadvantage isn't too great.The program is short,and it
5641 allows you to use any CLI command in a program.
5642 Here is the complete program in AssemPro format that calls the dir
5643 program:
5644
5645 ;***** 6.5.5A DIR.ASM S.D.*****
5646
5647 openlib =-408
5648 closelib =-414
5649 ;execbase = 4 ;defined in AssemPro
5650 ;macros
5651
5652
5653 *calls to Amiga Dos:
5654
5655 open =-30
5656 close =-36
5657 execute =-222
5658 IoErr =-132
5659 mode_old = 1005
5660 alloc_abs =-$cc
5661
5662 ILABEL AssemPro:includes/Amiga.l ;AssemPro only
5663
5664 INIT_AMIGA ;AssemPro only
5665
5666 run:
5667 bsr init ;initialization
5668 bra test ;system test
5669
5670 init: ;system initialization and
5671 ;open
5672 move.l execbase,a6 ;number of execute-library
5673 lea dosname(pc),a1
5674 moveq #0,d0
5675 jsr openlib(a6) ;open DOS-library
5676 move.l d0,dosbase
5677 beq error
5678
5679 lea consolname(pc),a1 ;console definition
5680 move.l #mode_old,d0
5681 bsr openfile ;console open
5682 beq error
5683 move.l d0,conhandle
5684
5685 rts
5686
5687 test:
5688 bsr dir ;do directory
5689 bra qu ;quit and exit
5690
5691 dir:
5692 move.l dosbase,a6 ;DOS base address in A6
5693 move.l #command,d1 ;pointer to command line
5694 clr.l d2 ;no input (CLI window)
5695 move.l conhandle,d3 ;output in our window
5696 jsr execute(a6) ;execute command
5697 rts
5698
5699 error:
5700 move.l dosbase,a6
5701 jsr IoErr(a6)
5702 move.l d0,d5
5703
5704 move.l #-1,d7 ;flag
5705
5706 qu:
5707 move.l conhandle,d1 ;window close
5708 move.l dosbase,a6
5709 jsr close(a6)
5710
5711 move.l dosbase,a1 ;DOS.Lib close
5712 move.l execbase,a6
5713 jsr closelib(a6)
5714
5715 EXIT_AMIGA ;AssemPro only
5716
5717 openfile: ;open file
5718 move.l a1,d1 ;pointer to I/O-Definition-
5719 ;text
5720 move.l d0,d2
5721 move.l dosbase,a6
5722 jsr open(a6)
5723 tst.l d0
5724 rts
5725
5726 dosname: dc.b 'dos.library',0,0
5727 align.w
5728 dosbase: dc.l 0
5729 consolname: dc.b 'CON:0/100/640/100/** CLI-Test **',0
5730 align.w
5731 conhandle: dc.l 0
5732 command:
5733 dc.b "dir",0
5734
5735 end
5736
5737 6.5.6.Read Directory.
5738 ---------------------
5739 Now,lets look at another method that doesn't need the CLI.In this
5740 way,you can read the directory of any disk without having to play
5741 Disk Jockey.
5742 You need to writ a program that does what CLI's Dir program does.
5743 There are several steps.
5744 First you must give the system a key to the desired directory.That
5745 means you must call DOS'Lock function.It needs two parameters:
5746
5747 In D1 pass a pointer to a text that contains the name of the
5748 directory you wish to read.If,for example,you want to
5749 read the contents of the RAM disk,the text would be
5750 'RAM:',0.
5751 In D2 put the mode that determines whether to read or write.Let
5752 us use the "Read"(-2) mode.
5753
5754 You call the Lock function (offset -84) and get either a point to
5755 the key or a zero returned to you in the D0 register.If you get a
5756 zero,the call did'nt work,the file was'nt found.This function can
5757 be used to find if a file is on the disk.You use this function
5758 with the name and see if D0 comes back zero.If not,the file
5759 exists.
5760 Lets assume the file or path exists.You need to save the value
5761 that came back in D0.You'll need it for both functions that you'll
5762 call.
5763 The next function you need is called Examine.You use it to search
5764 the disk for an acceptable entry.It returns parameters like name,
5765 length and date that correspond to the entry.You need to reserve a
5766 memory block for this information and put the beginning of the
5767 block in D2 before calling the Examine function.Put the key you
5768 got from the Lock function in the D1 register.
5769 The memory area that is filled with information is called a
5770 FileInfoBlock.Its 260 bytes long and contains information about
5771 the file.The name starts in the 9th byte and ends with a null byte
5772 so you can easily print it with our "pmsg"routine.The information
5773 that Examine gives isn't about a particular file,but about the
5774 disk.The name in FileInfoBlock is the disk name.
5775 The Examine function sends the status back in the D0 register.
5776 Since the Lock function already tested if the file existed,evalua-
5777 ting the status really isn't necessary.
5778 Now to the function that you can use to read individual files from
5779 the directory.The function is called ExNext (Examine Next).This
5780 function searches for the next entry that fits the key every time
5781 it is called.ExNext gets the same parameters as Examine gets.
5782 However,the return parameter in D0 is more important here.
5783 The ExNext function is always called in the same way.It always
5784 gets the next entry of the directory.If no more entries exist in
5785 the directory,ExNext puts a zero in the D0 register.
5786 You need to continue performing this operation until there aren't
5787 any more entries.You can find this using the IoErr function from
5788 the DOS library.
5789 This function doesn't need any parameters.It returns the status of
5790 the last I/O operation that was performed in the D0 register.After
5791 the last ExNext,this value is 232,which means no_more_Entries.
5792
5793 Heres a complete routine for reading the directory of the disk in
5794 DFO:and displaying the contents in the window.
5795
5796 ; 6.5.5B.ASM
5797 ;***** DOS-Sample function 3/87 S.D. *****
5798
5799 openlib =-30-378
5800 closelib =-414
5801 exbase =4
5802
5803 * calls to amiga dos:
5804
5805 open =-30
5806 close =-30-6
5807 read =-30-12
5808 write =-30-18
5809 myinput =-30-24
5810 output =-30-30
5811 currdir =-30-96
5812 lock =-30-54
5813 examine =-30-72
5814 exnext =-30-78
5815 exit =-30-114
5816 IoErr =-30-102
5817 waitforch =-30-174
5818 mode = 0
5819 mode_old = 1005
5820 mode_new = 1006
5821 alloc_abs =-$cc
5822 free_mem =-$d2
5823
5824 ILABEL AssemPro:includes/Amiga.l ;AssemPro only
5825
5826 INIT_AMIGA ;AssemPro only
5827
5828 run:
5829 bsr init ;initialization
5830 bra test ;system-test
5831
5832 init: ;system initialization and
5833 ;open
5834 move.l exbase,a6 ;pointer to exec.library
5835 lea dosname(pc),a1
5836 moveq #0,d0
5837 jsr openlib(a6) ;open dos-library
5838 move.l do,dosbase
5839 beq error
5840
5841 lea consolname(pc),a1 ;console definition
5842 move.l #mode_old,d0
5843 bsr openfile ;console open
5844 beq error
5845 moveq d0,conhandle
5846
5847 rts
5848
5849 test:
5850 move.l #mytext,d0
5851 bsr pmsg ;test-text output
5852
5853 move.l dosbase,a6
5854 move.l #name,d1
5855 move.l #-2,d2
5856 jsr lock(a6)
5857 move.l d0,d5
5858 tst.l d0
5859 beq error
5860 move.l d0,locksav
5861
5862 move.l dosbase,a6
5863 move.l locksav,d1
5864 move.l #fileinfo,d2
5865 jsr examine(a6)
5866 move.l d0,d6
5867 tst.l d0
5868 beq error
5869
5870 loop:
5871 move.l dosbase,a6
5872 move.l locksav,d1
5873 move.l #fileinfo,d2
5874 jsr exnext(a6)
5875 tst.l d0
5876 beq error
5877
5878 move.l #fileinfo+8,d0
5879 bsr pmsg
5880 bsr pcrlf
5881 bra loop
5882
5883 error:
5884 move.l dosbase,a6
5885 jsr ioerr(a6)
5886 move.l d0,d6
5887
5888 move.l #presskey,d0
5889 bsr pmsg
5890 bsr getch
5891 move.l #-1,d7 ;flag
5892
5893 qu:
5894 move.l conhandle,d1 ;window close
5895 move.l dosbase,a6
5896 jsr close(a6)
5897
5898 move.l dosbase,a1 ;dos.lib close
5899 move.l exbase,a6
5900 jsr closelib(a6)
5901
5902 EXIT_AMIGA ;AssemPro only
5903
5904 openfile: ;open file
5905 move.l a1,d1 ;pointer to I/O-Definition-
5906 ;Text
5907 move.l d0,d2
5908 move.l dosbase,a6
5909 jsr open(a6)
5910 tst.l d0
5911 rts
5912
5913 pmsg: ;print message (D0)
5914 movem.l d0-d7/a0-a6,-(sp)
5915 move.l d0,a0
5916 move.l a0,d2
5917 clr.l d3
5918
5919 mess1:
5920 tst.b (a0)+
5921 beq mess2
5922 addq.l #1,d3
5923 bra mess1
5924
5925 mess2:
5926 move.l conhandle,d1
5927 move.l dosbase,a6
5928 jsr write(a6)
5929 movem.l (sp)+,d0-d7/a0-a6
5930 rts
5931
5932 pcrlf:
5933 move #10,d0
5934 bsr pchar
5935 move #13,d0
5936
5937 pchar: ;character in D0 output
5938 movem.l d0-d7/a0-a6,-(sp) ;save all
5939 move.l conhandle,d1
5940
5941 pch1:
5942 lea chbuff,a1
5943 move.b d0,(a1)
5944 move.l a1,d2
5945 move.l #1,d3
5946 move.l dosbase,a6
5947 jsr write(a6)
5948 movem.l (sp)+,d0-d7/a0-a6 ;restore all
5949 rts
5950
5951 scankey: ;test key
5952 move.l conhandle,d1
5953 move.l #500,d2 ;wait value
5954 move.l dosbase,a6
5955 jsr waitforch(a6)
5956 tst.l d0
5957 rts
5958
5959 readin: ;input from keyboard
5960 movem.l d0-d7/a0-a6,-(sp) ;registers
5961 lea inline+2,a2 ;pointer to input buffer
5962 clr.l (a2)
5963
5964 inplop:
5965 bsr getchr
5966 cmp.b #8,d0
5967 beq backspace
5968 cmp.b #127,d0 ;delete?
5969 beq backspace
5970 bsr pchar ;character output
5971 cmp.b #13,d0
5972 beq inputx
5973 move.b d0,(a2)+
5974 bra inplop
5975
5976 input:
5977 clr.b (a2)+
5978 sub.l #inline,a2
5979 move a2,inline ;length in inline+1
5980 movem.l (sp)+,d0-d7/a0-a6 ;registers
5981 rts
5982
5983 backspace:
5984 cmp.l #inline,a2 ;at beginning?
5985 beq inplop ;yes
5986 move.b #8,d0
5987 bsr pchar ;backspace
5988 move #32,d0
5989 bsr pchar ;blank
5990 move #8,d0
5991 bsr pchar ;backspace
5992 clr.b (a2)
5993 subq.l #1,a2
5994 bra inplop
5995
5996 getchr: ;get 1 character from keyboard
5997 move.l #1,d3 ;1 character
5998 move.l conhandle,d1
5999 lea inbuff,a1 ;buffer-address
6000 move.l a1,d2
6001 move.l dosbase,a6
6002 jsr read(a6)
6003 clr.l d0
6004 move.b inbuff,d0
6005 rts
6006
6007
6008 mytext: dc.b 'Directory of Diskette: DFO:',10,13,10,13,0,0
6009 dosname: dc.b 'dos.library',0,0
6010 presskey: dc.b 'Press thr Return key!!',0
6011 align.w
6012 dosbase: dc.l 0
6013 consolname: dc.b 'CON:0/100/640/100/** Directory-Test **',0
6014 name: dc.b 'DFO:',0
6015 align.w
6016 locksav: dc.l 0
6017 fileinfo: ds.l 20
6018 conhandle: dc.l 0
6019 inbuff: DS.B 8
6020 inline: DS.B 180
6021 chbuff DS.B 82
6022
6023 end
6024
6025 The FileInfoBlock contains the following entries:
6026
6027 Offset Name Meaning
6028 ----------------------------------------------------------------
6029 0 DiskKey.L Disk Number
6030 4 DieEntryType.L Entry Type (+=Directory,-=File)
6031 8 FileName 108 bytes with the filename
6032 116 Protection.L File Protected?
6033 120 EntryType.L Entry type
6034 124 Size.L Length of file in bytes
6035 128 NumBlocks.L Number of blocks
6036 132 Days.L Creation day
6037 136 Minute.L Creation time
6038 140 Tick.L Creation time
6039 144 Comment 116 bytes with comments
6040
6041 If you want to have the program output the file length as well,you
6042 can read the length with "move.l fileinfo+124,d0"and then use a
6043 conversion routine to produce a decimal number.You can output this
6044 result with the name.
6045
6046 6.5.7.Direct Access To Disk.
6047 ----------------------------
6048 There isn't a simple function in the library for accessing single
6049 disk sectors.Here,you must work with a device just like you did
6050 with speech output.This time you'll be working with the trackdisk.
6051 device.
6052 You want to work with this device to directly program the disk
6053 drives.Once you've built up the necessary program machinery,you
6054 can experiment with various commands for disk access.Remember that
6055 an error can cause the disk to be modified and thus unusable.Make
6056 sure you're using a non-essential disk.Don't use one which
6057 contains your only copy of something.
6058 The initialization here is similar to that for speech output.Here
6059 is the initialization routine for your program:
6060
6061 ;** Direct disk access via trackdisk.device ** (6.5.7)
6062
6063 openlib =-408
6064 closelib =-414
6065 execbase = 4
6066 open =-30
6067 close =-36
6068 opendevice =-444
6069 closedev =-450
6070 sendIo =-462
6071 read =-30-12
6072 write =-30-18
6073 waitforch =-30-174
6074 mode_old = 1005
6075
6076 run:
6077 bsr init ;initialization
6078 bra test ;system-test
6079
6080 init: ;initialize and open system
6081 move.l execbase,a6 ;pointer to exec.library
6082 lea dosname,a1
6083 moveq #0,d0
6084 jsr openlib(a6) ;open dos.library
6085 move.l d0,dosbase
6086 beq error
6087 lea diskio,a1 ;pointer to disk I/O area
6088 move.l #diskrep,14(a1) ;pointer to port
6089 clr.l d0 ;drive 0 (built in)
6090 clr.l d1 ;no flags
6091 lea trddevice,a0 ;pointer to device name
6092 jsr opendevice(a6) ;open trackdisk.device
6093 tst.l d0 ;error?
6094 bne error ;yes!
6095 move.l #consolname(pc),d1 ;console definition
6096 move.l #mode_old,d2 ;old mode
6097 move.l dosbase,a6 ;dos base address
6098 jsr open(a6) ;open window
6099 tst.l d0 ;error?
6100 beq error ;yes!
6101 move.l d0,conhandle ;else save handle
6102 rts ;done
6103
6104 test: ;place for test routine
6105
6106
6107 And now for the functions that take care of the various messages
6108 at the end of the program.
6109
6110
6111 error:
6112 move.l #-1,d7 ;flag for error (for SEKA)
6113
6114 qu:
6115 move.l execbase,a6 ;exec base address
6116 lea diskio,a1 ;pointer to disk I/O
6117 move.l 32(a1),d7 ;IO_ACTUAL in D7 (for testing)
6118 move #9,28(a1) ;command motor on/off
6119 move.l #0,36(a1) ;0=off,1=on,so turn motor
6120 jsr sendio(a6) ;off
6121 move.l conhandle,d1 ;close window
6122 move.l dosbase,a6
6123 jsr close(a6)
6124 move.l dosbase,d1 ;close dos.lib
6125 move.l execbase,a6
6126 jsr closelib(a6)
6127 lea diskio,a1
6128 jsr closedev(a6) ;close trackdisk.device
6129 rts
6130
6131
6132 Lets not forget the routine that waits for the user to press
6133 <Return>,so that you can watch the effects of the test function in
6134 peace:
6135
6136 getchr: ;get a character from keyboard
6137 move.l #1,d3 ;1 character
6138 move.l conhandle,d1 ;window handle
6139 move.l #inbuff,d2 ;buffer address
6140 move.l dosbase,a6 ;dos base address
6141 jsr read(a6) ;read character
6142 rts ;thats it
6143
6144
6145 The last thing you need is the section of code that declares the
6146 text and data fields that your program needs:
6147
6148 dosname: dc.b 'dos.library',0
6149 align
6150 consolname: dc.b 'RAW:0/100/640/50/** Wait window',0
6151 align
6152 trddevice: dc.b 'trackdisk.device',0
6153 align
6154 dosbase: dc.l 0 ;dos base address
6155 conhandle: dc.l 0 ;window handle
6156 inbuff: blk.b 80,0 ;keyboard buffer
6157 diskio: blk.l 20,0 ;I/O structure
6158 diskrep: blk.l 8,0 ;I/O port
6159 diskbuff: blk.b 512*2,0 ;place for 2 sectors
6160
6161 There,now you've done with the set up work.Lets look at how you
6162 can give commands to the disk drives.The first and easiest command
6163 is the one for turning the drive motor on and off.You've already
6164 seen this command in the program.This is command number nine.This
6165 number goes in the command word of the I/O structure (bytes 28 and
6166 29 of the structure).
6167 You need to pass a parameter that lets the computor know whether
6168 to turn the motor off or on.This information goes in the I/O long
6169 word that starts at byte 36:its zero for off,and one for on.
6170 You already chose the motor that should be turned on or off when
6171 you opened the device.You put the number of the chosen disk drive
6172 in D0-in your case you put a zero there because you are using the
6173 DFO:disk drive.
6174 Heres an overview of the commands you can use to access
6175 information on the disk:
6176
6177 No Name Function
6178 -----------------------------------------------------------------
6179 2 READ Read one or more sectors
6180 3 WRITE Write sectors
6181 4 UPDATE Update the track buffer
6182 5 CLEAR Erase track buffer
6183 9 MOTOR Turn motor on/off
6184 10 SEEK Search for a track
6185 11 FORMAT Format tracks
6186 12 REMOVE Initialize routine that is called when you
6187 remove the disk
6188 13 CHANGENUM Find out number of disk changes
6189 14 CHANGESTATE Test if disk is in drive
6190 15 PROTSTATUS Test if disk is write protected
6191
6192 You've already learned about command number nine.Lets look at the
6193 three commands you can use to make tests.These are the last three
6194 commands.They put a return value in the long word that begins in
6195 the 32nd byte in the I/O structure.This value was written in D7 in
6196 the program above for testing purposes.You can read its contents
6197 directly if you ran the program with AssemPro.
6198 Here is a simple routine that you can use to run one of these
6199 commands with:
6200
6201 test: ; (6.5.7B)
6202 lea diskio,a1 ;pointer to I/O structure
6203 move #13,28(a1) ;pass command (for example 13)
6204 move.l execbase,a6 ;execbase address in A6
6205 jsr sendio(a6) ;call function
6206
6207 If CHANGENUM (command 13) is executed,in D7 you'll get the number
6208 of times a disk was taken out and put in the drive.If you call the
6209 program,you'll get a value back.If you take the disk out and put
6210 it back in,the number is two higher the next time you call the
6211 program.
6212 The CHANGESTATE command (command 14) tells whether a disk is in
6213 the drive or not.If one is,a zero comes back.Otherwise,a $FF is
6214 returned.
6215 You get the same values back from the PROTSTATUS function (command
6216 15).Here a zero means that the disk isn't write protected,while
6217 $FF means that it is.
6218 Now lets look at the READ and WRITE functions.These operations
6219 need a few more parameters than the status functions.You need to
6220 pass the following parameters:
6221
6222 The address of the I/O buffer in the data pointer,the number of
6223 bytes to be transfered in I/O length,and the data address on the
6224 disk in I/O offset.
6225
6226 The number of data bytes must be a multiple of 512,since every
6227 sector is 512 bytes,and only whole sectors can be read.
6228
6229 The data address is the number of the first byte in the sector.If
6230 you want to use the first sector,the offset is zero.For the second
6231 sector,its 512,etc...The formula is:
6232
6233 offset = (sector_number -1) *512
6234
6235 Here is a routine that loads the first two sectors of the disk
6236 into the buffer:
6237
6238 test: (6.5.7C)
6239 lea diskio,a1
6240 move #2,28(a1) ;command:READ
6241 move.l #diskbuff,40(a1) ;buffer
6242 move.l #2*512,36(a1) ;length:2 sectors
6243 move.l #0*512,44(a1) ;offset:0 sectors
6244 move.l execbase,a6 ;exec base address
6245 jsr sendio(a6) ;start function
6246
6247 Start the program from the debugger and then look at the buffers
6248 contents after the program ends.You can find out the format of the
6249 disk here.If you want to read a sector thats being used,change the
6250 0 in the offset definition to 700 and start again.Its highly
6251 probable that theres some data there.
6252 To modify and write back the data that you've read from the disk,
6253 you need command number three,the WRITE command.The parameters are
6254 the same.
6255 If you've executed the WRITE commandyou're probably wondering why
6256 the disk light did'nt go on.Thats because the Amiga writes a track
6257 that as been read into a buffer on its own.It WRITE's data there
6258 as well.It won't write the data to disk until another track is
6259 accessed.
6260 You can have the data updated directly as well using command four,
6261 the UPDATE command.
6262 Command 11,the FORMAT command,is also quite interesting.This
6263 command needs a data field that is 11*512=5632 bytes long-the
6264 length of a track.The offset must be a multiple of this number so
6265 that you start at the beginning of a track.
6266 The length must be a multiple of 5632 as a result.If several
6267 tracks are formatted,each track is filled with the same data.
6268 You can use this function to easy write a disk copy program.You
6269 READ the source disk and then FORMAT the corresponding track on
6270 the destination disk.Thats how the DiskCopy program works-it
6271 reformats the destination disk.
6272 Command ten,the SEEK command,just needs the offset.It moves the
6273 Read/Write head of the drive to the position specified without
6274 making a disk access or testing if its at the right position.
6275 Command 12,the REMOVE command,is used to install an interrupt
6276 routine that is called when the disk is removed from the disk
6277 drive.The address of the interrupt structure is passed in the data
6278 pointer of the I/O structure.If theres a zero here,the interrupt
6279 routine is turned off.
6280
6281 Heres a complete example program in AssemPro format:
6282
6283 ;***** Track disk-Basic function 10/86 S.D. *****
6284
6285 ILABEL ASSEMPRO:includes/Amiga.l :AssemPro only
6286
6287 openlib =-30-378
6288 closelib =-414
6289 ;execbase = 4 ;defined in INIT_AMIGA
6290
6291 * calls to amiga dos:
6292
6293 open =-30
6294 close =-30-6
6295 opendevice =-444
6296 closedev =-450
6297 sendIo =-462
6298 read =-30-12
6299 write =-30-18
6300 waitforch =-30-174
6301 mode_old = 1005
6302
6303 INIT_AMIGA ;AssemPro only
6304
6305 run:
6306 bsr init ;initialization
6307 bra test ;system test
6308
6309 init: ;system initialization and
6310 ;open
6311 move.l execbase,a6 ;pointer to exec-library
6312 lea dosname,a1
6313 moveq #0,d0
6314 jsr openlib(a6) ;open dos-library
6315 move.l d0,dosbase
6316 beq error
6317
6318 lea diskio,a1
6319 move.l #diskrep,14(a1)
6320 clr.l d0
6321 clr.l d1
6322 lea trddevice,a0
6323 jsr opendevice(a6) ;open trackdisk.device
6324 tst.l d0
6325 bne error
6326
6327 bp:
6328 lea consolname(pc),a1 ;console-definition
6329 move.l #mode_old,d0
6330 bsr openfile ;console open
6331 beq error
6332 move.l d0,conhandle
6333
6334 rts
6335
6336 test:
6337 bsr accdisk
6338
6339 bsr getchr ;wait for character
6340 bra qu
6341
6342 error:
6343 move.l #-1,d7 ;flag
6344
6345 qu:
6346 move.l execbase,a6
6347 lea diskio,a1
6348 move #9,28(a1)
6349 move.l #0,36(a1)
6350 jsr sendio(a6)
6351
6352 move.l conhandle,d1 ;window close
6353 move.l dosbase,a6
6354 jsr close(a6)
6355
6356 move.l dosbase,a1 ;dos.lib close
6357 move.l execbase,a6
6358 jsr closelib(a6)
6359
6360 lea diskio,a1
6361 move.l 32(a1),d7
6362 jsr closedev(a6)
6363
6364 EXIT_AMIGA ;AssemPro only
6365
6366 openfile: ;open file
6367 move.l a1,d1 ;pointer to the I/O-definition
6368 ;text
6369 move.l d0,d2
6370 move.l dosbase,a6
6371 jsr open(a6)
6372 tst.l d0
6373 rts
6374
6375 scankey: ;test for key
6376 move.l conhandle,d1
6377 move.l #500,d2 ;wait value
6378 move.l dosbase,a6
6379 jsr waitforch(a6)
6380 tst.l d0
6381 rts
6382
6383 getchr: ;get one character from
6384 ;keyboard
6385 move.l #1,d3 ;1 character
6386 move.l conhandle,d1
6387 lea inbuff,a1 ;buffer-address
6388 move.l a1,d2
6389 move.l dosbase,a6
6390 jsr read(a6)
6391 clr.l d0
6392 move.b inbuff,d0
6393 rts
6394
6395 accdisk:
6396 lea diskio,a1
6397 move #2,28(a1) ;command:READ
6398 move.l #diskbuff,40(a1) ;buffer
6399 move.l #2*512,36(a1) ;length:2 sectors
6400 move.l #20*512,44(a1) ;offset: n sectors
6401 move.l execbase,a6
6402 jsr sendio(a6)
6403 rts
6404
6405 dosname: dc.b 'dos.library',0,0
6406 align.w
6407 dosbase: dc.l 0
6408 consolname: dc.b 'RAW:0/100/640/100/** Test-Window S.D.V0.1',0
6409 trddevice: dc.b 'trackdisk.device',0
6410 align.w
6411 conhandle dc.l 0
6412 inbuff: ds.b 8
6413 diskio: ds.l 20,0
6414 diskrep: ds.l 8,0
6415 diskbuff: ds.b 512*2,0
6416
6417 end
6418
6419 Chapter 7.
6420 ----------
6421 7.Working With Intuition.
6422 -------------------------
6423 Now that you've learned so much about machine language,lets look
6424 at the special features of the Amiga.Lets look at the operating
6425 system Intuition that is in charge of windows,screens,the mouse
6426 and lots of other things.Beforetaking a look at these beautiful
6427 features,theres some bad news.
6428 First,though,lets here the good news.Since Intuition has so many
6429 functions,it allows you to be very creative in programming your
6430 ideas.The disadvantage is that the flexibility means that you have
6431 to use a lot of parameters,and that makes for a lot of tedious
6432 work.
6433 However,this is no grounds for panic.Once you've built up the
6434 necessary routines,the programming and experimentation becomes
6435 increasingly interesting.Before you try out new program variations
6436 you should save your source code to disk,because Intuition gets
6437 fairly upset about bad parameters and often responds by crashing
6438 the system.
6439 Now lets get to work.To start working with Intuition,you need the
6440 Intuition library.You can load it with the OpenLibrary function
6441 from the EXEC library.Heres the subroutine that takes care of
6442 initialization.
6443
6444 openlib =-408
6445 execbase = 4
6446
6447 run:
6448 bsr openint ;load intuition library
6449 ...
6450
6451 openint: ;*initialize and open system
6452 move.l execbase,a6 ;exec base address
6453 lea intname,a1 ;name of intuition library
6454 jsr openlib(a6) ;open intuition
6455 move.l d0,intbase ;save intuition base address
6456 rts
6457
6458 intname: dc.b "intuition.library",0
6459 align
6460 intbase: dc.l 0 ;base address of intuition
6461
6462 When your program is finished,you need to close the screens,the
6463 window and the library.To do this,use the CloseLibrary function
6464 from the EXEC library.It has an offset of -414.
6465 Heres the subroutine:
6466
6467 closelibrary =-414
6468 ...
6469 closeint: ;*close intuition
6470 move.l execbase,a6 ;exec base address in A6
6471 move.l intbase,a1 ;intuition base address in A1
6472 jsr closelibrary(a6) ;close intuition
6473 rts ;done
6474
6475 Now that you've got that taken care of,you can finally start
6476 working with Intuition.
6477
6478 7.1.Open Screen.
6479 ----------------
6480 Intuition is a graphics operating system.For this reason,you'll be
6481 working with the screen.Its even more interesting to work with
6482 several screens at the same time.However,you only have one monitor
6483 on the Amiga.
6484 You can open as many screens as you like (at least,as long as
6485 theres some memory available).You can open a window,display menus
6486 and do I/O's there.The individual screens are fully independant.
6487 You can work with all of them simultaneously on the monitor.
6488 You can move individual screens forward and back to your hearts
6489 content.You can also press the left <Amiga> key and then an "m"to
6490 return to the workbench screen after getting into the different
6491 screens.
6492 You want to begin programming Intuition by setting up a screen.You
6493 have already loaded the Intuition library,so you can use the Open-
6494 Screen function.
6495 Wait a minute!What should the screen look like,where should it go,
6496 and what form should it have?You need to look at the options for
6497 the form of the screen you have available.
6498 The input to the screen is in the form of a table that has 13
6499 entries.Lets take a look at the parameters that you need for our
6500 screen.
6501 You'll start the table with the label "screen_defs"which must be
6502 at an even address:
6503
6504 align
6505 screen_defs: ;The screen table begins here
6506
6507 The first bit of information that the screen needs is the position
6508 and size.Lets have it start in the upper left corner and fill the
6509 entire screen.You'll use the positions X=0 and Y=0,the width 320
6510 and the height 200.This means that your screen is the maximum
6511 size.
6512
6513 x_pos: dc.w 0 ;X-Position
6514 y_pos: dc.w 0 ;Y-Position
6515 width: dc.w 320 ;width
6516 height: dc.w 200 ;height
6517
6518 Next you need to decide which colors should be displayed.That
6519 depends on the number of bitplanes,on the depth.Lets choose two.
6520 That means you have 2^2 (4) colours available.Lets choose two,
6521 since four colours is usually plenty.
6522
6523 depth: dc.w 2 ;number of bitplanes
6524
6525 Next you need to choose the colour of the title line and the
6526 function symbols.Give the number of the colour register:
6527
6528 detail_pen: dc.b 0 ;colour of text,etc...
6529
6530 Now for the colour of the text background:
6531
6532 block_pen dc.b 1 ;background colour
6533
6534 Make sure that these two inputs fit in a byte.The colours are
6535 normally the following (if the standard values have'nt been
6536 changed).You'll notice that the number of colours depends on the
6537 number of bit maps.
6538
6539 Pen Colour
6540 ---------------------------------------------------------
6541 0 Background (blue)
6542 1 White
6543 for two bit planes
6544 2 Black
6545 3 Red
6546 for three bit planes
6547 4 Blue
6548 5 Violet
6549 6 Turquoise
6550 7 White
6551 for four bit planes
6552 8 Black
6553 9 Red
6554 10 Green
6555 11 Brown
6556 12 Blue
6557 13 Blue
6558 14 Green
6559 15 Green
6560
6561 The next word contains the bits that describe the appearance of
6562 the screen.The bits are:
6563
6564 Bit Value Name Meaning
6565 ---------------------------------------------------------------
6566 1 2 GENLOCK_VIDEO
6567 2 4 INTERLACE Puts the screen in Interlace
6568 mode.The resolution and thus the
6569 maximum screen size are doubled.
6570 6 $40 PFBA
6571 7 $80 EXTRA_HALFBRITE
6572 8 $100 GENLOCL_AUDIO
6573 10 $400 DBLPF Divides the screen into a border
6574 and character area.
6575 11 $800 HOLDNMODIFY Turns on Hold-and-Modify mode.
6576 13 $2000 VP_HIDE
6577 14 $4000 SPRITES Allows sprites to be used.
6578 15 $8000 MODE_640 Turns on the highest resolution
6579 graphics for the screen(640x400).
6580
6581 Choose the value two (normal) for your example screen:
6582
6583 view_modes: dc.w 2 ;representation mode
6584
6585 The following word is constructed in such away that each bit as
6586 its own meaning.Use this to set what sort of screen it is.Choose
6587 15 so the screen is a "Custom screen",which allows you all of the
6588 options.
6589
6590 screen_type: dc.w 15 ;screen type:custom screen
6591
6592 Next theres a pointer to the character set to be used for all
6593 output to the screen.If you don't want to install your own
6594 character set,just put a zero here,and the standard character set
6595 is used.
6596
6597 font: dc.l 0 ;character set:standard
6598
6599 Next theres a pointer to the text thats used as the name of the
6600 screen.The text ends with a zero,just like window names must.
6601
6602 title: dc.l name ;pointer to title text
6603
6604 Next comes a long word that defines the gadgets.These gadgets
6605 represent the functions,like "Bring forward",that can be accessed
6606 via a mouse click in the screen.The long word in this table is a
6607 pointer to a list which specifies the gadgets.These aren't the
6608 system gadgets.However,you're only using system gadgets here,so
6609 put a zero here.
6610
6611 gadgets: dc.l 0 ;no gadgets
6612
6613 Finally theres a long word that you only need if you want to use
6614 the special bitmap just for your screen.Since this isn't the case,
6615 just put a zero here.
6616
6617 bitmap: dc.l 0 ;no bitmap
6618
6619 Thats it for the list entries that you need to define the screen.
6620 You still need the text for the name of the screen.Enter the
6621 following:
6622
6623 sname: dc.b 'Our Screen',0 ;screen title
6624
6625 Heres a quick overview of the list:
6626
6627 align
6628 screen_defs: ;*The screen ta
6629 x_pos: dc.w 0 ;X-position
6630 y_pos: dc.w 0 ;Y-position
6631 width: dc.w 320 ;width
6632 height: dc.w 200 ;height
6633 depth: dc.w 2 ;number of bitplanes
6634 detail_pen: dc.b 0 ;colour of the text,etc...
6635 block_pen: dc.b 1 ;background colour
6636 view_modes: dc.w 2 ;representation mode
6637 screen_type: dc.w 15 ;screen type:custom screen
6638 font: dc.l 0 ;character set:standard
6639 title: dc.l sname ;pointer to title text
6640 gadgets: dc.l 0 ;no gadgets
6641 bitmap: dc.l 0 ;no bit map
6642 sname: dc.b 'Our Screen',0 ;screen title
6643
6644 Once you've decided on the parameters,its very easy to open the
6645 screen.You need Intuitions OpenScreen function.Its offset is -198
6646 and it only needs one parameter,the address of the parameter
6647 table.The program fragment looks like this:
6648
6649 openscreen =-198
6650 bsr openint ;open intuition
6651 bsr scropen ;open screen
6652 ...
6653 scropen: ;*open screen
6654 move.l intbase,a6 ;intuition base address in A6
6655 lea screen_defs,a0 ;pointer to table
6656 jsr openscreen(a6) ;and open
6657 move.l d0,screenhd ;save screen handle
6658 rts ;return to main program
6659 ...
6660 screen_defs: ;table info follows
6661
6662 Now the Amigas Workbench screen is covered by your screen.Now you
6663 can do what you want with it until the program is done.Afterwards,
6664 the screen must be closed again,so that you can see the Workbench
6665 screen again.
6666 Use the CloseScreen function (offset -66) to do this.The only
6667 parameter it needs is the pointer to the screen structure you got
6668 back from the OpenScreen function.
6669
6670 closescreen =-66
6671 ...
6672 scrclose: ;* close screen
6673 move.l intbase,a6 ;intuition base address in A6
6674 move.l screenhd,a0 ;screen handle in A0
6675 jsr closescreen(a6) ;clos screen
6676 rts ;done
6677
6678 The long word that OpenScreen returned to you is a pointer to a
6679 screen structure that contains all the needed data about the
6680 screen.Besides the data which was given,there is a pointer in the
6681 screen area for individual bit planes,etc...
6682 The form of this structure is fairly complicated and contains some
6683 data that you can't use.Several of the parameters are interesting,
6684 however.Heres a selection of usable parameters:
6685
6686 No Name Function
6687 ------------------------------------------------------------------
6688 0 (NextScreen.L) Pointer to next screen.
6689 4 (FirstWindow) Pointer to first window structure
6690 8 (LeftEdge.W)
6691 $A (TopEdge.W) Position of screen
6692 $C (Width.W) Width
6693 $E (Height.W) Height
6694 $10 (MouseY.W)
6695 $12 (MouseX.W) Mouse position in the screen
6696 $14 (Flags.W) Screen flags
6697 $16 (Title.L) Pointer to title text
6698 $1A (DefaultTitle) Pointer to normal title
6699 $28 (Font.L) Pointer to character set
6700 $C0 (Plane0.L) Pointer to bitplane 0
6701 $C4 (Plane1.L) Pointer to bitplane 1
6702 $C8 (Plane2.L) Pointer to bitplane 2
6703 $CC (Plane3.L) Pointer to bitplane 3
6704
6705 An example of an application for the plane pointer is writing and
6706 using your own character routine.Next you want to move the address
6707 of the plane into an address register as follows:
6708
6709 move.l screenhd,a5 ;screen pointer in A5
6710 move.l $c0(a5),a5 ;bitplane 0-pointer in A5
6711
6712 If you want to try this,do the following:
6713
6714 move.l screenhd,a5 ;screen pointer in A5
6715 move.l $c0(a5),a5 ;bitplane 0-pointer in A5
6716 move #$20,d0 ;Counter D0=$20
6717
6718 lop1:
6719 move d0,(a5) ;write counter bits in picture
6720 add.l #80,a5 ;address+80,next line
6721 dbra d0,lop1 ;continue until D0 < 0
6722
6723 This program draws a white,square pattern that corresponds to the
6724 bit pattern for the numbers $20 to 0.This isn't a particularly
6725 useful program,but it shows how easy it is to write from a machine
6726 language program directly to the screen.If you change the offset
6727 in the second line to $C4,the pattern is read.
6728 You can move the entire screen with the normal technique of moving
6729 the mouse pointer into the upper border and moving it up and down
6730 with the left mouse key depressed.You can do the same with a
6731 program.
6732 Lets move the screen without the mouse.Use the joystick for
6733 demonstration purposes.Put the joystick in port two.As you saw in
6734 the chapter on the hardware register,you can read memory location
6735 $DFF00C to find information about the joystick.You can find the
6736 direction the screen should be moved here.
6737 Moving the screen requires another Intuition function.You use the
6738 MoveScreen function which as an offset of -162 and needs three
6739 parameters to do this.The parameters are:
6740
6741 In A0 the pointer to the screen structure that you got back in
6742 D0 when you opened the screen.(You saved it in "screenhd")
6743 In D1 the desired movement in the Y-direction,the vertical
6744 direction.
6745 In D0 the horizontal movement in the X-direction.The varient
6746 doesn't work so you can only move the screen vertically.
6747
6748 Insert the following lines in your program:
6749
6750 MoveScreen =-162
6751 ...
6752 scrmove: ;*move screen D0 to the right
6753 ;and D1 down
6754 move.l intbase,a6 ;intuition base address in A6
6755 move.l screenhd,a0 ;screen handle in A0
6756 clr.l d0 ;no horizontal movement
6757 jsr movescreen(a6) ;move screen
6758 rts ;done
6759
6760 Now your looking at a complete program that goes through the
6761 following steps:
6762
6763 1. Opens the Intuition library
6764 2. Opens the screen
6765 3. Moves the screen in the direction specified by the joystick in
6766 port two
6767 4. Closes the screen when the fire button is hit
6768 5. Closes the Intuition library
6769 6. Ends
6770
6771 Here is the complete program including the subroutines,so you'll
6772 have it all in one spot:
6773
6774 ;** Demo program to open and move a screen **
6775
6776 movescreen =-162
6777 openscreen =-198
6778 closescreen =-66
6779 closelibrary =-414
6780 openlib =-408 ;open library
6781 execbase = 4 ;exec base address
6782 joy2 =$dff00c ;joystick 2 data
6783 fire =$bfe001 ;firebutton 2:bit 7
6784
6785 run:
6786 bsr openint ;open intuition
6787 bsr scropen ;open screen
6788 move joy2,d6 ;save joystick info
6789
6790 loop:
6791 tst.b fire ;test fire button
6792 bpl ende ;pressed down:done
6793 move joy2,d0 ;basic info in D0
6794 sub d6,d0 ;subtract new data
6795 cmp #$0100,d0 ;up?
6796 bne noup ;no
6797 move.l #-1,d1 ;dy=-1 direction y
6798 bsr scrmove ;move up
6799 bra loop
6800
6801 noup:
6802 cmp #$0001,d0 ;down?
6803 bne loop ;no
6804 move.l #1,d1 ;dy=1
6805 bsr scrmove ;move down
6806 bra loop
6807
6808 ende:
6809 bsr scrclose ;close screen
6810 bsr closeint ;close intuition
6811 rts ;done!
6812
6813 openint: ;*initialize and open system
6814 move.l execbase,a6 ;exec base address
6815 lea intname,a1 ;name of intuition library
6816 jsr openlib(a6) ;open intuition
6817 move.l d0,intbase ;save intuition base address
6818 rts
6819
6820 closeint: ;*close intuition
6821 move.l execbase,a6 ;exec base address in A6
6822 move.l intbase,a1 ;intuition base address in A1
6823 jsr closelibrary(a6) ;close intuition
6824 rts ;done
6825
6826 scropen: ;*open screen
6827 move.l intbase,a6 ;intuition base address in A6
6828 lea screen_defs,a0 ;pointer to table
6829 jsr openscreen(a6) ;open
6830 move.l d0,screenhd ;save screen handle
6831 rts ;return to main program
6832
6833 scrclose: ;*close screen
6834 move.l intbase,a6 ;intuition base address in A6
6835 move.l screenhd,a0 ;screen handle in A0
6836 jsr closescreen(a6) ;close screen
6837 rts ;done
6838
6839 scrmove: ;move screen D0 right/D1 down
6840 move.l intbase,a6 ;intuition base address in A6
6841 move.l screenhd,a0 ;screen handle in A0
6842 clr.l d0 ;no horizontal movement
6843 jsr movescreen(a6) ;and move
6844 rts ;done
6845 align
6846
6847 screen_defs: ;*screen table begins here
6848 x_pos: dc.w 0 ;X-position
6849 y_pos: dc.w 0 ;Y-position
6850 width: dc.w 320 ;width
6851 height: dc.w 200 ;height
6852 depth: dc.w 2 ;number of bitplanes
6853 detail_pen: dc.b 1 ;Text colour=white
6854 block_pen: dc.b 3 ;background colour=red
6855 view_modes: dc.w 2 ;representation mode
6856 screen_type dc.w 15 ;screen type:custom screen
6857 font: dc.l 0 ;standard character set
6858 title: dc.l sname ;pointer to title text
6859 gadgets: dc.l 0 ;no gadgets
6860 bitmap: dc.l 0 ;no bit map
6861 intbase: dc.l 0 ;base address of intuition
6862 screenhd: dc.l 0 ;screen handle
6863 intname: dc.b 'intuition.library',0
6864 align
6865 sname: dc.b 'Our Screen',0 ;Screen title
6866 align
6867 end
6868
6869 From this example,you can see how easy scrolling actually is.
6870 Another easy thing to do is to use the DisplayBeep function.It as
6871 an offset -96;the only parameter it needs is the screen pointer
6872 that you stored in the "screenhd"memory block.This function covers
6873 the screen with an orange colour for a short while.The screen is
6874 not changed.The beep function can be used as follows:
6875
6876 DisplayBeep: =-96
6877 ...
6878 move.l intbase,a6 ;intuition base address in A6
6879 move.l screenhd,a0 ;screen pointer in A0
6880 jsr displaybeep(a6) ;light up screen
6881
6882 If you put a zero instead of a screen pointer in A0,the whole
6883 screen blinks.
6884 Good,now you have your own screen that you can move up and down.
6885 What good is it if you can't put anything on it?Lets open a window
6886 on the screen!
6887
6888 7.2.Open Window.
6889 ----------------
6890 As you saw in the chapter on program initialization,its easy to
6891 open a window with the DOS library.You can't use this method on
6892 your own screen however.You need to use another method that can
6893 open any window on any screen.
6894 Intuition has a function called OpenWindow which handles this sort
6895 of work.It has an offset of -204 and needs only one parameter,a
6896 pointer to a window definition table.This pointer goes in register
6897 A0.
6898 This table is very similar to the one used to define the screen.
6899 The first four values specify the X-and Y-positions,the width,and
6900 the height of the window to be opened.Heres an example:
6901
6902 align
6903 window_defs:
6904 dc.w 10 ;x-position
6905 dc.w 20 ;y-position
6906 dc.w 300 ;width
6907 dc.w 150 ;height
6908
6909 Next come two bytes that define the colour of the letters on the
6910 background:
6911
6912 dc.b 1 ;white letter colour
6913 dc.b 3 ;on a red background
6914
6915 The next long word contains the IDCMP flags in its bits.The bits
6916 determine the circumstances under which Intuition sends a message
6917 to the program.The bits have the following meanings:
6918
6919 Bit Value Name Meaning
6920 -----------------------------------------------------------------
6921 0 $000001 SIZEVERIFY
6922 1 $000002 NEWSIZE Window size changed
6923 2 $000004 REFRESHWINDOW
6924 3 $000008 MOUSEBUTTONS Mouse key hit
6925 4 $000010 MOUSEMOVE Mouse moved
6926 5 $000020 GADGETDOWN A special gadget chosen
6927 6 $000040 GADGETUP Same as above
6928 7 $000080 REQSET
6929 8 $000100 MENUPICK A menu item chosen
6930 9 $000200 CLOSEWINDOW A window closed
6931 10 $000400 RAWKEY A key pressed
6932 11 $000800 REQVERIFY
6933 12 $001000 REQCLEAR
6934 13 $002000 MENUVERIFY
6935 14 $004000 NEWPREFS Preferences modified
6936 15 $008000 DISKINSERTED A disk put in
6937 16 $010000 DISKREMOVED A disk taken out
6938 17 $020000 WBENCHMESSAGE
6939 18 $040000 ACTIVEWINDOW A window activated
6940 19 $080000 INACTIVEWINDOW A window deactivated
6941 20 $100000 DELTAMOVE Report relative mouse movement
6942
6943 If you want your first window to respond only by clicking on the
6944 close symbol,write the following:
6945
6946 dc.l $200 ;IDCMP flags:CLOSEWINDOW
6947
6948 Next comes a long word whose bits determine the windows type.You
6949 can use this to construct a window to your exact specifications.
6950 This is quite different from windows opened with the DOS function.
6951 The bits mean:
6952
6953 Bit Value Name Meaning
6954 ------------------------------------------------------------------
6955 0 $0000001 WINDOWSIZING Window size is changeable
6956 1 $0000002 WINDOWDRAG Window is moveable
6957 2 $0000004 WINDOWDEPTH Window covering is posible
6958 3 $0000008 WINDOWCLOSE Window close symbol
6959 4 $0000010 SIZEBRIGHT
6960 5 $0000020 SIZEBOTTOM
6961 6 $0000040 SIMPLE_REFRESH New drawing manuel
6962 7 $0000080 SUPER_BITMAP Save the windows contents
6963 8 $0000100 BACKDROP Move window back
6964 9 $0000200 REPORTMOUSE Report mouse co-ordinates
6965 10 $0000400 GIMMEZEROZERO
6966 11 $0000800 BORDERLESS Window without border
6967 12 $0001000 ACTIVATE Window active
6968 13 $0002000 WINDOWACTIVATE
6969 14 $0004000 INREQUEST
6970 15 $0008000 MENUSTATE
6971 16 $0010000 RMBTRAP Right mouse key:no menu
6972 17 $0020000 NOCAREREFRESH No refresh message
6973 24 $1000000 WINDOWREFRESH
6974 25 $2000000 WBENCHWINDOW
6975
6976 To refresh is to rebuild the window contents when necessary,for
6977 instance when the windows size is changed.If none of the refresh
6978 bits are set,you're in Smart-Refresh-Mode.In this case,Intuition
6979 takes care of refreshing the window.This is the easiest method.
6980 If you choose the value $100F as the type for your example window,
6981 the window is active once its opened,and it has all the system
6982 gadgets:
6983
6984 dc.l $100F ;ACTIVATE and all gadgets
6985
6986 The next long word in the list allows you to use your own gadgets
6987 in the window.This long word is a pointer to the structure of a
6988 your gadget.Since you don't want this,just put a zero here.
6989
6990 dc.l 0 ;first gadget:no gadgets of our own
6991
6992 The next long word is a pointer to a graphics structure so you can
6993 design your own symbol for checking menu points.Put a zero here.
6994 You'll use the standard sign:
6995
6996 dc.l windowname ;pointer to window name
6997
6998 The next long word is a pointer to the screen structure that you
6999 got back after calling the OpenScreen function.The easiest way to
7000 do this is to save the pointer to this location in the buffer:
7001
7002 screenhd: dc.l 0 ;screen pointer
7003
7004 The next long word is a pointer to a bit map if you want one of
7005 your own for the window.Since you don't want one,put a zero here.
7006
7007 dc.l 0 ;no bit map of our own
7008
7009 Next come four values that set the maximum and minimum width and
7010 height of the window:
7011
7012 dc.w 150 ;smallest width
7013 dc.w 50 ;smallest height
7014 dc.w 320 ;maximum width
7015 dc.w 200 ;maximum height
7016
7017 The last value in the list is the screen type of the screen the
7018 window is located in.Put a 15 here.You're using our screen as a
7019 custom screen:
7020
7021 dc.w 15 ;screen type:custom screen
7022
7023 Heres a quick overview of the whole list:
7024
7025 align
7026 window_prefs:
7027 dc.w 10 ;X-position
7028 dc.w 20 ;Y-position
7029 dc.w 300 ;width
7030 dc.w 150 ;height
7031 dc.b 1 ;white print colour
7032 dc.b 3 ;on red background
7033 dc.l $200 ;IDCMP flags:CLOSEWINDOW
7034 dc.l $100f ;ACTIVATE and all gadgets
7035 dc.l 0 ;first gadget:no gadgets of
7036 ;our own
7037 dc.l 0 ;checkmark:standard
7038 dc.l windowname ;pointer to window name
7039 screenhd: dc.l 0 ;screen pointer
7040 dc.l 0 ;no bitmap of our own
7041 dc.w 150 ;smallest width
7042 dc.w 50 ;smallest height
7043 dc.w 320 ;maximum width
7044 dc.w 200 ;maximum height
7045 dc.w 15 ;screen type:custom screen
7046
7047 ;and here comes the window name:
7048 windowname: dc.b 'Our Window',0
7049 align
7050
7051 Insert these lines in the program you listed above.Here are two
7052 subroutines for opening and closing the window:
7053
7054 openwindow =-204
7055 closewindow =-72
7056 ...
7057 windopen:
7058 move.l intbase,a6 ;intuition base address in A6
7059 lea windowdef,a0 ;pointer to window definition
7060 jsr openwindow(a6) ;open window
7061 move.l d0,windowhd ;save window handle
7062 rts
7063
7064 windclose:
7065 move.l intbase,a6 ;intuition base address in A6
7066 move.l windowhd,a0 ;window handle
7067 jsr closewindow(a6) ;close window
7068 rts
7069 ...
7070 windowhd: dc.l 0 ;window handle
7071
7072 Now you can insert a "bsr windowopen"after the "bsr scropen"and a
7073 "bsr windclose"before the "bsr scrclose"command.Once you've
7074 started the program,move the window around in the screen.You'll
7075 find that you can't move the window out of the screen with the
7076 mouse.
7077 The window in the example has the close gadget in the upper left
7078 corner.Normally if you click it,the window is closed.Try clicking
7079 it.You'll find that nothing happens.
7080 The display of this and all other gadgets,as well as other events
7081 must be programmed in,since Intuition doesn't know which action
7082 causes which event.We'll take a look at how to handle this in the
7083 next chapter.
7084
7085 7.3.Requesters.
7086 ---------------
7087 If you only have one disk drive,you've certainly seen the Amiga
7088 message,"Please insert xxx in unit 0",a lot.This window is another
7089 that has two fields for clicking.This sort of message with a
7090 choice of options is called a requester.
7091 You want to take a look at how to program a requester.First,you
7092 need a window for the requester to appear in.You opened a window
7093 of this sort in the example program.
7094 To display a requester,use the Intuition function AutoRequest
7095 (offset -348).It takes care of drawing and managing the requester.
7096 This function needs the following parameters:
7097
7098 In A0 The pointer to the window structure that you put in
7099 "windowhd".
7100 In A1 A pointer to the text structure that should stand over the
7101 choice buttons.
7102 In A2 Same as above for the text of the left button.
7103 In A3 Same as above for the right button.
7104 In D0 The IDCMP flag which lets you know what event should go
7105 with the clicking of the left button.
7106 In D1 Same as above for the right button.
7107 In D2 The width of the whole requester.
7108 In D3 The height of the requester.
7109
7110 Insert the following lines in your program:
7111
7112 autorequest =-348
7113 ...
7114 request:
7115 move.l windowhd,a0 ;pointer to window structure
7116 lea btext,a1
7117 lea ltext,a2 ;pointer to text structure
7118 lea rtext,a3
7119 move.l #0,d0 ;left activates by clicking
7120 move.l #0,d1 ;right activates by clicking
7121 move.l #180,d2 ;width and
7122 move.l #80,d3 ;height of requester
7123 move.l intbase,a6 ;intuition base address
7124 jsr autorequest(a6) ;display requester
7125 rts
7126
7127 The flags passed in D0 and D1 offer some interesting posibilites.
7128 The system messages that tells you to enter a particular disk are
7129 overlooked when the DISKINSERTED flag is similar.Putting a disk in
7130 brings about the same responce as clicking the "Retry"button.
7131 Whats new is the use of a text structure.Use three of them.Text
7132 structures are lists that contain entries for the text that you
7133 need.
7134 These lists begin with two bytes that are used to define the
7135 colour.The first byte is the colour of the text.The second is for
7136 the background colour.Here this doesn't have any meaning.
7137
7138 btext:
7139 dc.b 2 ;black text colour
7140 dc.b 0 ;background colour
7141
7142 The next byte specifies the character mode.A zero means that the
7143 text is output normally.A four means the text is output inverted.
7144
7145 dc.b 0 ;normal text representation
7146
7147 The next entries are words.For this reason the addresses must be
7148 even,so you need to either insert another byte or use the "align"
7149 pseudo-op.The following words are the X-and Y-position of the text
7150 relative to the upper left corner of the requester.
7151
7152 dc.w 10 ;X-position
7153 dc.w 5 ;Y-position relative to upper
7154 ;left corner
7155
7156 Next,theres a pointer to the character set that is used.Put a zero
7157 here to use the standard set.
7158
7159 dc.l 0 ;standard character set
7160
7161 Next you need to give the address of the text that should be
7162 output.This text must be closed with a null byte.
7163
7164 dc.l text ;pointer to text
7165
7166 You need a long word at the end of the list that is either a
7167 pointer to another text or a zero if no more text is needed.
7168
7169 dc.l 0 ;no more text
7170
7171 Here are the three text structures that you need for the example:
7172
7173 btext: ;text structure for the title
7174 dc.b 0,1 ;colour
7175 dc.b 0 ;mode
7176 align
7177 dc.w 10,10 ;text position
7178 dc.l 0 ;standard font
7179 dc.l bodytxt ;pointer to text
7180 dc.l 0 ;no more text
7181
7182 bodytxt:
7183 dc.b "Requester Text",0
7184 align
7185 ltext: ;text structure of left button
7186 dc.b 0,1 ;colour
7187 dc.b 0 ;mode
7188 align
7189 dc.w 5,3 ;text position
7190 dc.l 0 ;standard font
7191 dc.l lefttext ;pointer to text
7192 dc.l 0 ;no more text
7193
7194 lefttext:
7195 dc.b "left",0
7196 align
7197
7198 rtext:
7199 dc.b 0,1 ;colour
7200 dc.b 0 ;mode
7201 align
7202 dc.w 5,3 ;text position
7203 dc.l 0 ;standard font
7204 dc.l righttext ;pointer to text
7205 dc.l 0 ;no more text
7206
7207 righttext:
7208 dc.b "right",0
7209 align
7210
7211 After calling the requester,D0 contains the information about
7212 which of the buttons were pressed,and in which button the event
7213 took place.If D0 is zero,it was the right button.If it is one,it
7214 was the left button.
7215
7216 7.4.Event Handling.
7217 -------------------
7218 Pretend you've opened a window that as a close symbol,and you want
7219 the program to react to this symbol being clicked.You need a
7220 signal from Intuition that lets you know that an event as taken
7221 place.The signal is called a message.
7222 The IDCMP flag of the window specifies which events should cause
7223 Intuition to send a message.By setting the bits for WINDOWCLOSE,
7224 you can allow a message to be sent when the close symbol is
7225 clicked.
7226 To get the message,you can use the EXEC function GetMsg (offset
7227 -372).It needs the source address of the event as a parameter.Here
7228 the source is the User port (which doesn't have anything to do
7229 with the User port on old Commodore computors).
7230 The User port contains a table which has entrieswhich specify the
7231 events that have taken place and related things like mouse
7232 position and time.
7233 How do you find the User port?Use the pointer to the window
7234 structure that you got back from the OpenWindow function and
7235 stored in the "windowhd"memory block.
7236 This pointer points to the window structure of this window.This
7237 structure consists of a number of entries.Some are copies of the
7238 parameters from our window definition table.We won't cover all the
7239 entries,because most won't be interesting to you.You're more
7240 interested in the pointer to the User port.Its in the window
7241 structure.
7242 You can find this in the long word that begins in the 86th byte of
7243 the structure.You can get this long word with the following lines
7244 of code:
7245
7246 move.l windowhd,a0 ;pointer to structure in A0
7247 move.l 86(a0),a0 ;user port pointer in A0
7248
7249 You can call the GetMsg function with this pointer in A0 by using
7250 the following lines of code in your program:
7251
7252 GetMsg = -372
7253 ...
7254 move.l windowhd,a0 ;pointer to structure in A0
7255 move.l 86(a0),a0 ;user port pointer in A0
7256 move.l execbase,a6 ;exec base address in A6
7257 jsr getmsg(a6) ;get message
7258
7259 This function returns a value in the D0 register.This value is a
7260 pointer to another structure,the Intuition Message Structure.If
7261 theres a zero in D0,no event as taken place.
7262 The long word that starts at the 20th byte in this structure
7263 contains the information about which event took place.Evaluating
7264 the information is easy,since the bits of this long word have the
7265 same meaning as the IDCMP flag that you described when you looked
7266 at opening windows.
7267 Put the lines above after "loop"and then insert the following:
7268
7269 move.l d0,a0 ;message pointer in A0
7270 move.l 20(a0),d6 ;save event in D6
7271 tst.l d0 ;did the event take place?
7272 bne end ;yes!
7273
7274 Now you can end this program by clicking the close symbol.This way
7275 you can find out if an event as taken place.You can use D6 to
7276 determine what event took place.In the example,D6 contains the
7277 number $00000200,which means that the close symbol was clicked.
7278 To see if this works with other events,change the $200 IDCMP flag
7279 to $10200 in the window definition table.When you've assembled and
7280 started this version,take the disk out of the drive-the program
7281 terminates.
7282 The IDCMP flags that you've got now cause the clicking of the
7283 close symbol and the taking out of the disk (DISKREMOVED) to be
7284 reported.If you want to find out which of the events took place,
7285 you can look in D6.It has a $200 in it if the window is closed,a
7286 $10000 if the disk was removed.
7287
7288 7.5.Menu Programming.
7289 ---------------------
7290 Now lets look at one of Intuitions more interesting capabillities:
7291 menu programming.By using menus,you can make your programs very
7292 user friendly.
7293 There are a lot of ways for you to use menus.You can make menu
7294 points unusable,output sub-menus,choose the type of menu entries
7295 (allow text or pictures to be output),etc..To have lots of options
7296 you need some parameters.
7297 Lets produce a menu with the SetMenuStrip function (offset -264)
7298 of Intuition.The function only needs two parameters,a pointer to
7299 the menu structure of the window to be drawn and a pointer to the
7300 window structure of the window in which the menu is to function.
7301 Each window can have its own menu that is active when the window
7302 is activated.
7303 Heres the subroutine to set up the menu:
7304
7305 SetMenuStrip =-264
7306 ...
7307 setmenu: ;* Initialize a menu
7308 move.l intbase,a6 ;intuition base address in A6
7309 move.l windowhd,a0 ;pointer to window structure
7310 lea menu,a1 ;pointer to menu structure
7311 jsr setmenustrip(a6) ;call function
7312 rts
7313
7314 Heres a routine to erase the menu:
7315
7316 ClearMenuStrip =-54
7317 ...
7318 clearmenu:
7319 move.l intbase,a6 ;intuition base address in A6
7320 move.l windowhd,a0 ;pointer to window structure
7321 jsr clearmenustrip(a6)
7322 rts
7323
7324 You've already got the pointer to the window structure.Lets look
7325 at the menu structure you need for the menu.You need to build a
7326 structure like this for each menu--for each menu title that
7327 appears when you press the right mouse key.
7328 This structure is a table with the following form:
7329
7330 First there is a long word that points to the menu structure of
7331 the next menu.If the current menu is the last one,a zero goes
7332 here.
7333
7334 align
7335 menu:
7336 dc.l menu1 ;pointer to the next menu
7337
7338 Next come two words which contain tha X- and Y-position of the
7339 menu title:
7340
7341 dc.w 20 ;X-position
7342 dc.w 0 ;Y-position
7343
7344 Next,use two words to store the menu titles width and height in
7345 pixels:
7346
7347 dc.w 50 ;width
7348 dc.w 10 ;height of menu title
7349
7350 The next word contains the flag bit that determines whether the
7351 menu is available or not.An unavailable menu either as grey
7352 entries or they are drawn weakly.If the flag bit,bit 0,is set the
7353 menu is available.Otherwise,it is not.
7354
7355 dc.w 1 ;menu available
7356
7357 Now comes a long word which functions as a pointer to the text
7358 which is used as the menu title.Make sure the length isn't larger
7359 than the width entry allows!Otherwise unpleasent things will
7360 happen.
7361
7362 dc.l menutext ;pointer to title text
7363
7364 Next comes a long word which functions as a pointer to the
7365 structure of the first menu entry of this menu.Each menu entry
7366 needs its own structure.
7367
7368 dc.l menuitem01 ;pointer to the first menu item
7369
7370 The last entries in the table are four words that are reserved for
7371 internal functions.They must be here.
7372
7373 dc.w 0,0,0,0 ;reserved words
7374
7375 Thats the structure of the first menu.This structures first long
7376 word points to the next structure which has the same form.The
7377 pointer is set to zero in the last menu.
7378 You still need the structure of the menu entries.These structure
7379 tables have the following form:
7380
7381 They start with a pointer to the next menu item.This pointer is
7382 set to zero for the last entry.
7383
7384 align
7385 menuitem01:
7386 dc.l menuitem02 ;pointer to next menu item
7387
7388 Next comes the four words:the X- and Y-position,the width and the
7389 height of the box the menu entry goes in.The size becomes obvious
7390 when the item is chosen by having the right mouse key clicked on
7391 it.Then the box becomes visible.As you can see,the next word is
7392 determined in the flags.First lets set the position and size of
7393 the menu point,though:
7394
7395 dc.w 0 ;X-position of entry
7396 dc.w 0 ;Y-position
7397 dc.w 90 ;width in pixels
7398 dc.w 10 ;height in pixels
7399
7400 The position entries are relative to the upper left corner of the
7401 menu that is pulled down.
7402 The following word was described above:it contains flags for
7403 entries to this menu item.There are several interesting variations
7404 possible.The following flag bits are contained in this word:
7405
7406 Bit Value Name Meaning When Set
7407 ------------------------------------------------------------------
7408 0 $0001 CHECKIT Point is checked when chosen
7409 1 $0002 ITEMTEXT Text menu item
7410 2 $0004 COMMSEQ Choice can be made with keys as well
7411 3 $0008 MENUTOGGLE Check turned on and off
7412 4 $0010 ITEMENABLED Menu item available
7413 6 $0040 HIGHCOMP Item inverted when chosen
7414 7 $0080 HIGHBOX Iten framed when chosen
7415 8 $0100 CHECKED Item is checked
7416
7417 Heres a description of the bits:
7418
7419 Name Description
7420 ------------------------------------------------------------------
7421 CHECKIT If this bit is set,a check or a user-defined
7422 drawing is put in front of the text when the item
7423 is chosen.The text should begin with two blanks.
7424
7425 ITEMTEXT The menu item is a normal text if this bit is set.
7426 Otherwise a drawing is output.
7427
7428 COMMSEQ By setting this bit and entering a character,this
7429 menu point can be chosen by pressing the right
7430 <Amiga> key and the key that was input.The input
7431 character is then displayed in the menu with the
7432 Amiga symbol.There needs to be space available for
7433 this.
7434
7435 MENUTOGGLE If this bit is set and checking is allowed (bit 0),
7436 the second time this point is chosen the check is
7437 erased,the next time it is displayed again,etc...
7438
7439 ITEMENABLED Erasing this bit makes the menu item available.
7440
7441 HIGHCOMP If this bit is set,the box you've defined is
7442 inverted when this menu item is chosen by the mouse
7443 pointer.
7444
7445 HIGHBOX In this mode,the box is framed whin its chosen.
7446
7447 The two previous bits determine the mode of the chosen menu item.
7448 The following combinations are possible:
7449
7450 HIGHIMAGE If both bits are cleared,choosing the bit causes a
7451 self-defined drawing to be output.
7452
7453 HIGHNONE When both bits are set,there isn't any reaction to
7454 choosing this item.
7455
7456 CHECKED This bit can be set by either the program or
7457 Intuition.It lets you know if the menu text has a
7458 check next to it or not.You can use this to find
7459 out if the item was checked by testing but eight.If
7460 its set,the item was checked.You can also use it to
7461 cause the item to be checked.
7462
7463 You're choosing the mode CHECKIT,ITEMTEXT,COMMSEQ,MENUTOGGLE,ITEM-
7464 ENABLED and HIGHBOX for the example:
7465
7466 dc.w $10011111 ;mode flag
7467
7468 Lets get back to the structure of the menu items.After the flag
7469 word,there is a long word whose flag bits determine whether this
7470 menu point can be turn off another one.Set this to zero:
7471
7472 dc.l 0 ;no connection
7473
7474 Now comes the pointer to the structure of the text that should be
7475 displayed.If the ITEMTEXT bit isn't set,this pointer must point to
7476 the structure of the drawing.If nothing should be shown,you can
7477 set this to zero.Use a text in the example and write the
7478 following:
7479
7480 dc.l menu01text ;pointer to menu text structure
7481
7482 The following long word only has a meaning if the HIGHIMAGE flag
7483 is set.Then this long word points to the text or the drawing that
7484 should be displayed when the menu items box is clicked.Otherwise
7485 the long word is ignored,so insert a zero:
7486
7487 dc.l 0 ;no drawing when clicked
7488
7489 The next entry is a byte that is used for input of keyboard
7490 characters,which together with the right <Amiga> key can be used
7491 to choose the menu item.This only works if the COMMSEQ bit is set.
7492 Place a character here:
7493
7494 dc.b 'A' ;choose item using <Amiga>/'A'
7495
7496 Since the next item is a long word,you need an "align"peudo-op
7497 here.Next comes the long word that points to the menu item
7498 structure or a submenu.The submenu is automatically shown when
7499 this menu item is clicked.You can't nest them any deeper,however,
7500 so this long word is ignored for submenus.
7501 If you don't want a submenu to this item,put a zero here:
7502
7503 align
7504 dc.l 0 ;no submenu
7505
7506 The next and final long word is written to by Intuition if you
7507 choose several menu itens.In this case,the menu number of the next
7508 menu item chosen goes here:
7509
7510 dc.l 0 ;preparation
7511
7512 Thats the structure for a menu item.You still need the text
7513 structure for the text of the item.This isn't complicated,but it
7514 makes you get into fine details about the form of the menu.You've
7515 already learned about this text structure when you looked at
7516 requesters,so we'll skip an explanation.
7517 Heres the complete structure of an example menu.You can use two
7518 menus,each with two subpoints.The second menu point of the left
7519 menu has a submenu with two entries.You ought to type this program
7520 in,so that you can experiment with it.You can also use this
7521 example to evaluate the clicked menu item.
7522
7523 ;**Complete menu structure foe example menu **
7524 menu:
7525 dc.l menu1 ;no next menu
7526 dc.w 10,30 ;X/Y
7527 dc.w 50,10 ;width/height
7528 dc.w 1 ;menu enabled
7529 dc.l menuname ;menu title
7530 dc.l menuitem01 ;menu entry
7531 menuname:
7532 dc.b "Menu 1",0 ;first menu name
7533 align
7534 menu1:
7535 dc.l 0 ;no further menu
7536 dc.w 80,0 ;see above
7537 dc.w 50,10
7538 dc.w 1
7539 dc.l menuname1
7540 dc.l menuitem11
7541 dc.w 0,0,0,0
7542 menuname1:
7543 dc.b "Menu 2",0 ;second menu name
7544 align
7545 menuitem01: ;first menu item
7546 dc.l menuitem02 ;pointer to next entry
7547 dc.w 0,0 ;X/Y
7548 dc.w 130,12 ;width/height
7549 dc.w $9f ;flags
7550 dc.l 0 ;exclude
7551 dc.l text01 ;pointer to text structure
7552 dc.l 0 ;select fill
7553 dc.b "1" ;command
7554 align
7555 dc.l 0 ;subitem:none
7556 dc.w 0 ;next select:no
7557 text01:
7558 dc.b 0,1 ;colours
7559 dc.b 0 ;mode:overwrite
7560 align
7561 dc.w 5,3 ;X/Y position
7562 dc.l 0 ;standard character set
7563 dc.l text01txt ;pointer to text
7564 dc.l 0 ;no more text
7565 text01txt:
7566 dc.b "Point 0.1",0
7567 align
7568 menuitem02: ;second menu item
7569 dc.l 0
7570 dc.w 0,10
7571 dc.w 130,12
7572 dc.w $57
7573 dc.l 0
7574 dc.l text02
7575 dc.l 0
7576 dc.b "2" ;activate with <Amiga>/'2'
7577 align
7578 dc.l 0
7579 dc.w 0
7580 text02:
7581 dc.b 0,1
7582 dc.b 0
7583 align
7584 dc.w 5,3
7585 dc.l 0
7586 dc.l text02txt
7587 dc.l 0
7588 text02txt:
7589 dc.b "Point 0.2",0
7590 align
7591 menuitem11: ;first menu point of the second menu
7592 dc.l menuitem12 ;pointer to second menu point
7593 dc.w 0,0
7594 dc.w 90,12
7595 dc.w $52
7596 dc.l 0
7597 dc.l text11
7598 dc.l 0
7599 dc.b 0
7600 align
7601 dc.l 0
7602 dc.w 0
7603 text11:
7604 dc.b 0,1
7605 dc.b 0
7606 align
7607 dc.w 5,3
7608 dc.l 0
7609 dc.l text11txt
7610 dc.l 0
7611 text11txt:
7612 dc.b "Point 1.1",0
7613 align
7614 menuitem12: ;second menu item of second menu
7615 dc.l 0 ;no more items
7616 dc.w 0,10
7617 dc.w 90,12
7618 dc.w $92
7619 dc.l 0
7620 dc.l text12
7621 dc.l 0
7622 dc.b 0
7623 align
7624 dc.l submenu0 ;pointer to submenu
7625 dc.w 0
7626 text12:
7627 dc.b 0,1
7628 dc.b 0
7629 align
7630 dc.w 5,3
7631 dc.l 0
7632 dc.l text12txt
7633 dc.l 0
7634 text12txt:
7635 dc.b "Point 1.2",0
7636 align
7637 submenu0: ;first point of submenu
7638 dc.l submenu1 ;pointer to next point
7639 dc.w 80,5
7640 dc.w 90,12
7641 dc.w $52
7642 dc.l 0
7643 dc.l texts0
7644 dc.l 0
7645 dc.b 0
7646 align
7647 dc.l 0
7648 dc.w 0
7649 texts0:
7650 dc.b 0,1
7651 dc.b 0
7652 align
7653 dc.w 5,3
7654 dc.l 0,texts0txt,0
7655 texts0txt:
7656 dc.b "S Point 1",0
7657 align
7658 submenu1: ;submenu,second item
7659 dc.l 0
7660 dc.w 80,15
7661 dc.w 90,12
7662 dc.w $52
7663 dc.l 0
7664 dc.l texts1
7665 dc.l 0
7666 dc.b 0
7667 align
7668 dc.l 0
7669 dc.w 0
7670 texts1:
7671 dc.b 0,1
7672 dc.b 0
7673 align
7674 dc.w 5,3
7675 dc.l 0
7676 dc.l texts1txt
7677 dc.l 0
7678 texts1txt:
7679 dc.b "S Point 2",0
7680 align
7681
7682 The menu items in this example have the following properties as a
7683 result of their flags:
7684
7685 Menu 1;
7686 The first item,"Point 0.1",can be chosen using the right <Amiga>
7687 key and the "1" key.This point alternates between checked and not
7688 checked,which can easily be used to check out the key function.If
7689 the item is checked and you hit both keys,the check disappears and
7690 vice versa.The box at this point is framed when the mouse pointer
7691 clicks on it.
7692 The second item,"Point 0.2",can be chosen using the right <Amiga>
7693 key and the "2"key.This item is checked the first time it is
7694 chosen.However,in contrast to the item above,it can't be erased.
7695 The box of this item is inverted when clicked.
7696
7697 Menu 2;
7698 These two points can't be chosen using keys.The box of the upper
7699 item is inverted when clicked on:the lower one is framed.When you
7700 click the second item,"Point 1.2",a submenu with two entries is
7701 displayed.
7702
7703 Experiment with this structure a little bit.Change some values and
7704 see what happens.As you can see,menu programming isn't as bad as
7705 you thought,and it offers a lot of options (but you'll have to do
7706 lots of typing!).
7707 When you've done experimenting,you'll want to produce your own
7708 program with menus.How does the program find whether a menu item
7709 in a menu has been clicked on?
7710 You already looked at one way to find out the menus state.You can
7711 test the CHECKED bit in the flag word of a menu item.If this is
7712 set,the user clicked on this item with the mouse.
7713 This only works if checking is allowed for the item being tested.
7714 You could allow all the menu items to be checked,but this still
7715 isn't a good solution--it requires testing all the flag bits of
7716 all the menus one after the other.That makes very boring
7717 programming.
7718 You've already learned about finding about events from Intuition.
7719 You've moved the message about which event took place into D6,and
7720 you can look at it to find out what happend.
7721 If you set the eight bit,the MENUPICK bit,of the IDCMP flag long
7722 word in the window definition,the choice of the menu point is
7723 reported.Put the following lines in your loop in the main program.
7724
7725 loop:
7726 move.l execbase,a6 ;exec base address in A6
7727 move.l windowhd,a0 ;window structure pointer
7728 move.l 86(a0),a0 ;user point pointer in A0
7729 jsr getmsg(a6) ;get message
7730 tst,l d0 ;whay happend?
7731 beq loop ;nothing happend
7732 move.l d0,a0 ;message pointer in A0
7733 move.l $14(a0),d6 ;event in D6
7734
7735 If the program makes it out of the loop,an event as taken place.
7736 You have the events flag in the D6 register.You can evaluate the
7737 event using CMP or BTST to find out which flag bits are set.You
7738 can then execute the function corresponding to the set bit.You can
7739 use lines like the following ones:
7740
7741 cmp #$200,d6 ;WINDOWCLOSE?
7742 beq ende ;yes:program end
7743
7744 These lines terminate the program when the window is closed.
7745
7746 If the user chose a menu item,there is a $100 in the D6 register.
7747 You now need to determine which item it was.
7748 You can find this information in a word that comes right after the
7749 long word with the event flags in the message structure.Write:
7750
7751 move $18(a0),d7
7752
7753 You now have the code for the clicked menu item in the D7
7754 register.If the user just pressed the right key and let it go
7755 without choosing a menu item,you'll find a $FFFF here.This word
7756 doesn't contain just one,but three pieces of information:
7757
7758 Which menu was the item chosen from?
7759 Which menu item?
7760 Which submenu?
7761
7762 The information is divided in three bit groups.The division is as
7763 follows:
7764
7765 Bits 0-4 Menu title number
7766 Bits 5-10 Menu item number
7767 Bits 11-15 Submenu item number
7768
7769 The numbering begins with zero-ie the first menu point of the
7770 first menu has the numbers 0 and 0.
7771
7772 To try this out insert the following lines:
7773
7774 move d7,d6 ;move code into D6
7775 lsr #8,d7 ;shift right 11 times
7776 lsr #3,d7 ;submenu item now in D7
7777 clr.l d5
7778 roxr #1,d6 ;bit 0 in X-flag
7779 roxl #1,d5 ;menu number now in D5
7780 and.l #$7f,d6 ;issolate lower bits
7781 cmp #$7f,d6 ;no menu item?
7782 beq loop ;no:continue
7783 lsr #4,d6 ;else menu item in D6
7784 ende
7785
7786 By making a test run with AssemPro,you can easily see if this
7787 works right-just look at the registers after the program is over.
7788
7789 If you,for example,want to write a program with four menus with 10
7790 menu items each,this sort of method is too much work-there are 44
7791 tables.For this reason,lets look at a short program that takes
7792 care of the necessary structure table itself.
7793 The menu structure is built very simply-it doesn't offer submenus
7794 or the option of choosing items via the keyboard.If you want these
7795 extras,you can still use this program,but you'll have to use MOVE
7796 commands to insert the desired flags and pointers.
7797 The input that this program needs is a list of the menu names and
7798 the items in each menu.The addresses of the menu texts go in a
7799 table with the following simple form:
7800
7801 dc.l Menu title 1
7802 dc.l Point1,Point2,Point3,...,0
7803 dc.l Menu title 2
7804 dc.l Point1,Point2,Point3,...,0
7805 dc.l Menu title 3 oder 0
7806
7807 This program is set up in such a way that up to four menus can lie
7808 next to each other (in normal screen resolution),which is often
7809 plenty.The table above ends by putting a zero instead of a pointer
7810 to the nxt menu title.As you can see,its pretty simple.
7811 This program is inserted in your big program right behind the
7812 "setmenu"label.After the "bsr setmenu"command is executed,the menu
7813 structure is built and initialized at the same time.You don't need
7814 to change the rest of the program,it'll be shorter that way.
7815
7816 Heres the program fragment for the complete "setmenu"routine:
7817
7818 setmenu: ;*initialize menu structure
7819 lea mentab,a0 ;pointer to text pointer in A0
7820 lea menu,a1 ;pointer to menu field in A1
7821 move #10,d1 ;horizontal menu position=10
7822
7823 menuloop:
7824 clr.l d2 ;vertical menu position=0
7825 move.l a1,a2 ;save address of pointer
7826 tst.l (a0) ;another menu there?
7827 beq setmenu1 ;no:quit
7828 clr.l (a1)+ ;"no more menus"preperations
7829 move d1,(a1)+ ;set X-position
7830 add.l #70,d1 ;and increment
7831 move.l #50,(a1)+ ;Y-position and width
7832 move.l #$a0001,(a1)+ ;height and flag
7833 move.l (a0)+,(a1)+ ;menu title
7834 lea 12(a1),a3
7835 move.l a3,(a1)+ ;pointer to menu item
7836 clr.l (a1)+ ;reserved words
7837 clr.l (a1)+
7838
7839 itemloop:
7840 tst.l (a0) ;last entry?
7841 beq menuend ;yes:menu done
7842 lea 54(a1),a3
7843 move.l a3,(a1)+ ;pointer to next item
7844 move.l d2,(a1)+ ;X- and Y-positions
7845 add #10,d2 ;Y-position+10
7846 move.l #$5a000a,(A1)+ ;WIDTH/HEIGHT
7847 move #$52,(a1)+ ;flag:normal
7848 clr.l (a1)+ ;no connection
7849 lea 16(a1),a3
7850 move.l a3,(a1)+ ;text structure pointer
7851 clr.l (a1)+ ;no fill structure
7852 clr.l (a1)+ ;no command,no submenu
7853 clr.l (a1)+ ;and no continuation
7854 move #$1,(a1)+ ;set text structure:colour
7855 clr.l (a1)+ ;mode 0
7856 move.l #$50003,(a1)+ ;X- and Y-position
7857 clr.l (a1)+ ;standard character set
7858 move.l (a0)+,(a1)+ ;text pointer
7859 clr.l (a1)+ ;no continuation
7860 bra itemloop ;next item...
7861
7862 menuend: ;eventual transfer to next menu
7863 clr.l -54(a1) ;erase pointer to next item
7864 tst.l (a0)+ ;increment table pointer
7865 tst.l (a0) ;another menu there?
7866 beq setmenu1 ;no:done
7867 move.l a1,(a2) ;pointer to next menu
7868 bra menuloop ;and continue
7869 setmenu1: ;*initialize menu (like before)
7870 move.l intbase,a6 ;intuition base address in A6
7871 move,l windowhd,a0 ;window structure in A0
7872 lea menu,a1 ;pointer to menu structure
7873 jsr setmenustrip(a6)
7874 rts
7875
7876 You need three things yet for this program:the memory to be used
7877 for the structure,the table of text pointers and the text.Heres an
7878 example:
7879
7880 mentab:
7881 dc.l menu1 ;first menu title
7882 dc.l mp11,mp12,mp13 ;menu items
7883 dc.l 0 ;end of menu 1
7884 dc.l menu2 ;second menu title
7885 dc.l mp21,mp22,mp23 ;menu items
7886 dc.l 0 ;end of menu 2
7887 dc,l 0 ;you're out of menus!
7888
7889 ;** Menu Text **
7890 menu1: dc.b "Menu 1",0
7891 mp11: dc.b "Point11",0
7892 mp12: dc.b "Point12",0
7893 mp13: dc.b "Point13",0
7894 menu2: dc.b "Menu 2",0
7895 mp21: dc.b "Point21",0
7896 mp22: dc.b "Point22",0
7897 mp23: dc.b "Point23",0
7898 align
7899 ;** Storage space for menu structure **
7900 menu: blk.w 500
7901
7902 Make sure that the memory area reserved for the menu structure is
7903 big enough and change the entry "blk.w 500"to the calculated
7904 value.
7905 If you use this program,and want to build some special features
7906 into the menu (for instance key commands),you can make entries in
7907 the menu structure table while the program is running.You can find
7908 the word (or byte or long word) that interests you in the table as
7909 follows:
7910
7911 For example,to find the keyboard command byte of the second entry
7912 in the first menu,calculate as follows:
7913
7914 Address = Start_address+Menu*30+(entry-1)*54+26
7915
7916 which in the example comes to:
7917
7918 Address = menu+30+54+26
7919 = menu+110
7920
7921 The 26 is the distance from the beginning of the MenuItem
7922 structure to the desired byte,the command byte.In this way,you can
7923 calculate the addresses and use MOVE commands to modify the menu
7924 to fit your wishes.By the way,in the example above,the correspond-
7925 ing flag bit must be set as well,so that the keyboard command is
7926 recognized.
7927 Now lets get back to the window.Its nice to have a window that you
7928 can change and close,but you really want to be able to output text
7929 in a window!
7930
7931 7.6.Text Output.
7932 ----------------
7933 Its very easy to use Intuition's text output function.Use the
7934 PrintIText function (offset -216).It needs four parameters.
7935
7936 In A0 A pointer to the RastPort of the window.You can find this
7937 in the window structure.
7938 In A1 A pointer to the text structure of the text that should
7939 be output.
7940 In D0 The X-position.
7941 In D1 The Y-position of the text in the window.
7942
7943 Its very easy to enter the X- and Y-positions.You've already used
7944 the text structure twice (for requesters and menus).
7945 Whats new is accessing the windows RastPort.The RastPort is a
7946 structure that describes the window.The address is needed by
7947 several Intuition functions.
7948 The pointer to the RastPort starts at the 50th byte in the window
7949 structure.You can access it as follows:
7950
7951 move.l windowhd,a0 ;address of window structure
7952 move.l 50(a0),a0 ;RastPort address in A0
7953
7954 Now you've got the address of the RastPort.Lets write a routine
7955 that prints a text.The X- and Y-positions are in D0 and D1
7956 respectively and the address of the text structure in A1 before
7957 the routine is called:
7958
7959 PrintIText = -216
7960 ...
7961 print:
7962 move.l intbase,a6 ;intuition base address in A6
7963 move.l windowhd,a0 ;address of window structure
7964 move.l 50(a0),a0 ;rastport address in A0
7965 jsr printitext(a6) ;call function
7966 rts
7967
7968 You can try out this routine by using the requesters text that is
7969 still in a structure of the program.Write the following lines
7970 before the "loop"label:
7971
7972 lea btext,a1 ;pointer to text structure in A1
7973 move.l #10,d0 ;X-position
7974 move.l #30,d1 ;Y-position of text
7975 bsr print ;output text
7976
7977 Start the program and the text appears in the middle of the window
7978 If this doesn't happen,check the colour of the text in the text
7979 structure.Its probably zero.Just change it to three,and the text
7980 appears in red the next time you start the program.
7981
7982 7.7.Images.
7983 -----------
7984 An image is a drawing that goes in a rectangular field and is
7985 defined bitwise.The disk symbol of the Intuition screen and the
7986 system gadgets in the screen and window borders are examples of
7987 such Images.
7988 The rectangle that the drawing goes in can be arbitrarily large,
7989 but each pixel in the rectangle needs its own bit,so programming
7990 screen-sized Images isn't advisable.You'll stick to an Image that
7991 requires about 32x16 bits-an Image thats about 3x1cm.
7992 You can make all sorts of images as you've seen looking at window
7993 gadgets.There is an Intuition functionthat draws an Image:It is
7994 the DrawImage function (offset -114) and it needs 4 parameters:
7995
7996 In A0 The address of the rastport image is drawn in.You've
7997 already learned how to access this address in the section
7998 on the text function.
7999 In A1 The structure address of the image to be drawn.
8000 In D0 The relative X-position
8001 In D1 The relative Y-position of the drawing.
8002
8003 Lets draw this picture in your window.It justs takes a simple
8004 routine.You just need to put the address of the image structure in
8005 A1 and the position of the image in D0 and D1 before you call it.
8006
8007 DrawImage =-114
8008 ...
8009 draw: ;*draw image
8010 move.l intbase,a6 ;intuition base address in A6
8011 move.l windowhd,a0 ;pointer to window structure
8012 move.l 50(a0),a0 ;now,rastport address in A0
8013 jsr drawimage(a6) ;draw image
8014 rts
8015
8016 Now you need the structure of the image.The structure contains
8017 nine entries which have the following meanings:
8018
8019 The first two entries are words which specify the distance in the
8020 X- and Y-direction from the co-ordinates that were given to tell
8021 where the image should be drawn.You'll just put two zeros here:
8022
8023 image:
8024 dc.w 0,0 ;X- and Y-position
8025
8026 Next come two words which specify the width and height of the
8027 image in pixels.Lets draw a 32x13 point image.Enter:
8028
8029 dc.w 32,13 ;width and height of image
8030
8031 The next word in the list specifies the number of planes in the
8032 drawing.If its a simple image that only uses two colours,just
8033 enter a one.For more colours,you'll need a correspondingly bigger
8034 number.When more colurs are worked with,the bit pattern of the
8035 image must have more data.Lets just have one bit plane:
8036
8037 dc.w 1 ;one bitplane:2^1=2 colours
8038
8039 Next comes a long word that points to the data of the image:
8040
8041 dc.l imgdata ;pointer to image data
8042
8043 The next two bytes are very interesting.The first byte,the
8044 PlanePick byte,tells which plane of the window or screen the image
8045 data should be written in.Since you only have one plane,you need
8046 to enter the bit plane of the window.This information is found in
8047 the bits of the byte-bit0 stands for plane 0,bit 1 for plane 1,etc
8048 ..You also define the colour of the image with this input.If you
8049 enter a two,every set bit of your image represents a red point.
8050
8051 dc.b 2 ;drawing red:plane 1
8052
8053 The second byte,the PlaneOnOff byte,is an interesting enhancement.
8054 Each bit of the window bit plane corresponds to a whole number
8055 here.The only bytes that are interesting though are the ones that
8056 are cleared in the PlanePick byte.If the bit is set in PlaneOnOff,
8057 evert bit of the image in the corresponding plane is set.Otherwise
8058 they are cleared.To make sure that each bit of the image that
8059 isn't set appears white,enter a one.All the bits of the image that
8060 aren't set,are set in Plane 1 and appear white.
8061
8062 dc.b 1 ;background:white
8063
8064 The last entry of the structure is a lobg word that points to
8065 another image.You don't need this,so set the long word to zero:
8066
8067 dc.l 0 ;no more images
8068
8069 Heres a quick overview of the image structure:
8070
8071 image:
8072 dc.w 0,0 ;X- and Y-positions
8073 dc.w 32,13 ;width and height of image
8074 dc.w 1 ;one bitplane:2^1=2 colours
8075 dc.l imgdata ;pointer to image data
8076 dc.b 2 ;drawing red:plane 1
8077 dc.b 1 ;background:white
8078 dc.l 0 ;no more images
8079
8080 Now lets produce the image data.Each image row uses a word,long
8081 word,or several of these represent the pattern.The set points of
8082 the image correspond to the set bits.This is repeated as often as
8083 the height of the image requires.The data on each line must begin
8084 on a word border,on a even address.
8085 For the example,its easy to decide on the data,since you're going
8086 32 points across-that corresponds to exacty one long word.Its
8087 easiest to program the image using the binary representation of
8088 the data.
8089 Lets use,as an example,an image that represents a switch in "OFF"
8090 mode.This form is chosen for a good reason,so you should type it
8091 in.In the chapter on gadgets thats coming up,we'll show you how to
8092 turn the switch on.Here is the example data for the switch image:
8093
8094 imgdata: ;Data for switch in "OFF" mode
8095 dc.l %00000000000000000000000000000000
8096 dc.l %00000000000000000000111000000000
8097 dc.l %00011101110111000001111100000000
8098 dc.l %00010101000100000001111100000000
8099 dc.l %00010101100110000001111000000000
8100 dc.l %00011101000100000011100000000000
8101 dc.l %00000000000000000111000000000000
8102 dc.l %00000000000000001110000000000000
8103 dc.l %00000000000111111111100000000000
8104 dc.l %00000000001111111111110000000000
8105 dc.l %00000000001111111111110000000000
8106 dc.l %00000000000110000001100000000000
8107 dc.l %00000000000000000000000000000000
8108
8109 Once you've typed in this data,you can experiment with displaying
8110 it on the screen.Enter the following lines before the "loop"label:
8111
8112 move.l image,a1 ;pointer to image structure
8113 move #30,d0 ;X-postion in window
8114 move #50,d1 ;Y-position
8115 bsr draw ;draw image
8116
8117 How do you like the image on the screen?You'll run into this
8118 switch again when we talk about putting the switch in the "ON"
8119 state when discussing gadgets.You need to look at other methods of
8120 drawing in the window first,though.
8121
8122 7.8.Borders.
8123 ------------
8124 A border is a collection of lines that are connected.They can be
8125 of any length or at any angle.Intuition lets you draw borders to
8126 do things like put frames around windows and screens.They are used
8127 to put borders around pictures or text,especially for use with
8128 string gadgets.We'll talk about that later,though.
8129 Its easy to draw borders.Just use the Intuition function
8130 DrawBorder (offset -108) which needs four parameters:
8131
8132 In A0 The rastport address of the output medium the lines should
8133 be drawn in.Use your window.
8134 In A1 The address of the border structure.We'll look at the form
8135 of this structure shortly.
8136 In D0 The relative X-co-ordinate which is used with the X- and Y
8137 co-ordinate list to calulate the actual line co-ordinates.
8138 In D1 The relative Y-co-ordinates.Relative,here too,means that
8139 this is relative to the upper left corner of the screen.
8140
8141 Lets write a short routine that is called with three parameters.
8142 The structure address in A1 and the X and Y co-ordinates are in D0
8143 and D1 respectively when the routine is called.The border is drawn
8144 in the window whose structure address is in "windowhd".
8145
8146 DrawBorder =-108
8147 ...
8148 borderdraw: ;* draw several lines
8149 move.l inbase,a6 ;intuition base address in A6
8150 move.l windowhd,a0 ;pointer to window structure
8151 move.l 50(a0),a0 ;now rastport address in A0
8152 jsr drawborder(a6) ;draw lines
8153 rts
8154
8155 Now lets look at the border structure.The list needs the eight
8156 following parameters:
8157
8158 First,you need two words for the vertical and horizontal distance
8159 from the co-ordinates given in the function call.To avoid losing
8160 sight of some of the many distance entries,put two zeros here:
8161
8162 border:
8163 dc.w 0 ;horizontal distance
8164 dc.w 0 ;vertical distance
8165
8166 Next come two bytes that determine the colour.Use a red frame:
8167
8168 dc.b 3 ;red frame
8169 dc.b 0 ;background (unused)
8170
8171 As you can see,the background colour isn't used.You have two modes
8172 to choose between for drawing the lines.The following mode
8173 determines the mode that is used.If it is zero,each line is drawn
8174 in the colour chosen,no matter what was done before.This is the
8175 JAM1 mode.The other mode is the XOR mode which ignores both colour
8176 entries.In this mode,all the points that lie under the line have
8177 their colour value inverted.As a result,a white point becomes
8178 black,and a blue one becomes red.That is mode two.Lets use the
8179 JAM1 mode for the example:
8180
8181 dc.b 0 ;mode:JAM1 (2=XOR)
8182
8183 The next entry specifies how many co-ordinate pairs there are in
8184 the list.Since this word must be on an even address,you need to
8185 use the "align"peudo-op first.Then enter the number of pairs.
8186 Remember that you need three points to draw two lines:beginning,
8187 corner and end point.To draw a rectangular frame,you need five
8188 pairs:
8189
8190 dc.b 5 ;5 X,Y pairs used together
8191
8192 The next item is a pointer to the co-ordinate table that contains
8193 a list of points to be connected:
8194
8195 dc.l coord ;pointer to cordinate table
8196
8197 The border structures final entry is a long word that can point to
8198 another border structure.If you don't have any more structures to
8199 be pointed to,just enter a zero here.The pointer is useful for
8200 connecting two independant border structures-for example,to
8201 produce a two coloured frame that really stands out.You don't need
8202 this pointer in the example,though:
8203
8204 dc.l 0 ;no more structures
8205
8206 Thats the border structure.Now lets look at the co-ordinate list.
8207 For the example,it consists of five pairs of numbers which
8208 represent a rectangle.I recommend entering these values,because
8209 you'll use them in example programs further down the line.
8210
8211 coord: ;coordinates for rectangle frame
8212 dc.w -2,-2
8213 dc.w 80,-2
8214 dc.w 80,9
8215 dc.w -2,9
8216 dc.w -2,-2
8217
8218 Heres a quick overview of the border structure:
8219
8220 border:
8221 dc.w 0 ;horizontal distance
8222 dc.w 0 ;vertical distance
8223 dc.b 3 ;red frame
8224 dc.b 0 ;background (unused)
8225 dc.b 0 ;mode:JAM1 (2=XOR)
8226 dc.b 5 ;5 X,Y pairs used together
8227 dc.l coord ;pointer to cordinate table
8228 dc.l 0 ;no more structures
8229 coord: ;coordinates for rectangle frame
8230 dc.w -2,-2
8231 dc.w 80,-2
8232 dc.w 80,9
8233 dc.w -2,9
8234 dc.w -2,-2
8235
8236 Once you've typed this in,you can try the whole thing out.Type the
8237 following lines before the "loop"label in the program:
8238
8239 lea border,a1 ;address of the border structure
8240 move #20,d0 ;X base position
8241 move #80,d1 ;Y base position
8242 bsr drawborder ;draw frame
8243
8244 As you can see,using enough X and Y co-ordinates,you can draw the
8245 Eiffel tower.Thats enough about simple drawings.You want to put
8246 some life into your drawings and text.Lets manipulate them with
8247 the mouse!
8248
8249 7.9.Gadgets.
8250 ------------
8251 We already talked a bit about gadgets when you looked at screen
8252 construction.Looking at system gadgets like the window close
8253 symbol,you can activate by clicking and causes a program function
8254 to be executed.
8255 You can make your own gadgets as well.Intuition allows you a lot
8256 of interesting possibilities.
8257
8258 There are four types of gadgets:
8259
8260 Boolean gadgets are used in Yes/No situations.You can click and
8261 activate it (Yes) or deactivate it (No).
8262
8263 String gadgets are used to accept input of text of a specified
8264 length.
8265
8266 Integer gadgets are a special sort of string gadgets which accept
8267 the input of a decimal number.Intuition converts the value into a
8268 long word and sends it to the program.
8269
8270 Proportional gadgets let you choose an analog value with the mouse
8271 You can move these around with the mouse.
8272
8273 7.9.1.Boolean Gadgets.
8274 ----------------------
8275 Lets start with the simplest type,the boolean gadget.an example of
8276 this sort of gadget is the close symbol of the window.The only
8277 status it differenciates between are clicked and not clicked.Lets
8278 develop a gadget of this type step by step.The flags and other
8279 parameters are similar for the other gadgets.
8280 Each gadget needs a structure containing fifteen entries.There is
8281 a pointer to this structure in window,screen or requester that the
8282 gadget is to appear in.Theres always a long word available for
8283 this purpose.Up to this point,you've just put a zero there.If
8284 there is an address of a gadget structure there,the gadget or
8285 gadgets are displayed when the window is opened.
8286
8287 A gadget structure as the following entries:
8288
8289 The first long word is a pointer to the next gadget to be
8290 installed.The gadgets are displayed in a row,like pearls on a
8291 string.This pointer is the first gadget in this linked list of
8292 gadgets.If you just want one gadget in your window,put a zero
8293 here:
8294
8295 gadget1:
8296 dc.l 0 ;no more gadgets
8297
8298 The next two words determine the position of the gadget in the
8299 window.There are several ways to determine the position.Use flags
8300 to access the various possibilities.Lets start with a gadget that
8301 stays in one spot:
8302
8303 dc.w 40 ;X and
8304 dc.w 50 ;Y position of the gadget
8305
8306 The next two words determine the size of the gadgets Hit box.This
8307 box isn't the visible size of the gadget (that depends on the
8308 image data).It is the size of the rectangle that Intuition should
8309 watch.If the mouse pointer is moved into this box and the left
8310 button pressed,the gadget is activated.Clicking on parts of the
8311 gadget that are outside this box have no effect!
8312
8313 dc.w 32 ;width and
8314 dc.w 13 ;height of the hit box
8315
8316 Next comes the word whose bits determine the properties of the
8317 gadget.Bits 0 and 1 determine what should happen when this objects
8318 hit box is clicked on.The meanings of the various values of these
8319 bits go as follows:
8320
8321 Bit 0 1 Value Name Meaning
8322 ------------------------------------------------------------------
8323 0 0 0 GADGHCOMP The gadget inverted
8324 0 1 1 GADGHBOX The gadget framed
8325 1 0 2 GADGHIMAGE Another image appears
8326 1 1 3 GADGHNONE No reaction
8327
8328 Bit 2 determines whether the gadget should consist of a drawing or
8329 a border.If it is set(Value+4),it is treated as an image;otherwise
8330 its treated like a border.
8331 The next bit determines if the gadget should appear in the upper
8332 or lower border of the frame.If it is set(Value+8).the position is
8333 relative to the lower border;otherwise it is relative to the upper
8334 border.The next bit as the same meaning for the horizontal
8335 position.If set(Value+$10),it is a relative positioning.Otherwise,
8336 it is an absolute positioning.
8337 Notice that when you define a gadget to be relative,you must have
8338 a negative value in the position input in the first word of the
8339 structure.Since the desired position isn't under,but its over this
8340 position!
8341 In this way,you can choose either absolute or relative positioning
8342 of the gadget.An example of a gadget that is positioned absolutely
8343 is the system gadget,close window.An example of a relative gadget
8344 is the symbol for changing the size.
8345 The width and height of the gadgets hit box can also be relative
8346 to the window size.Specify this by using bit 5 for width (Value +
8347 $20)and bit 6 for the height (Value +$40).A set bit mens a
8348 relative size.
8349 Bit 7 (Value+$80)makes the object active as soon as the window is
8350 opened.
8351 Bit 8 (Value+$100)determines whether the gadget can be used or not
8352 If this bit is set,the gadget can't be activated.
8353 For the example,you'll use absolute positioning and size,the
8354 inverted appearance for the activated gadget,and the
8355 representation of the object as an image.That means you must use
8356 the value four:
8357
8358 dc.w 4 ;flags:image,invert
8359
8360 Next comes a word whose bits are used as flags.This flag is called
8361 the Activation Flag.It determines the functions of the gadget.The
8362 bits,their values and meanings follow:
8363
8364 Bit Value Name Meaning
8365 ------------------------------------------------------------------
8366 0 1 RELVERIFY Causes the gadget to be activated
8367 only when the left mouse key is let
8368 loose over the gadget.
8369 1 2 GADGIMMEDIATE Lets the gadget be active as soon as
8370 there is a click.
8371 2 4 ENDGADGET Lets you choose to end this choice
8372 and have it disappear if this is a
8373 requester gadget.
8374 3 8 FOLLOWMOUSE Lets the gadget know the mouse
8375 position at regular intervals from
8376 the time it is selected until the
8377 time it is deselected.You can use
8378 this to move the gadget with the
8379 mouse when you want to change the
8380 gadget position.
8381 4 $10 RIGHTBORDER This makes sure thay when borders
8382 are used that the page is adjusted
8383 to the size of the gadget so that it
8384 fits in the border.
8385 5 $20 LEFTBORDER
8386 6 $40 TOPBORDER
8387 7 $80 BOTTOMBORDER
8388 8 $100 TOGGLESELECT Allows the objects state to change
8389 every time it is clicked.If
8390 activated,it becomes deactivated and
8391 vice versa.
8392 9 $200 STRINGCENTRE For a string gadget,these two bits
8393 determine whether the string should
8394 appear centred or right justified.If
8395 neither is set,the string is output
8396 left justified.
8397 10 $400 STRINGRIGHT
8398 11 $800 LONGINT Turns a string gadget into a Integer
8399 gadget (explanation later).
8400 12 $1000 ALTKEYMAP Causes another ketboard placement to
8401 be in effect for string gadget input
8402
8403 Thats it for the activation flags.Lets choose the TOGGLESELECT and
8404 GADGETIMMEDIATED flags for example:
8405
8406 dc.w $102 ;activation
8407
8408 The next word of the gadget structure determines the gadget type.
8409 Heres the meaning of the individual bits:
8410
8411 Bit Value Name Meaning(report what circumstances)
8412 ----------------------------------------------------------------
8413 0 1 BOOLGADGET This is a boolean gadget
8414 1 2 GADGET002
8415 2 4 STRGADGET String order Integer gadget
8416 0+1 3 PROPGADGET Proportional gadget
8417
8418 System gadgets:
8419 4 $10 SIZING Size changing gadget
8420 5 $20 WDRAGGING Moving gadget for window
8421 4+5 $30 SDRAGGING Same for screen
8422 6 $40 WUPFRONT Gadget to move window forward
8423 6+4 $50 SUPFRONT Gadget to move screen forward
8424 6+5 $60 WDOWNBACK Move window back
8425 6+5+4 $70 SDOWNBACK Move screen back
8426 7 $80 CLOSE Window close gadget
8427
8428 Type definitions:
8429 12 $1000 REQGADGET Requester gadget
8430 13 $2000 GZZGADGET Border gadget in GIMMEZEROZERO
8431 window
8432 14 $4000 SCRGADGET Screen gadget when set
8433 15 $8000 SYSGADGET System gadget when set
8434
8435 You want to use a simple boolean gadget for your example,so enter:
8436
8437 dc.w 1 ;gadget type:boolean
8438
8439 Next comes a pointer to the gadget structure.The first pointer
8440 contains the address of the image or border structure which should
8441 be used to represent the gadget.If no representation is needed,put
8442 a zero here.You want to represent the gadget as an image,so put a
8443 pointer to the image structure that you produced in the chapter
8444 about images:
8445
8446 dc.l image ;gadget image
8447
8448 The next pointer is only used if the GADGHIMAGE flag in the flag
8449 word of the structure is set.This is a pointer to another
8450 structure that should be put on the screen when the object is
8451 activated.If a border structure is used for the gadget represent-
8452 ation,this must be a border structure as well.You won't use a
8453 second image,so put a zero here:
8454
8455 dc.l 0 ;no new gadget displayed
8456
8457 The next pointer is to the text structure that should be output by
8458 the gadget.If no text is needed,just put a zero here.You want to
8459 use some text,however:
8460
8461 dc.l ggtext ;gadget text
8462
8463 Now comes a long word that determines which gadgets are
8464 deactivated when this is activated.This function still doesn't
8465 work right so put a zero here:
8466
8467 dc.l 0 ;no exclude
8468
8469 You'll set the next pointer to zero as well,because it is only
8470 used for String and Proportional gadgets.For these gadgets,this is
8471 a special structure to describe the characteristics of the gadget.
8472 Its called SpecialInfo.
8473
8474 dc.l 0 ;no SpecialInfo
8475
8476 The next word contains the Gadget Identification (ID) number:
8477
8478 dc.w 1 ;gadget ID
8479
8480 Finally there is a long word that doesn't have any function,so put
8481 a zero here:
8482
8483 dc.l 0 ;user data (ignore)
8484
8485 Thats it.Heres a quick overview of the gadget structure:
8486
8487 gadget1:
8488 dc.l 0 ;no more gadgets
8489 dc.w 40 ;X and
8490 dc.w 50 ;Y position of gadget
8491 dc.w 32 ;width and
8492 dc.w 13 ;height of hit box
8493 dc.w 4 ;flags:image,invert
8494 dc.w $102 ;activation flags
8495 dc.w 1 ;gadget type:boolean
8496 dc.l image ;gadget image
8497 dc.l 0 ;no new gadget displayed
8498 dc.l ggtext ;gadget text
8499 dc.l 0 ;no exclude
8500 dc.l 0 ;no SpecialInfo
8501 dc.w 1 ;gadget ID
8502 dc.l 0 ;user data (ignore)
8503
8504 You've already prepared a structure that you can use for this
8505 image.Now you need the text that appears under the gadget.
8506 Since the gadget looks like a switch,label it "switch".The text
8507 structure looks like this:
8508
8509 ggtext:
8510 dc.b 1,0 ;colours
8511 dc.b 1 ;mode
8512 align
8513 dc.w -8,14 ;X and Y position
8514 dc.l 0 ;standard font
8515 dc.l swtext ;pointer to text
8516 dc.l 0 ;no more text
8517 swtext:
8518 dc.b "switch",0
8519 align
8520
8521 Once you've typed this in,save it,assemble it and start again.You
8522 can click the switch and cause it to be inverted.Click it again,
8523 and it appears normal.
8524 Now you can experriment with the structure.If you change the flag
8525 from four to five,you can cause the gadget to be framed when it is
8526 activated.Set the RELVERIFY bit(bit0:+1)in the Activation Flag
8527 word.Then you can move the mouse pointer onto the object and press
8528 the button.It is activated.Keep the mouse button pressed down and
8529 move the mouse.Once you leave the hit box,the activation disapears
8530 This way,you can avoid accidently activating a gadget.
8531 Now you want to display the switch in an on state.This is easy.All
8532 you need to do is produce another image structure,one for the on
8533 state.You put this pointer in the long word right after the
8534 pointer to the normal image structure.You can change the flag word
8535 to six which causes a second image to be displayed when the gadget
8536 is activated.
8537 Here is the image structure for the switch in the one state.
8538
8539 image2:
8540 dc.w 0,0 ;no offset
8541 dc.w 32,13 ;32x13 pixels
8542 dc.w 1 ;mode 1
8543 dc.l imgdata2 ;pointer to the data
8544 dc.b 2,1 ;same colours as before
8545 dc.l 0 ;nothing else
8546
8547 imgdata2: ;data for switch in the On state
8548 dc.l %00000000000000000000000000000000
8549 dc.l %00000000011100000000000000000000
8550 dc.l %00000000111110000011101001000000
8551 dc.l %00000000111110000010101101000000
8552 dc.l %00000000011110000010101011000000
8553 dc.l %00000000000111000011101001000000
8554 dc.l %00000000000011100000000000000000
8555 dc.l %00000000000001110000000000000000
8556 dc.l %00000000000111111111100000000000
8557 dc.l %00000000001111111111110000000000
8558 dc.l %00000000001111111111110000000000
8559 dc.l %00000000000110000001100000000000
8560 dc.l %00000000000000000000000000000000
8561
8562 Now the state of the object can be determined by looking at the
8563 picture.If the gadget is activated,the switch is on.If not,the
8564 switch is off.
8565 Thats it for boolean gadgets.You can learn about the things you
8566 did'nt touch with some experimentation.You want to get to the
8567 string gadgets that also do some interesting things.
8568
8569 7.9.2.String Gadgets.
8570 ---------------------
8571 Lets pretend you want a program to load data from the disk.To get
8572 the user to enter the filename,you need to output text telling the
8573 user to enter the name.Then you need to call an input routine to
8574 evaluate the keyboard input.
8575 Its easier and more elegant to use a String gadget.This function
8576 allows for easy input and/or editingof short text.You have the
8577 option of having the text framed.The Undo function can be used by
8578 pressing the right <Amiga> key and a "Q",and the old contents of
8579 the gadget,the old text are restored.
8580 You can also vary the size of the text and the input field.If the
8581 text is longer than the input field is wide,the text is moved back
8582 and forth through the visible area when you move the cursor keys
8583 or the normal input to the border.
8584 You can also restrict input to just digits.This makes it posible
8585 to accept numeric input.Intuition even converts the digit string
8586 into a binary number.This saves the machine language programmer
8587 some work.A specialized String gadget of this sort is called a
8588 Integer gadget.
8589 The structure is similar to the Boolean gadgets structure.There
8590 are only two major differences:
8591
8592 The type word of the structure must be a four to declare that this
8593 is a String gadget (STRGADGET).
8594
8595 The pointer to the SpecialInfo structure is needed.Put a pointer
8596 to the StringInfo structure that you are going to design later
8597 here.
8598
8599 The width and height entries in the gadget structure have a
8600 different meaning than they had previously.They do declare the
8601 area in which you can bring the mouse pointer to activate the
8602 String gadget.However,it is also used for representation of text.
8603 These values determine the size of the box in which the text is
8604 output.You should surround the box with a border using the Border
8605 function,so that the user can see where it is.
8606 If the text is longer than the box,only a portion of it is seen on
8607 the screen.You can move through the area by entering text or using
8608 the left/right cursor keys to move through the box.The characters
8609 that are entered are inserted at the cursor position,so the rest
8610 of the text is shifted by one character when you are on the right
8611 edge of the input area.The following functions can be used for
8612 editing this text:
8613
8614 Cursor key left/right
8615 Moves the cursor over the text thats already on hand.Moves
8616 the text through the Container.
8617
8618 Cursor keys with <Shift>
8619 Puts the cursor on the beginning or the end of the text.
8620
8621 <Del> Deletes the character under the cursor.
8622
8623 <Backspace>
8624 Deletes the character to the left of the cursor.
8625
8626 <Return>
8627 Ends text input.
8628
8629 <Amiga>right+"Q"
8630 This is the Undo function.It replaces the text with the
8631 original contents.
8632
8633 The StringInfo structure only has a few entries:
8634
8635 First theres a pointer to the memory area that is used to store
8636 the text that is input.The memory buffer must be big enough to
8637 handle all the text entered.
8638
8639 strinfo:
8640 dc.l strpuffer ;pointer to text buffer
8641
8642 Next comes the pointer to the Undo buffer.This pointer and this
8643 buffer are only needed if you want the Undo function.If you do,you
8644 must have a buffer that is at least as big as your text buffer.
8645 Every time the string gadget function is called,the text buffers
8646 contents are copied into this buffer.To get the old contents back,
8647 just press the right <Amiga>key and the "Q"key.The contents of the
8648 Undo buffer are copied back to the text buffer.If you use several
8649 string gadgets in a program,you can use the same Undo buffer for
8650 all of them,since only one string gadget is used at one time.
8651
8652 dc.l undo ;pointer to undo buffer
8653
8654 The following word contains the cursor position in the text.You
8655 should set this word to zero,so that the user can see the
8656 beginning of the text when the string gadget appears.
8657
8658 dc.w 0 ;cursor position
8659
8660 The next word contains the maximum number of characters that can
8661 be input.If you type one more than this number of characters,the
8662 screen blinks,to show that you can't enter a longer input string.
8663 The number of characters and the reserved space for the input
8664 field don't have to agree,since text can be scrolled by typing.
8665
8666 dc.w 10 ;maximum # of characters
8667
8668 The following word tells at which character of text in the buffer,
8669 the output to the box should begin.You should put a zero here,so
8670 that the user can see the beginning of the text.
8671
8672 dc.w 0 ;output text from this character
8673
8674 The next five words are used by Intuition,so you don't have to
8675 initialize them.Just put zeros here.The words contain the
8676 following information:
8677
8678 dc.w 0 ;character position in undo buffer
8679 dc.w 0 ;number of chars in text buffer
8680 dc.w 0 ;number of chars visible in box
8681 dc.w 0 ;horizontal box offset
8682 dc.w 0 ;vertical box offset
8683
8684 The next two long words are initialized by Intuition as well:
8685
8686 dc.l 0 ;pointer to rastport
8687 dc.l 0 ;long word with value of the input
8688 ; ;(for integer gadgets)
8689
8690 The final entry is a pointer to the keyboard table that is used if
8691 the ALTKEYMAP flag of the gadget is set.
8692
8693 dc.l 0 ;standard keyboard table
8694
8695 Heres a quick overview of the StringInfo structure:
8696
8697 strinfo:
8698 dc.l strpuffer ;pointer to text buffer
8699 dc.l undo ;pointer to undo buffer
8700 dc.w 0 ;cursor position
8701 dc.w 10 ;maximum # of characters
8702 dc.w 0 ;output text from this character
8703 dc.w 0 ;character position in undo buffer
8704 dc.w 0 ;number of chars in text buffer
8705 dc.w 0 ;number of chars visible in box
8706 dc.w 0 ;horizontal box offset
8707 dc.w 0 ;vertical box offset
8708 dc.l 0 ;pointer to rastport
8709 dc.l 0 ;long word with value of input
8710 ; ;(for integer gadgets)
8711 dc.l 0 ;standard keyboard table
8712
8713 Here are the text and undo buffers:
8714
8715 strpuffer:
8716 dc.b "Hello!",0,0,0
8717
8718 undo:
8719 dc.l 0,0,0,0
8720 align
8721
8722 Once you've entered these lines,you can either alter the old
8723 gadget structure or build a new one.We'd recommend building
8724 another gadget structure so that you can have the switch and use
8725 it later.Change the first pointer in the old structure from zero
8726 to "gadget1"and insert this new structure.Here is an example
8727 strucure for the string gadget.It as the following entries:
8728
8729 gadget1: ;*structure for string gadget
8730 dc.l 0 ;no more gadgets
8731 dc.w 20,80 ;position
8732 dc.w 80,10 ;width and height of box
8733 dc.w 0 ;flags:normal
8734 dc.w 2 ;activation($802 for long int)
8735 dc.w 4 ;type:string gadget
8736 dc.l border ;pointer to border
8737 dc.l 0 ;no drawing selected
8738 dc.l 0 ;no text
8739 dc.l 0 ;no exclude
8740 dc.l strinfo ;pointer to stringinfo structure
8741 dc.w 2 ;gadget ID
8742 dc.l 0 ;no user data
8743
8744 border: ;*border for box frame
8745 dc.w 0,0 ;no offset
8746 dc.b 3,3 ;red colour
8747 dc.b 0 ;mode:JAM1
8748 dc.b 5 ;5 X,Y pairs
8749 dc.l coord ;pointer to coordinates table
8750 dc.l 0 ;no more structures
8751
8752 coord: ;*coordinates for frame
8753 dc.w -2,-2 ;start in upper left corner
8754 dc.w 80,-2 ;upper right
8755 dc.w 80,9 ;lower right
8756 dc.w -2,9 ;lower left
8757 dc.w -2,-2 ;back to beginning
8758
8759 This data causes a red rectangle,the border,to appear around the
8760 "Hello!"text.You can change the text by clicking in the field and
8761 editing once the cursor appears.If you type something wrong,you
8762 can use the undo function(the right <Amiga> key and the Q key),to
8763 get "Hello!"back.
8764 Once you've done some typing and deactivated the gadget by
8765 pressing <Return> or by clicking outside the field (cursors
8766 disapear),you can terminate the program.
8767 Change the activation flag to $802 and the "strbuffer"to "dc.l
8768 0,0,0,0",assemble,and then start the program.You can type in the
8769 string gadget once it has been activated,but you can only enter
8770 digits.The screen blinks if you enter letters.
8771 Enter a number,and then end the program after deactivating the
8772 gadget.If you look at the stringinfo structure you can look at the
8773 value of the number you input(in hex)in the eight long word.
8774 After looking at boolean,text and numeric input to gadgets,lets
8775 look at Proportional gadgets which allow the user to enter analog
8776 values by moving a symbol.
8777
8778 7.9.3.Proportional Gadgets.
8779 ---------------------------
8780 You've seen the advantages of slider devices over knobs that you
8781 turn,maybe on a hifi,maybe on a toaster,but certainly someplace.
8782 Its easier to tell the state the item is in with a slider,
8783 especially if several such devices are next to each other(for
8784 example graphic equalizers).You can represent sliders on the
8785 Amigas screen and work with them with the mouse.This offers a nice
8786 way to represent information graphically in your programs.
8787 You can do this with gadgets.Using Proportional gadgets,you can
8788 put a symbol in a frame and move horzontally and/or vertically.The
8789 size of the frame and the slider can be variable size,so that the
8790 frame size is relative to the screen size so when the window
8791 changes size,it will also.The slider can be set up so that its
8792 size in the grows or shrinks.
8793 These are best seen via example and experimentation.(The
8794 posibilities mentioned do not form a complete list by any stretch
8795 of the imagination.)You want to set up a simple Proportional
8796 gadget that can be moved horizontally.
8797 You need a gadget structure that as the same form as others.To
8798 show the differences,heres a complete example structure for your
8799 gadget.You can connect this gadget to the other one,by changing
8800 the first long word in the last structure to "dc.l gadget2".
8801
8802 gadget2: ;*structure for Proportional gadget
8803 dc.l 0 ;no more gadgets
8804 dc.w 150,30 ;position
8805 dc.w 100,10 ;width and height of frame
8806 dc.w 4 ;flags:GADGIMAGE
8807 dc.w 2 ;activation:GADGIMMEDIATE
8808 dc.w 3 ;type:proportional gadget
8809 dc.l mover ;pointer to slider data
8810 dc.l 0 ;no select structure
8811 dc.l 0 ;no text
8812 dc.l 0 ;no exclude
8813 dc.l propinfo ;pointer to propinfo structure
8814 dc.w 3 ;gadget ID
8815 dc.l 0 ;no user data
8816
8817 You see two special features.Use an image structure for the mover
8818 and put a pointer to another structure in the spot for the Special
8819 Info pointer.
8820 First,lets look at the "mover"structure,the sliders image
8821 structure.Heres an example of this structure:
8822
8823 mover: ;*structure for slider image
8824 dc.w 0,0 ;no offset
8825 dc.w 16,7 ;16x7 pixels big
8826 dc.w 1 ;one bit plane
8827 dc.l moverdata ;pointer to image data
8828 dc.b 1,0 ;colour:white
8829 dc.l 0 ;don't continue
8830
8831 moverdata: ;*image data for mover
8832 dc.w %0111111111111110
8833 dc.w %0101111111111010
8834 dc.w %0101011111101010
8835 dc.w %0101010110101010
8836 dc.w %0101011111101010
8837 dc.w %0101111111111010
8838 dc.w %0111111111111110
8839
8840 Up till now,there was'nt anything new.Now lets look at the
8841 PropInfo structure that describes the properties of the
8842 Proportional gadget.
8843
8844 The structure starts with a flag word that contains the following
8845 bits:
8846
8847 Bits Value Name Meaning
8848 -----------------------------------------------------------------
8849 0 1 AUTOKNOB Mover is set up automatically
8850 1 2 FREEHORIZ Allows horizontal movement
8851 2 4 FREEVERT Allows vertical movement
8852 3 8 PROPBORDERLESS Turns off automatic framing
8853 8 $100 KNOBHIT Set when the mover is touched
8854
8855 You can set the first four bits to get the representation that you
8856 want.Bit 8 is set by Intuition when the mover is clicked with the
8857 mouse pointer.
8858 Bit 0,AUTOKNOB,allos for the simplest sort of Proportional gadget.
8859 If this bit is set,no move data are used for the mover image.
8860 Instead,a white mover is generated that is adjusted to the size of
8861 the box and the values to be represented.When you use this slider
8862 to represent the displayed lines in a long text of a program,the
8863 displayed lines are a percentage of the total text.The
8864 relationship between the total number of lines and the lines shown
8865 is represented by an AUTOKNOB as the relationship between the
8866 frame and the slider.The bigger the percentage,the bigger the
8867 slider is.You don't want to work with this though,even though it
8868 is simple and interesting,because a simple white button isn't
8869 particularly attractive.If you experiment with it,make sure that
8870 the pointer to the image data points to a four word long buffer
8871 that Intuition can use to store values.The buffer is of the
8872 following form:
8873
8874 buffer:
8875 dc.w 0 ;X position of the slider in the box
8876 dc.w 0 ;Y position in the box
8877 dc.w 0 ;width of slider
8878 dc.w 0 ;height of slider
8879
8880 Leys look at the PropInfo structure.Since you're not using
8881 AUTOKNOB and wish to allow horizontal movement only,put two in as
8882 a flag:
8883
8884 propinfo:
8885 dc.w 2 ;flags:FREEHORIZ
8886
8887 In the next two words of the structure,the horizontal (HorizPot)
8888 and vertical (VertPot) position of sliders are stored.A value of
8889 zero means left or upper,while the value $FFFF means right or
8890 lower.The value that results from movement is in this range.You
8891 set these values to zero at the start of the program.After moving
8892 the mouse,there is different values here.
8893
8894 dc.w 0,0 ;X and Y position of the slider
8895
8896 Next come two words which determine the size of the AUTOKNOB or
8897 the step size of the slider(this determines how far the slider
8898 moves when you click in the box next to the slider).These words
8899 are called HorizBody (horizontal movement) and VertBody (vertical
8900 movement).
8901
8902 dc.w $ffff/16 ;horizontal step size:1/16
8903 dc.w 0 ;no vertical movement
8904 ;The next six words are initialized by Intuition.
8905 dc.w 0 ;box width
8906 dc.w 0 ;box height
8907 dc.w 0 ;absolute step size horizontal
8908 dc.w 0 ;and vertical
8909 dc.w 0 ;left border of box
8910 dc.w 0 ;upper border of box
8911
8912 Thats it.Heres a quick overview of the PropInfo structure:
8913
8914 prpoinfo:
8915 dc.w 2 ;flags:FREEHORIZ
8916 dc.w 0,0 ;X and Y position of slider
8917 dc.w $ffff/16 ;horizontal step size:1/16
8918 dc.w 0 ;no vertical movement
8919 dc.w 0 ;box width
8920 dc.w 0 ;box height
8921 dc.w 0 ;absolute step size horizontal
8922 dc.w 0 ;and vertical
8923 dc.w 0 ;left border of box
8924 dc.w 0 ;upper border of box
8925
8926 Once you've typed this in,you can start the program and try it
8927 out.
8928 You can also try vertical movement by setting the flag word equal
8929 to six,the vertical step size to $FFFF/10,and the height of the
8930 gadget to 80,for the example.To try out the AUTOKNOBs,change the
8931 flag value to seven.
8932
8933 7.10.Example Program.
8934 ---------------------
8935 Here is a complete example program using what you have learned in
8936 this chapter:
8937
8938 ;7_Intuition.asm
8939 ;** Demo-Program for working with Intuition **
8940
8941 movescreen =-162
8942 openscreen =-198
8943 closescreen =-66
8944 openwindow =-204
8945 closewindow =-72
8946 autorequest =-348
8947 setmenustrip =-264
8948 clearmenustrip=-54
8949 printitext =-216
8950 drawimage =-144
8951 drawborder =-108
8952 displaybeep =-96
8953 closelibrary =-414
8954 openlib =-408
8955 execbase = 4
8956 getmsg =-372
8957
8958 joy2 =$dff0c
8959 fire =$bfe001
8960
8961 ;!!!when > 500kb !!!
8962 ;org $40000
8963 ;load $40000
8964 ; or use AssemPro to place in CHIP RAM
8965 ;!!!!!!!!!!!!!!!!!!!!!!!
8966
8967 run:
8968 bsr openint
8969 bsr scropen
8970 bsr windopen
8971 bsr setmenu
8972 bsr print
8973
8974 lea border,a1
8975 move #22,d0
8976 move #30,d1
8977 bsr borderdraw
8978
8979 bsr draw
8980
8981 bsr request
8982
8983 loop:
8984 move.l execbase,a6
8985 move.l windowhd,a0
8986 move.l 86(a0),a0 ;user port
8987 jsr getmsg(a6)
8988 tst.l d0
8989 beq loop ;no event
8990 move.l d0,a0
8991 move.l $16(a0),msg ;event:LO=item,HI=Event
8992 move.l msg,d6 ;to test
8993 move.l d6,d7
8994 lsr #8,d7
8995 lsr #3,d7 ;sub menu point in D7
8996 clr.l d5
8997 roxr #1,d6
8998 roxl #1,d5 ;menu number in D5
8999 and.l #$7f,d6
9000 cmp #$7f,d6 ;no menu point?
9001 beq loop ;no:continue
9002 lsr #4,d6 ;menu point in D6
9003 cmp #1,d6 ;point 2?
9004 bne no1
9005 move,l intbase,a6
9006 move.l screenhd,a0
9007 jsr displaybeep(a6)
9008
9009 no1:
9010 cmp #0,d6
9011 bne loop
9012
9013 ende:
9014 bsr clearmenu
9015 bsr windclose
9016 bsr scrclose
9017 bsr closeint
9018 rts
9019
9020 openint:
9021 move.l execbase,a6
9022 lea intname,a1
9023 jsr openlib(a6)
9024 move.l d0,intbase
9025 rts
9026
9027 closeint:
9028 move.l execbase,a6
9029 move.l intbase,a1
9030 jsr closelibrary(a6)
9031 rts
9032
9033 scropen:
9034 move.l inbase,a6
9035 lea screen_defs,a0
9036 jsr openscreen(a6)
9037 move.l d0,screenhd
9038
9039 scrclose:
9040 move.l inbase,a6
9041 move.l screenhd,a0
9042 jsr closescreen(a6)
9043 rts
9044
9045 scrmove:
9046 move.l intbase,a6
9047 move,l screenhd,a0
9048 jsr movescreen(a6)
9049 rts
9050
9051 windopen:
9052 move.l intbase,a6
9053 lea windowdef,a0
9054 jsr openwindow(a6)
9055 move.l d0,windowhd
9056 rts
9057
9058 windclose:
9059 move.l intbase,a6
9060 move.l windowhd,a0
9061 jsr closewindow(a6)
9062 rts
9063
9064 request:
9065 move.l windowhd,a0
9066 lea btext,a1
9067 lea ltext,a2
9068 lea rtext,a3
9069 move.l #0,d0
9070 move.l #0,d1
9071 move.l #180,d2
9072 move.l #80,d3
9073 move.l intbase,a6
9074 jsr autorequest(a6)
9075 rts
9076
9077 setmenu:
9078 lea mentab,a0 ;pointer to text pointer in A0
9079 lea menu,a1 ;pointer to menu field in A1
9080 move #10,d1 ;menu position = 10
9081
9082 menuloop:
9083 clr.l d2 ;menu point-Y=0
9084 move.l a1,a2 ;save pointer
9085 tst.l (a0)
9086 beq setmenu1 ;end
9087 clr.l (a1)+
9088 move d1,(a1)+
9089 add.l #70,d1
9090 move.l #50,(a1)+
9091 move.l #$a0001,(a1)+
9092 move.l (a0)+,(a1)+ ;menu title
9093 lea 12(a1),a3
9094 move.l a3,(a1)+ ;menu point
9095 clr.l (a1)+
9096 clr.l (a1)+
9097
9098 itemloop:
9099 tst.l (a0) ;last one?
9100 beq menuend ;yes
9101 lea 54(a1),a3
9102 move.l a3,(a1)+ ;pointer to next point
9103 move.l d2,(a1)+ ;X/Y
9104 add #10,d2
9105 move.l #$5a000a,(a1)+ ;width/height
9106 move #$52,(a1)+
9107 clr.l (a1)+
9108 lea 16(a1),a3
9109 move.l a3,(a1)+ ;text structor-pointer
9110 clr.l (a1)+
9111 clr.l (a1)+
9112 clr.l (a1)+
9113
9114 move #$1,(a1)+ ;text-structor set
9115 clr (a1)+
9116 move.l #$50003,(a1)+
9117 clr.l (a1)+
9118 move.l (a0)+,(a1)+ ;text pointer
9119 clr.l (a1)+
9120
9121 bra itemloop ;next point...
9122
9123 menuend:
9124 clr.l -54(a1)
9125 tst.l (a0)+
9126 tst.l (a0) ;still in menu?
9127 beq setmenu1 ;no:ready
9128 move.l a1,(a2) ;pointer to next menu
9129 bra menuloop ;and continue
9130
9131 setmenu1:
9132 move.l intbase,a6
9133 move.l windowhd,a0
9134 lea menu,a1
9135 jsr setmenustrip(a6)
9136 rts
9137
9138 clearmenu:
9139 move.l intbase,a6
9140 move.l windowhd,a0
9141 jsr clearmenustrip(a6)
9142 rts
9143
9144 print:
9145 move.l intbase,a6
9146 move.l windowhd,a0
9147 move.l 50(a0),a0
9148 lea ggtext,a1
9149 move.l #30,d0 ;X
9150 move.l #16,d1 ;Y
9151 jsr printitext(a6)
9152 rts
9153
9154 draw:
9155 move.l intbase,a6
9156 move.l windowhd,a0
9157 move.l 50(a0),a0
9158 lea image,a1
9159 move.l #200,d0
9160 move.l #100,d1
9161 jsr drawimage(a6)
9162 rts
9163
9164 borderdraw:
9165 move.l intbase,a6
9166 move.l windowhd,a0
9167 move.l 50(a0),a0
9168 jsr drawborder(a6)
9169 rts
9170
9171 screen_defs:
9172 dc.w 0,0
9173 dc.w 640,200
9174 dc.w 4
9175 dc.b 0
9176 dc.b 1
9177 dc.w $800
9178 dc.w 15
9179 dc.l 0
9180 dc.l tite1
9181 dc.l 0
9182 dc.l 0
9183
9184 windowdef:
9185 dc.w 10,20
9186 dc.w 300,150
9187 dc.b 0,1
9188 dc.l $300
9189 dc.l $100f
9190 dc.l gadget
9191 dc.l 0
9192 dc.l windname
9193
9194 screenhd:
9195 dc.l 0
9196 dc.l 0
9197 dc.w 200,40,600,200
9198 dc.w $f
9199
9200 btext:
9201 dc.b 3,3
9202 dc.b 0
9203 align
9204 dc.w 10,10
9205 dc.l 0
9206 dc.l bodytxt
9207 dc.l 0
9208
9209 bodytxt:dc.b "Requester-Text",0
9210 align
9211
9212 ltext:
9213 dc.b 3,1
9214 dc.b 0
9215 align dc.w 5,3
9216 dc.l 0
9217 dc.l lefttext
9218 dc.l 0
9219
9220 lefttext: dc.b "left",0
9221 align
9222
9223 rtext:
9224 dc.b 0,1
9225 dc.b 0
9226 align dc.w 5,3
9227 dc.l 0
9228 dc.l righttext
9229 dc.l 0
9230
9231 righttext: dc.b "right",0
9232 align
9233 tite1: dc.b "User Screen",0
9234 windname: dc.b "Window-Title",0
9235 align windowhd: dc.l 0
9236
9237 intbase:dc.l 0
9238 intname:dc.b "intuition.library",0
9239 align msg:dc.l 0
9240
9241 mentab:
9242 dc.l menu1
9243 dc.l mp11,np12,mp13,mp14,mp15,mp16,mp17,mp18,mp19,0
9244 dc.l menu2
9245 dc.l mp21,mp22,mp23,0
9246 dc.l menu3
9247 dc.l mp31,mp32,0
9248 dc.l menu4,mp41,0
9249 dc.l 0
9250
9251 menu1: dc.b "Menu 1",0
9252 mp11: dc.b "Point 11",0
9253 mp12: dc.b "Point 12",0
9254 mp13: dc.b "Point 13",0
9255 mp14: dc.b "Point 14",0
9256 mp15: dc.b "Point 15",0
9257 mp16: dc.b "Point 16",0
9258 mp17: dc.b "Point 17",0
9259 mp18: dc.b "Point 18",0
9260 mp19: dc.b "Point 19",0
9261
9262 menu2: dc.b "Menu 2",0
9263 mp21: dc.b "End!",0
9264 mp22: dc.b "Beep",0
9265 mp23: dc.b "Point 23",0
9266
9267 menu3: dc.b "Menu 3",0
9268 mp31: dc.b "Point 31",0
9269 mp32: dc.b "Point 32",0
9270
9271 menu4: dc.b "Menu 4",0
9272 mp41: dc.b "Point 41",0
9273 align
9274
9275 gadget:
9276 dc.l gadget1
9277 dc.w 20,80,80,10
9278 dc.w 0
9279 dc.w $2 ;activation,$802 for longint
9280 dc.w 4
9281 dc.l border
9282 dc.l 0
9283 dc.l 0
9284 dc.l 0
9285 dc.l strinfo
9286 dc.w 2
9287 dc.l 0
9288
9289 border:
9290 dc.w 0,0
9291 dc.b 1,0,0
9292 dc.d 5 ;XY-pair
9293 dc.l koord
9294 dc.l 0
9295
9296 koord:
9297 dc.w -2,-2,80,-2,80,9,-2,9,-2,-2
9298
9299 strinfo:
9300 dc.l strpuffer
9301 dc.l undo
9302 dc.w 0 ;cursor position
9303 dc.w 10 ;max.char
9304 dc.w 0
9305 dc.w 0,0,0,0,0
9306 dc.l 0,0,0
9307
9308 strpuffer:
9309 dc.b "Hello!",0,0,0
9310
9311 undo: dc.l 0,0,0
9312 align
9313
9314 gadget1:
9315 dc.l gadget2 ;more gadget
9316 dc.w 40,50,32,13
9317 dc.w $6 ;flags:invert
9318 dc.w $103 ;activate
9319 dc.w 1 ;gadget type
9320 dc.l image ;gadget image
9321 dc.l image2 ;select gadget
9322 dc.l ggtext ;gadget text
9323 dc.l 0 ;no exclude
9324 dc.l 0 ;special info
9325 dc.w 1 ;ID
9326 dc.l 0 ;user data
9327
9328 ggtext:
9329 dc.b 1,0,1
9330 align
9331 dc.w -8,14
9332 dc.l 0
9333 dc.l swtext
9334 dc,l 0
9335
9336 swtext:
9337 dc.b "Switch",0
9338 align
9339
9340 image:
9341 dc.w 0,0
9342 dc.w 32,13
9343 dc.w 1
9344 dc.l imgdata
9345 dc.b 2,1
9346 dc.l 0
9347
9348 image2:
9349 dc.w 0,0
9350 dc.w 32,13
9351 dc.w 1
9352 dc.l imgdata2
9353 dc.b 2,1
9354 dc.l 0
9355
9356 imgdata:
9357 dc.l 0
9358 dc.l %00000000011100000000000000000000
9359 dc.l %00000000111110000011101001000000
9360 dc.l %00000000111110000010101101000000
9361 dc.l %00000000011110000010101011000000
9362 dc.l %00000000000111000011101001000000
9363 dc.l %00000000000011100000000000000000
9364 dc.l %00000000000001110000000000000000
9365 dc.l %00000000000111111111100000000000
9366 dc.l %00000000001111111111110000000000
9367 dc.l %00000000001111111111110000000000
9368 dc.l %00000000000110000001100000000000
9369 dc.l 0
9370
9371 imgdata2:
9372 dc.l 0
9373 dc.l %00000000000000000000111000000000
9374 dc.l %00011101110111000001111100000000
9375 dc.l %00010101000100000001111100000000
9376 dc.l %00010101100110000001111000000000
9377 dc.l %00011101000100000011100000000000
9378 dc.l %00000000000000000111000000000000
9379 dc.l %00000000000000001110000000000000
9380 dc.l %00000000000111111111100000000000
9381 dc.l %00000000001111111111110000000000
9382 dc.l %00000000001111111111110000000000
9383 dc.l %00000000000110000001100000000000
9384 dc.l 0
9385
9386 gadget2:
9387 dc.l 0
9388 dc.w 150,30,100,50
9389 dc.w 5
9390 dc.w 2
9391 dc.w 3 ;prop.gadet
9392 dc.l mover ;border
9393 dc.l 0,0,0
9394 dc.l specinfo
9395 dc.w 3
9396 dc.l 0
9397
9398 specinfo:
9399 dc.w 6 ;flags:free horiz
9400 dc.w 0,0
9401 dc.w $ffff/10,$ffff/5
9402 dc.w 0,0,0,0,0,0
9403
9404 mover:
9405 dc.w 0,0,16,7
9406 dc.w 1
9407 dc.l moverdata
9408 dc.b 1,0
9409 dc.l 0
9410
9411 moverdata:
9412 dc.w %0111111111111110
9413 dc.w %0101111111111010
9414 dc.w %0101011111101010
9415 dc.w %0101010110101010
9416 dc.w %0101011111101010
9417 dc.w %0101111111111010
9418 dc.w %0111111111111110
9419
9420 menu:blk.w 500
9421
9422 end
9423
9424
9425
9426
9427 Chapter 8.
9428 ----------
9429 8.Advanced Programming.
9430 -----------------------
9431 You've learned a lot about machine language programming on the
9432 Amiga.What you need yet are a few routines that can be used as
9433 programming tools.We'll work on that right now.They'll be easy to
9434 use in your own program.The sky's the limit now!
9435
9436 8.1.Supervisor Mode.
9437 --------------------
9438 As mentioned in the chapter on the MC68000 processor,there are two
9439 operating modes:the User and the Supervisor mode.It is often
9440 necessary to move between the two modes.However,this isn't a
9441 simple process.
9442 The reason you want to do this,is that in User mode,you can't
9443 access the Status register.If you write to one of them,an
9444 Exception is executed which crashes the program.
9445
9446 How can you get in Supervisor mode?
9447
9448 No problem.The operating system of the Amiga contains a function
9449 in the EXEC library that lets you get into supervisor mode.Its
9450 called SuperState and it doesn't need any parameters.You can
9451 easily call this program by using the following lines:
9452
9453 execbase = 4 ;exec base address
9454 superstate =-150 ;turn on function
9455 ...
9456 move.l execbase,a6 ;exec base address in A6
9457 jsr superstate(a6) ;turn on supervisor mode
9458 move.l d0,savesp ;save return value
9459 ...
9460 savesp:blk.l 1 ;space for sp value
9461
9462 You get the value of the Stack Pointer(SP)back in the D0 register.
9463 You'll also find it in register A7,but this register is changed
9464 regularly.The reason is that in Supervisor mode,the Amiga works
9465 with all the Interrupts and with the SP,and there are lots of
9466 Interrupts for this computor.We'll talk about interrupts in a bit.
9467
9468 After this call,you'll use the user stack instead of the
9469 supervisor stack.In this way,you can access the old user stack.You
9470 need to make sure that the user stack is large enough since the
9471 interrupts must have enough room for their data on the stack.
9472 You need to save the value returned in D0,because you'll need this
9473 value later.You need to return to user mode sometime.Theres a
9474 function for this in the exec library as well.It is called the
9475 UserState function.It needs one parameter,the SP value that comes
9476 back from the SuperState function.
9477 Since you've saved this value in the long word starting at
9478 "savesp",you can write the following:
9479
9480 userstate =-156
9481 ...
9482 move.l execbase,a6 ;exec base address in A6
9483 move.l savesp,d0 ;put old sp in D0
9484 jsr userstate(a6) ;return to user mode
9485
9486 Now you are back in the user mode.The user stack point(USP)is the
9487 same as before.You can write functions that need to be run from
9488 the supervisor mode as subroutines.First you call superstate,save
9489 the return value,execute the desired function,call userstate,and
9490 end with a RTS command.If the USP was changed,the RTS command
9491 would'nt work right,and the computor would jump who knows where
9492 and perhaps crash.Here it works though.
9493 Now comes the question:how does the operating system get the
9494 supervisor mode?Thats not too difficult;it goes like this:
9495
9496 The superstate function attempts to access a Status Register.This
9497 causes an Exception to occur and a routine is called whose address
9498 begins at the long word starting at $20.It is the Exception Vector
9499 for Privilege Violation.The routine that it branches to is called
9500 in supervisor mode.Then it tests where this exception came from.If
9501 the routine finds that the exception comes from the superstate
9502 routine whose address it knows,the matter is settled.It just
9503 branches to the routine without turning off the user mode.Thats
9504 all there is to it.
9505
9506 8.2.Exception Programming.
9507 --------------------------
9508 The exceptions described in the processor chapter offer you a lot
9509 of oppertunities to control the Amiga's functions.You can use them
9510 to specify how errors should be handled and even list a crash
9511 program.
9512
9513 Here is a list of vectors that are used to jump to the exception
9514 routines:
9515
9516 Number Address Use with
9517 ------------------------------------------------------------------
9518 2 $008 Bus error
9519 3 $00C Address eror
9520 4 $010 Illegal command
9521 5 $014 Division by zero
9522 6 $018 CHK command
9523 7 $01C TRAPV command
9524 8 $020 Privilege Violation
9525 9 $024 Trace
9526 10 $028 Axxx command emulation
9527 11 $02C Fxxx command emulation
9528 $030-$038 Reserved
9529 15 $03C Uninitialized interrupt
9530 $040-$05F Reserved
9531 24 $060 Unauthorised interrupt
9532 25-31 $064-$083 Level 1-7 interrupt
9533 32-47 $080-$0BF TRAP commands
9534 $0C0-$0FF Reserved
9535 64-255 $100-$3FF User interrupt vector
9536
9537 Lets look at the TRAP commands as an example.They aren't used in
9538 the Amiga operating system.A TRAP command and a number between
9539 zero and fifteen are used to call one of the 16 posible TRAP
9540 routines.If the command TRAP #0 is executed,the processor (in
9541 supervisor mode)branches to the routine whose address lies at $80
9542 in memory.This routine must end with a RTE(ReTurn from Exception)
9543 command.
9544 Some operating systems,for example,the ATARI ST's TOS operating
9545 systems,are completely callable via these TRAP's.Parameters are
9546 put on the stack,and then a TRAP command is executed.The advantage
9547 is that you don't have to know any of the operating systems
9548 addresses.In the Amiga you must know the addresses(Execbase=4).
9549
9550 Lets write your own TRAP routine to demonstrate the use of the
9551 TRAP command.You'll need three program sections:
9552
9553 1.The initialization of the TRAP vector.
9554 2.The TRAP routine itself(It must end with RTE).
9555 3.A test routine that calls the TRAP command.
9556
9557 Initialization is very short:
9558
9559 init:
9560 move.l #trap0,$80 ;set vector for TRAP #0
9561 rts
9562
9563 Now you need to write the trap0 routine.Lets use the example from
9564 the hardware chapter that produced a beep.
9565 Lets write this routine using as little effort as possible.Change
9566 the RTS to a RTE at the end,erase the line in which the loop
9567 counter D0 was loaded for the tone production,and change the loop
9568 so that it works with long words.Now you can load the register
9569 with an arbitrary value and have the TRAP #0 followed by a peep of
9570 arbitrary duration.
9571
9572 ;** beep tone production after a TRAP #0 **
9573
9574 ctlw =$dff096 ;DMA control
9575 c0thi =$dff0a0 ;HI table address
9576 c0tlo =c0thi+2 ;LO table address
9577 c0tl =c0thi+4 ;table length
9578 c0per =c0thi+6 ;read in rate
9579 c0vol =c0thi+8 ;volume
9580
9581 trap0: ;* produce a short peep
9582 move.l #table,c0thi ;table beginning
9583 move #4,c0tl ;table length
9584 move #300,c0per ;read in rate
9585 move #40,c0vol ;volume
9586 move #$8201,ctlw ;start DMA (sound)
9587
9588 loop:
9589 subq.l #1,d0 ;counter -1
9590 bne loop ;count dwn to zero
9591
9592 still:
9593 move #1,ctlw ;turn on tone
9594 rte ;exception end
9595
9596 table: ;sound table
9597 dc.b -40,-70,-40,0,40,70,40,0
9598
9599 You need to make sure that "table"is in CHIP RAM($00000-$7FFFF),
9600 otherwise the sound chip can't access the data!
9601
9602 After entering this,you can test it out using the following
9603 routine:
9604
9605 test:
9606 move.l #$2ffff,d0 ;pass tone length in D0
9607 trap #0 ;carry out exception:peep
9608 rts
9609
9610 Now assemble both routines and start the initialization routine,
9611 init.Nothing happens.
9612 Start the second routine,test.A beep that lasts about one second
9613 is output.
9614 One thing you must keep in mind is that if you change the program
9615 and reassemble it,the address of the trap0 routine can change.
9616 Before you execute the TRAP command,you must repeat the initializ-
9617 ation,so that the computor doesn't jump to the wrong location!
9618
9619
9620
9621
9622 Appendices.
9623 -----------
9624 Overview of Library Functions.
9625 ------------------------------
9626 The following table gives you an overview of the available
9627 libraries and their functions.Each sublist of functions is
9628 preceded by the name of the library it is found in.
9629 These functions are listed with their negative offset in hex and
9630 decimal.Their name and their parameters are also specified.The
9631 parameter names are in parenthesis behind the function name.The
9632 second set of parenthesis includes a list of registers that
9633 correspond to the parameter names.If no parameters are needed,we
9634 put () to let you know.
9635
9636 CLIST.LIBRARY
9637 -$001E -30 InitCLPool (cLPool,size) (A0,D0)
9638 -$0024 -36 AllocCList (cLPool) (A1)
9639 -$002A -42 FreeCList (cList) (A0)
9640 -$0030 -48 FlushCList (cList) (A0)
9641 -$0036 -54 SizeCList (cList) (A0)
9642 -$003C -60 PutCLChar (cList,byte) (A0,D0)
9643 -$0042 -66 GetCLChar (cList) (A0)
9644 -$0048 -72 UnGetCLChar (cList,byte) (A0,D0)
9645 -$004E -78 UpPutCLChar (cList) (A0)
9646 -$0054 -84 PutCLWord (cList,word) (A0,D0)
9647 -$005A -90 GetCLWord (cList) (A0)
9648 -$0060 -96 UnGetCLWord (cList,word) (A0,D0)
9649 -$0066 -102 UnPutCLWord (cList) (A0)
9650 -$006C -108 PutCLBuf (cList,buffer,length) (A0,A1,D1)
9651 -$0072 -114 GetCLBuf (cList,buffer,maxLength) (A0,A1,D1)
9652 -$0078 -120 MarkCList (cList,offset) (A0,D0)
9653 -$007E -126 IncrCLMark (cList) (A0)
9654 -$0084 -132 PeekCLMark (cList) (A0)
9655 -$008A -138 SplitCList (cList) (A0)
9656 -$0090 -144 CopyCList (cList) (A0)
9657 -$0096 -150 SubCList (cList,index,length) (A0,D0.D1)
9658 -$009C -156 ConcatCList (sourceCList,destCList) (A0,A1)
9659
9660 CONSOLE.LIBRARY
9661 -$002A -42 CDInputHandler (events,device) (A0,A1)
9662 -$0030 -48 RawKeyConvert (events,buffer,length,keyMap)
9663 (A0,A1,D1,A2)
9664 DISKFONT.LIBRARY
9665 -$001E -30 OpenDiskFont (textAttr) (A0)
9666 -$0024 -36 AvailFonts (buffer,bufBytes,flags) (A0,D0,D1)
9667
9668 DOS.LIBRARY
9669 -$001e -30 Open (name,access mode)(d1,d2)
9670 -$0024 -36 Close (file)(d1)
9671 -$002a -42 Read (file,buffer,length)(d1,d2,d3)
9672 -$0030 -48 Write (file,buffer,length)(d1,d2,d3)
9673 -$0036 -54 Input()
9674 -$003c -60 Output()
9675 -$0042 -66 Seek(file,position,offset)(d1,d2,d3)
9676 -$0048 -72 DeleteFile (name)(d1)
9677 -$004e -78 Rename(oldname,newname)(d1,d2)
9678 -$0054 -84 Lock(name,type)(d1,d2)
9679 -$005a -90 UnLock(lock)(d1)
9680 -$0060 -96 DupLock(lock)(d1)
9681 -$0066 -102 Examine(lock,fileinfoblock)(d1,d2)
9682 -$006c -108 ExNext(lock,fileinfoblock)(d1,d2)
9683 -$0072 -114 Info(lock,parameterblock)(d1,d2)
9684 -$0078 -120 CreateDir(name)(d1)
9685 -$007e -126 CurrentDir(lock)(d1)
9686 -$0084 -132 IoErr()
9687 -$008a -138 CreateProc(name,pri,seglist,stacksize)(d1,d2,d3,d4)
9688 -$0090 -144 Exit(returncode)(d1)
9689 -$0096 -150 LoadSeg(filename)(d1)
9690 -$009c -156 UnLoadSeg(segment)(d1)
9691 -$00a2 -162 Getpacket(wait)(d1)
9692 -$00a8 -168 Queuepacket(packet)(d1)
9693 -$00ae -174 DeviceProc(name)(d1)
9694 -$00be -180 SetComment(name,comment)(d1,d2)
9695 -$ooba -186 SetProtection(name,mask)(d1,d2)
9696 -$00c0 -192 DateStamp(date)(d1)
9697 -$00c6 -198 Delay(timeout)(d1)
9698 -$00cc -204 WaitForChar(file,timeout)(d1,d2)
9699 -$00d2 -210 ParentDir(lock)(d1)
9700 -$00d8 -216 IsInteractive(file)(d1)
9701 -$00de -222 Execute(string,file,file)(d1,d2,d3)
9702
9703 EXEC.LIBRARY
9704 -$001e -30 Supervisor()
9705 -$0024 -36 ExitIntr()
9706 -$002a -42 Schedule()
9707 -$0030 -48 Reschedule()
9708 -$0036 -54 Switch()
9709 -$003c -60 Dispatch()
9710 -$0042 -66 Exception()
9711 -$0048 -72 InitCode(startclass,version)(d0,d1)
9712 -$004e -78 InitStruct(inittable,memory,size)(a1,a2,d0)
9713 -$0054 -84 MakeLibrary(funcinit,structinit,libinit,datasize,
9714 codesize)(a0,a1,a2,d0,d1)
9715 -$005a -90 MakeFunctions(target,functionarray,funcdispbase)
9716 (a0,a1,a2)
9717 -$0060 -96 FindResident(name)(a1)
9718 -$0066 -102 InitResident(resident,seglist)(a1,d1)
9719 -$006c -108 Alert(alertnum,parameters)(d7,a5)
9720 -$0072 -114 Debug()
9721 -$0078 -120 Disable()
9722 -$007e -126 Enable()
9723 -$0084 -132 Forbid()
9724 -$008a -138 Permit()
9725 -$0090 -144 SetSR(newsr,mask)(d0,d1)
9726 -$0096 -150 SuperState()
9727 -$009c -156 UserState(sysstack)(d0)
9728 -$00a2 -162 setIntVector(intnumber,interrupt)(d0,d1)
9729 -$00a8 -168 AddIntServer(intnumber,interrupt)(d0,d1)
9730 -$00ae -174 RemIntServer(intnumber,interrupt)(d0,d1)
9731 -$00b4 -180 Cause(interrup)(a1)
9732 -$00ba -186 Allocate(freelist,bytesize)(a0,d0)
9733 -$00c0 -192 Deallocate(freelist,memoryblock,bytesize)(a0,a1,d0)
9734 -$00c6 -198 AllocMem(bytesize,requirements)(d0,d1)
9735 -$00cc -204 AlloAbs(bytesize,location)(d0,a1)
9736 -$00d2 -210 FreeMem(memoryblock,bytesize)(a1,d0)
9737 -$00d8 -216 AvailMem(requirements)(d1)
9738 -$00de -222 AllocEntry(entry)(a0)
9739 -$00e4 -228 FreeEntry(entry)(a0)
9740 -$00ea -234 Insert(list,node,pred)(a0,a1,a2)
9741 -$00f0 -240 AddHead(list,node)(a0,a1)
9742 -$00f6 -246 AddTail(list,node)(a0,a1)
9743 -$00fc -252 Remove(node)(a1)
9744 -$0102 -258 RemHead(list)(a0)
9745 -$0108 -264 RemTail(list)(a0)
9746 -$010e -270 Enqueue(list,node)(a0,a1)
9747 -$0114 -276 FindName(list,name)(a0,a1)
9748 -$011a -282 AddTask(task,initpc,finalpc)(a1,a2,a3)
9749 -$0120 -288 RemTask(task)(a1)
9750 -$0126 -294 FindTask(name)(a1)
9751 -$012c -300 SetTaskPri(task,prority)(a1,d0)
9752 -$0132 -306 SetSignal(newsignals,signelset)(d0,d1)
9753 -$0138 -312 SetExcept(newsignals,signalset)(d0,d1)
9754 -$013e -318 Wait(signalset)(d0)
9755 -$0144 -324 Signal(task,signalset)(a1,d0)
9756 -$014a -330 AllocSignal(signalnum)(d0)
9757 -$0150 -336 FreeSignal(signalnum)(d0)
9758 -$0156 -342 AllocTrap(trapnum)(d0)
9759 -$015c -348 FreeTrap(trapnum)(d0)
9760 -$0162 -354 AddPort(port)(a1)
9761 -$0168 -360 RemPort(port)(a1)
9762 -$016e -366 PutMsg(port,message)(a0,a1)
9763 -$0174 -372 GetMsg(port)(a0)
9764 -$017a -378 ReplyMsg(message)(a1)
9765 -$0180 -384 WaitPort(port)(a0)
9766 -$0186 -390 FindPort(name)(a1)
9767 -$018c -396 AddLibrary(library)(a1)
9768 -$0192 -402 RemLibrary(library)(a1)
9769 -$0198 -408 OldOpenLibrary(libname)(a1)
9770 -$019e -414 CloseLibrary(library)(a1)
9771 -$01a4 -420 Setfunction(library,funcoffset,funcentry)(a1,a0,d0)
9772 -$01aa -426 SumLibrary(library)(a1)
9773 -$01b0 -432 AddDevice(device)(a1)
9774 -$01b6 -438 RemDevice(device)(a1)
9775 -$01bc -444 OpenDevice(devname,unit,iorequest,flags)(a0,d0,a1
9776 ,d1)
9777 -$01c2 -450 CloseDevice(iorequest)(a1)
9778 -$01c8 -456 DoIO(iorequest)(a1)
9779 -$01ce -462 SendIO(iorequest)(a1)
9780 -$01d4 -468 CheckIO(iorequest)(a1)
9781 -$01da -474 WaitIO(iorequest)(a1)
9782 -$01e0 -480 AbortIO(iorequest)(a1)
9783 -$01e6 -486 AddResource(resource)(a1)
9784 -$01ec -492 RemResource(resource)(a1)
9785 -$01f2 -498 OpenResource(resname,version)(a1,d0)
9786 -$01f8 -504 RawIOInit()
9787 -$01fe -510 RawMayGetChar()
9788 -$0204 -516 RawPutChar(char)(d0)
9789 -$020a -522 RawDoFmt()(a0,a1,a2,a3)
9790 -$0210 -528 GetCC()
9791 -$0216 -534 TypeOfMem(address)(a1)
9792 -$021c -540 Procedure(semaport,bidmsg)(a0,a1)
9793 -$0222 -546 Vacate(semaport)(a0)
9794 -$0228 -552 OpenLibrary(libname,version)(a1,d0)
9795
9796 GRAPHICS.LIBRARY
9797 -$001e -30 BltBitMap(scrbitmap,scrx,scry,destbitmap,destx,
9798 desty,sizex,sizey,minterm,mask,tempa)
9799 (a0,d0,d1,a1,d2,d3,d4,d5,d6,d7,a2)
9800 -$0024 -36 BltTemplate(source,scrx,scrmod,destrastport,destx,
9801 desty,sixex,sizey)(a0,d0,d1,a1,d2,d3,d4,d5)
9802 -$002a -42 ClearEOL(rastport)(a1)
9803 -$0030 -48 ClearScreen(rastport)(a1)
9804 -$0036 -54 TextLength(rastport,string,count)(a1,a0,d0)
9805 -$003c -60 Text(rastport,string,count)(a1,a0,d0)
9806 -$0042 -66 SetFont(rastportid,textfont)(a1,a0)
9807 -$0048 -72 OpenFont(textattr)(a0)
9808 -$004e -78 CloseFont(textfont)(a1)
9809 -$0054 -84 AskSoftStyle(rastport)(a1)
9810 -$005a -90 SetSoftStyle(rastport,style,enable)(a1,d0,d1)
9811 -$0060 -96 AddBob(bob,rastport)(a0,a1)
9812 -$0066 -102 AddVSprite(vsprite,rastport)(a0,a1)
9813 -$006c -108 DoCollision(rastport)(a1)
9814 -$0072 -114 DrawGList(rastport,viewport)(a1,a0)
9815 -$0078 -120 InitGels(dummyhead,dummytail,gelsinfo)(a0,a1,a2)
9816 -$007e -126 InitMasks(vsprite)(a0)
9817 -$0084 -132 RemIBob(bob,rastport,viewport)(a0,a1,a2)
9818 -$008a -138 RemVSprite(vsprite)(a0)
9819 -$0090 -144 SetCollision(type,routine,gelsinfo)(d0,a0,a1)
9820 -$0096 -150 SortGList(rastport)(a1)
9821 -$009c -156 AddAnimObj(obj,animationkey,rastport)(a0,a1,a2)
9822 -$00a2 -162 Animate(animationkey,rastport)(a0,a1)
9823 -$00a8 -168 etGBuffers(animationobj,rastport,doublebuffer)(a0,
9824 a1,d0)
9825 -$00ae -174 InitGMasks(animationobj)(a0)
9826 -$00b4 -180 GelsFuncE()
9827 -$00ba -186 GelsFuncF()
9828 -$00c0 -192 LoadRGB4(viewport,colurs,count)(a0,a1,d0)
9829 -$00c6 -198 InitRastPort(rastport)(a1)
9830 -$00cc -204 InitVPort(viewport)(a0)
9831 -$00d2 -210 MrgCop(view)(a1)
9832 -$00D8 -216 MakeVPort (view,viewPort) (A0,A1)
9833 -$00DE -222 LoadView (view) (A1)
9834 -$00E4 -228 WaitBlit ()
9835 -$00EA -234 SetRast (rastPort,color) (A1,D0)
9836 -$00F0 -240 Move (rastPort,x,y) (A1,D0,D1)
9837 -$00F6 -246 Draw (rastPort,x,y) (A1,D0,D1)
9838 -$00FC -252 AreaMove (rastPort,x,y) (A1,D0,D1)
9839 -$0102 -258 AreaDraw (rastPort,x,y) (A1,D0,D1)
9840 -$0108 -264 AreaEnd (rastPort) (A1)
9841 -$010E -270 WaitTOF ()
9842 -$0114 -276 QBlit (blit) (A1)
9843 -$011A -282 InitArea (areaInfo,vectorTable,vectorTableSize)
9844 (A0,A1,D0)
9845 -$0120 -288 SetRGB4 (viewPort,index,r,g,b) (A0,D0,D1,D2,D3)
9846 -$0126 -294 QBSBlit (blit) (A1)
9847 -$012C -300 BltClear (memory,size,flags) (A1,D0,D1)
9848 -$0132 -306 RectFill (rastPort,xl,yl,xu,yu)
9849 (A1,D0,D1,D2,D3)
9850 -$0138 -312 BltPattern (rastPort,ras,xl,yl,maxX,maxY,
9851 fillBytes) (A1,A0,D0,D1,D2,D3,D4)
9852 -$013E -318 ReadPixel (rastPort,x,y) (A1,D0,D1)
9853 -$0144 -324 WritePixel (rastPort,x,y) (A1,D0,D1)
9854 -$014A -330 Flood (rastPort,mode,x,y) (A1,D2,D0,D1)
9855 -$0150 -336 PolyDraw (rastPort,count,polyTable) (A1,D0,A0)
9856 -$0156 -342 SetAPen (rastPort,pen) (A1,D0)
9857 -$015C -348 SetBPen (rastPort,pen) (A1,D0)
9858 -$0162 -354 SetDrMd (rastPort,drawMode) (A1,D0)
9859 -$0168 -360 InitView (view) (A1)
9860 -$016E -366 CBump (copperList) (A1)
9861 -$0174 -372 CMove (copperList,destination,data) (A1,D0,D1)
9862 -$017A -378 CWait (copperList,x,y) (A1,D0,D10
9863 -$0180 -384 VBeamPos ()
9864 -$0186 -390 InitBitMap (bitMap,depth,width,height)
9865 (A0,D0,D1,D2)
9866 -$018C -396 ScrollRaster (rastPort,dX,dY,minx,miny,maxx,
9867 maxy) (A1,D0,D1,D2,D3,D4,D5)
9868 -$0192 -402 WaitBOVP (viewPort) (A0)
9869 -$0198 -408 GetSprite (simpleSprite,num) (A0,D0)
9870 -$019E -414 FreeSprite (num) (D0)
9871 -$01A4 -420 ChangeSprite (vp,simpleSprite,data) (A0,A1,A2)
9872 -$01AA -426 MoveSprite (viewPort,simpleSprite,x,y)
9873 (A0,A1,D0,D1)
9874 -$01B0 -432 LockLayerRom (layer) (A5)
9875 -$01B6 -438 UnlockLayerRom (layer) (A5)
9876 -$01BC -444 SyncSBitMap (1) (A0)
9877 -$01C2 -450 CopySBitMap (11,12) (A0,A1)
9878 -$01C8 -456 OwnBlitter ()
9879 -$01CE -462 DisownBlitter ()
9880 -$01D4 -468 InitTmpRas (tmpras,buff,size) (A0,A1,D0)
9881 -$01DA -474 AskFont (rastPort,textAttr) (A1,A0)
9882 -$01E0 -480 AddFont (textFont) (A1)
9883 -$01E6 -486 RemFont (textFont) (A1)
9884 -$01EC -492 AllocRaster (width,height) (D0,D1)
9885 -$01F2 -498 FreeRaster (planeptr,width,height) (A0,D0,D1)
9886 -$01F8 -504 AndRectRegion (rgn,rect) (A0,A1)
9887 -$01FE -510 OrRectRegion (rgn,rect) (A0,A1)
9888 -$0204 -516 NewRegion ()
9889 -$020A -522 ** reserved **
9890 -$0210 -528 ClearRegion (rgn) (A0)
9891 -$0216 -534 DisposeRegion (rgn) (A0)
9892 -$021C -540 FreeVPortCopLists (viewPort) (A0)
9893 -$0222 -546 FreeCopList (coplist) (A0)
9894 -$0228 -552 ClipBlit (srcrp,srcX,srcY,destrp,destX,destY,
9895 sizeX,sizeY,minterm) (A0,D0,D1,A1,D2,D3,D4,D5,D6)
9896 -$022E -558 XorRectRegion (rgn,rect) (A0,A1)
9897 -$0234 -564 FreeCprList (cprlist) (A0)
9898 -$023A -570 GetColorMap (entries) (D0)
9899 -$0240 -576 FreeColorMap (colormap) (A0)
9900 -$0246 -582 GetRGB4 (colormap,entry) (A0,D0)
9901 -$024C -588 ScrollVPort (vp) (A0)
9902 -$0252 -594 UCopperListInit (copperlist,num) (A0,D0)
9903 -$0258 -600 FreeGBuffers (animationObj,rastPort,
9904 doubleBuffer) (A0,A1,D0)
9905 -$025E -606 BltBitMapRastPort (srcbm,srcx,srcy,destrp,
9906 destX,destY,sizeX,sizeY,minter)
9907 (A0,D0,D1,A1,D2,D3,D4,D5,D6)
9908
9909 ICON.LIBRARY
9910 -$001E -30 GetWBObject (name) (A0)
9911 -$0024 -36 PutWBObject (name,object) (A0,A1)
9912 -$002A -42 GetIcon (name,icon,freelist) (A0,A1,A2)
9913 -$0030 -48 PutIcon (name,icon) (A0,A1)
9914 -$0036 -54 FreeFreeList (freelist) (A0)
9915 -$003C -60 FreeWBOject (WBOject) (A0)
9916 -$0042 -66 AllocWBOject ()
9917 -$0048 -72 AddFreeList (freelist,mem,size) (A0,A1,A2)
9918 -$004E -78 GetDiskObject (name) (A0)
9919 -$0054 -84 PutDiskObject (name,diskobj) (A0,A1)
9920 -$005A -90 FreeDiskObj (diskobj) (A0)
9921 -$0060 -96 FindToolType (toolTypeArray,typeName) (A0.A1)
9922 -$0066 -102 MatchToolValue (typeString,value) (A0,A1)
9923 -$006C -108 BumbRevision (newname,oldname) (A0,A1)
9924
9925 INTUITION.LIBRARY
9926 -$001E -30 OpenIntuition ()
9927 -$0024 -36 Intuition (ievent) (A0)
9928 -$002A -42 AddGadget (AddPtr,Gadget,Position) (A0,A1,D0)
9929 -$0030 -48 ClearDMRequest (Window) (A0)
9930 -$0036 -54 ClearMenuStrip (Window) (A0)
9931 -$003C -60 ClearPointer (Window) (A0)
9932 -$0042 -66 CloseScreen (Screen) (A0)
9933 -$0048 -72 CloseWindow (Window) (A0)
9934 -$004E -78 CloseWorkbench ()
9935 -$0054 -84 CurrentTime (Seconds,Micros) (A0,A1)
9936 -$005A -90 DisplayAlert (AlertNumber,String,Height)
9937 (D0,A0,D1)
9938 -$0060 -96 DiplayBeep (Screen) (A0)
9939 -$0066 -102 DoubleClick (sseconds,smicros,cseconds,
9940 cmicros) (D0,D1,D2,D3)
9941 -$006C -108 DrawBorder (Rport,Border,LeftOffset,TopOffset)
9942 (A0,A1,D0,D1)
9943 -$0072 -114 DrawImage (RPort,Image,LeftOffset,TopOffset)
9944 (A0,A1,D0,D1)
9945 -$0078 -120 EndRequest (requester,window) (A0,A1)
9946 -$007E -126 GetDefPref (preferences,size) (A0,D0)
9947 -$0084 -132 GetPrefs (preferences,size) (A0,D0)
9948 -$008A -138 InitRequester (req) (A0)
9949 -$0090 -144 ItemAddress (MenuStrip,MenuNumber) (A0,D0)
9950 -$0096 -150 ModifyIDCMP (Window,Flags) (A0,D0)
9951 -$009C -156 ModifyProp (Gadget,Ptr,Reg,Flags,HPos,VPos,
9952 HBody,VBody) (A0,A1,A2,D0,D1,D2,D3,D4)
9953 -$00A2 -162 MoveScreen (Screen,dx,dy) (A0,D0,D1)
9954 -$00A8 -168 MoveWindow (Window,dx,dy) (A0,D0,D1)
9955 -$00AE -174 OffGadget (Gadget,Ptr,Req) (A0,A1,A2)
9956 -$00B4 -180 OffMenu (Window,MenuNumber) (A0,D0)
9957 -$00BA -186 OnGadget (Gadget,Ptr,Req) (A0,A1,A2)
9958 -$00C0 -192 OnMenu (Window,MenuNumber) (A0,D0)
9959 -$00C6 -198 OpenScreen (OSArgs) (A0)
9960 -$00CC -204 OpenWindow (OWArgs) (A0)
9961 -$00D2 -210 OpenWorkBench ()
9962 -$00D8 -216 PrintIText (rp,itext,left,top) (A0,A1,D0,D1)
9963 -$00DE -222 RefreshGadgets (Gadgets,Ptr,Req) (A0,A1,A2)
9964 -$00E4 -228 RemoveGadgets (RemPtr,Gadget) (A0,A1)
9965 -$00EA -234 ReportMouse (Window,Boolean) (A0,D0)
9966 -$00F0 -240 Request (Requester,Window) (A0,A1)
9967 -$00F6 -246 ScreenToBack (Screen) (A0)
9968 -$00FC -252 SCreenToFront (Screen) (A0)
9969 -$0102 -258 SetDMRequest (Window,req) (A0,A1)
9970 -$0108 -264 SetMenuStrip (Window,Menu) (A0,A1)
9971 -$010E -270 SetPointer (Window,Pointer,Height,Width,
9972 XOFFset, YOFFset) (A0,A1,D0,D1,D2,D3)
9973 -$0114 -276 SetWindowTitles (Window,windowTitle,
9974 screenTitle) (A0,A1,A2)
9975 -$011A -282 ShowTitle (Screen,ShowIt) (A0,D0)
9976 -$0120 -288 SizeWindow (Windowmdx,dy) (A0,D0,D1)
9977 -$0126 -294 ViewAddress ()
9978 -$012C -300 ViewPortAddress (Window) (A0)
9979 -$0132 -306 WindowToBack (Window) (A0)
9980 -$0138 -312 WindowToFront (Window) (A0)
9981 -$013E -318 WindowLimits (Window,minwidth,minheight,
9982 maxwidth, maxheight) (A0,D0,D1,D2,D3)
9983 -$0144 -324 SetPrefs (preferences,size,flag) (A0,D0,D1)
9984 -$014A -330 IntuiTextLength (itext) (A0)
9985 -$0150 -336 WBenchToBack ()
9986 -$0156 -342 WBenchToFront ()
9987 -$015C -348 AutoRequest (Window,Body,PText,NText,PFlag,
9988 NFlag,W,H) (A0,A1,A2,A3,D0,D1,D2,D3)
9989 -$0162 -354 BeginRefresh (Window) (A0)
9990 -$0168 -360 BuildSysRequest (Window,Body,PosText,NegText,
9991 Flags,W,H) (A0,A1,A2,A3,D0,D1,D2)
9992 -$016E -366 EndRefresh (Window,Complete) (A0,D0)
9993 -$0174 -372 FreeSysRequest (Window) (A0)
9994 -$017A -378 MakeScreen (Screen) (A0)
9995 -$0180 -384 RemakeDisplay ()
9996 -$0186 -390 RethinkDisplay ()
9997 -$018C -396 AllocRemember (RememberKey,Size,Flags) (A0,D0,D1)
9998 -$0192 -402 AlohaWorkBench (wbport) (A0)
9999 -$0198 -408 FreeRemember (RememberKey,ReallyForgot) (A0,D0)
10000 -$019E -414 LockIBase (dontknow) (D0)
10001 -$01A4 -420 UnlockIBase (IBLock) (A0)
10002
10003 LAYERS.LIBRARY
10004 -$001E -30 InitLayers (li) (A0)
10005 -$0024 -36 CreateUpfrontLayer (li,bm,x0,y0,xl,yl,flags,
10006 bm2) A0,A1,D0,D1,D2,D3,D4,A2)
10007 -$002A -42 CreateBehindLayer (li,bm,x0,y0,xl,yl,flags,
10008 bm2) (A0,A1,D0,D1,D2,D3,D3,A2)
10009 -$0030 -48 UpfrontLayer (li,layer) (A0,A1)
10010 -$0036 -54 BehindLayer (li,layer) (A0,A1)
10011 -$003C -60 MoveLayer (li,layer,dx,dy) (A0,A1,D0,D1)
10012 -$0042 -66 SizeLayer (li,layer,dx,dy) (A0,A1,D0,D1)
10013 -$0048 -72 ScrollLayer (li,layer,dx,dy) (A0,A1,D0,D1)
10014 -$004E -78 BeginUpdate (layer) (A0)
10015 -$0054 -84 EndUpdate (layer) (A0)
10016 -$005A -90 DeleteLayer (li,layer) (A0,A1)
10017 -$0060 -96 LockLayer (li,layer) (A0,A1)
10018 -$0066 -102 UnlockLayer (li,layer) (A0,A1)
10019 -$006C -108 LockLayers (li) (A0)
10020 -$0072 -114 UnlockLayers (li) (A0)
10021 -$0078 -120 LockLayerInfo (li) (A0)
10022 -$007E -126 SwapBitRastPortClipRect (rp,cr) (A0,A1)
10023 -$0084 -132 WhichLayer (li,x,y) (A0,D0,D1)
10024 -$008A -138 UnlockLayerInfo (li) (A0)
10025 -$0090 -144 NewLayerInfo ()
10026 -$0096 -150 DisposeLayerInfo (li) (A0)
10027 -$009C -156 FattenLayerInfo (li) (A0)
10028 -$00A2 -162 ThinLayerInfo (li) (A0)
10029 -$00A8 -168 MoveLayerInfrontOf (layer_to_move,
10030 layer_to_be_in_front_of) (A0,A1)
10031
10032 MATHFFP.LIBRARY
10033 -$001E -30 SPFix (float) (D0)
10034 -$0024 -36 SPFit (integer) (D0)
10035 -$002A -42 SPCmp (leftFloat,right,Float) (D1,D0)
10036 -$0030 -48 SPTst (float) (D1)
10037 -$0036 -54 SPAbs (float) (D0)
10038 -$003C -60 SPNeg (float) (D0)
10039 -$0042 -66 SPAdd (leftFloat,rightFloat) (D1,D0)
10040 -$0048 -72 SPSub (leftFloat,rightFloat) (D1,D0)
10041 -$004E -78 SPMul (leftFloat,rightFloat) (D1,D0)
10042 -$0054 -84 SPDiv (leftFloat,rightFloat) (D1,D0)
10043
10044 MATHIEEEDOUBBAS.LIBRARY
10045 -$001E -30 IEEEDPFix (integer,integer) (D0,D1)
10046 -$0024 -36 IEEEDPFit (integer) (D0)
10047 -$002A -42 IEEEDPCamp (integer,integer,integer,integer)
10048 (D0,D1,D2,D3)
10049 -$0030 -48 IEEEDPTst (integer,integer) (D0,D1)
10050 -$0036 -54 IEEEDPAbs (integer,integer) (D0,D1)
10051 -$003C -60 IEEEDPNeg (integer,integer) (D0,D1)
10052 -$0042 -66 IEEEDPAdd (integer,integer,integer,integer)
10053 (D0,D1,D2,D3)
10054 -$0048 -72 IEEEDPSub (integer,integer,integer,integer)
10055 (D0,D1,D2,D3)
10056 -$004E -78 IEEEDPMul (integer,integer,integer,integer)
10057 (D0,D1,D2,D3)
10058 -$0054 -84 IEEEDPDiv (integer,integer,integer,integer)
10059 (D0,D1,D2,D3)
10060
10061 MATHTRANS.LIBRARY
10062 -$001E -30 SPAtan (float) (D0)
10063 -$0024 -36 SPSin (float) (D0)
10064 -$002A -42 SPCos (float) (D0)
10065 -$0030 -48 SPTan (float) (D0)
10066 -$0036 -54 SPSincos (leftFloat,rightFloat) (D1,D0)
10067 -$003C -60 SPSinh (float) (D0)
10068 -$0042 -66 SPCosh (float) (D0)
10069 -$0048 -72 SPTanh (float) (D0)
10070 -$004E -78 SPExp (float) (D0)
10071 -$0054 -84 SPLog (float) (D0)
10072 -$005A -90 SPPow (leftFloat,rightFloat) (D1,D0)
10073 -$0060 -96 SPSqrt (float) (D0)
10074 -$0066 -102 SPTieee (float) (D0)
10075 -$006C -108 SPFieee (float) (D0)
10076 -$0072 -114 SPAsin (float) (D0)
10077 -$0078 -120 SPAcos (float) (D0)
10078 -$007E -126 SPLog10 (float) (D0)
10079
10080 POTGO.LIBRARY
10081 -$0006 -6 AllocPotBits (bits) (D0)
10082 -$000C -12 FreePotBits (bits) (D0)
10083 -$0012 -18 WritePotgo (word,mask) (D0,D1)
10084
10085 TIMER.LIBRARY
10086 -$002A -42 AddTime (dest,src) (A0,A1)
10087 -$0030 -48 SubTime (dest,src) (A0,A1)
10088 -$0036 -54 CmpTime (dest,src) (A0,A1)
10089
10090 TRANSLATOR.LIBRARY
10091 -$001E -30 Translate (inputString,inputLength,
10092 outputBuffer,bufferSize) (A0,D0,A1,D1)
10093
10094
10095 Abbreviations (symbols) used:
10096
10097 label A label or address
10098 reg Register
10099 an Address register n
10100 dn Data register n
10101 source source operand
10102 dest destination operand
10103 <ea> address of register
10104 #n direct value
10105
10106
10107 GENERAL INSTRUCTIONS
10108
10109 BCC label Conditional branch, depends on condition.
10110 BRA label Unconditional branch (Similar to JMP).
10111 BSR label Branch to subprogram. Return address is
10112 deposited on the stack, RTS causes return to
10113 that address.
10114 CHK <ea>,dx Check data register for limits, activate the
10115 CHK instruction exception.
10116 DBCC reg,label Check condition, decrement on branch.
10117 JMP label Jump to address (Similar to BRA).
10118 JSR label Jump to a subroutine. Return address is deposited
10119 on stack, RTS causes return to that address.
10120 NOP No operation.
10121 RESET Reset peripherals (Caution!).
10122 RTE Return from exception.
10123 RTR Return with loading of flags.
10124 RTS Return from subroutine (After BSR or JSR).
10125 SCC <ea> Set a byte to -1 when condition is met.
10126 STOP Stop processing (Caution!).
10127 TRAP #n Jump to an exception.
10128 TRAPV Check overflow flag, then TRAPV exception.
10129
10130
10131 ARITHMETIC OPERATIONS WITH WHOLE NUMBERS
10132
10133 ADD source,dest Binary addition.
10134 ADDA source,an Binary addition to an address register.
10135 ADDI #n,<ea> Addition with a constant.
10136 ADDQ #n,<ea> Fast addition of a constant which can be only
10137 from 1 to 8.
10138 ADDX source,dest Addition with transfer in X flag.
10139 CLR <ea> Clear an operand.
10140 CMP source,dest Comparison of two operands.
10141 CMPA <ea>,an Comparison with an address register.
10142 CMPI #n,<ea> Comparison with a constant.
10143 CMPM source,dest Comparison of two memory operands.
10144 DIVS source,dest Sign-true division of a 32 bit destination by
10145 a 16 bit source operand. The result of the
10146 division is stored in the LO word of the
10147 destination, the remainder in the HI word.
10148 DIVU source,dest Division without regard to sign, similar to DIVS.
10149 EXT dn Sign-true expansion to twice original size
10150 (width) data unit.
10151 MULS source,dest Sign-true multiplication of two words into one
10152 word.
10153 MULU source,dest Multiplication without regard to sign, similar
10154 to MULS.
10155 NEG <ea> Negation of an operand (twos complement).
10156 SUB source,dest Binary subtraction.
10157 SUBA <ea>,an Binary subtraction from an address register.
10158 SUBI #n,<ea> Subtraction of a constant.
10159 SUBQ #n,<ea> Fast subtraction of a three bit constant.
10160 SUBX source,dest Subtraction with transfer in X flag.
10161 TST <ea> Test operand and set N and Z flag.
10162
10163
10164 BINARY CODED DECIMAL NUMBERS
10165
10166 ABCD source,dest Addition of two binary coded decimal numbers.
10167 NBCD source,dest Negation of a binary coded decimal number
10168 (nine complement).
10169 SBCD source,dest Subtraction of two binary coded decimal numbers.
10170
10171
10172 LOGICAL OPERATIONS
10173
10174 AND source,dest Logic AND.
10175 ANDI #n,<ea> Logic AND with a constant.
10176 EOR source,dest Exclusive OR.
10177 EORI #n,<ea> Exclusive OR with a constant.
10178 NOT <ea> Inversion of an operand.
10179 OR source,dest Logic OR.
10180 ORI #n,<ea> Logic OR with a constant.
10181 TAS <ea> Check a byte and set bit 7.
10182
10183
10184 SINGLE BIT MANIPULATION
10185
10186 BCHG #n,<ea> Change bit n(0 is changed to 1 and vice versa).
10187 BCLR #n,<ea> Clear bit n.
10188 BSET #n,<ea> Set bit n.
10189 BTST #n,<ea> Test bit n, result is desplayed in Z flag.
10190
10191
10192 SHIFT AND ROTATE OPERANDS
10193
10194 NOTE: n indicates a register, # indicates a direct value which
10195 specifies the number of shiftings.
10196
10197 AS n,<ea> Arithmetic shift to the left (*2^n)
10198 ASR n,<ea> Arithmetic shift to the right (/2^n)
10199 LSL n,<ea> Logic shift to the left.
10200 LSR n,<ea> Logic shift to the right.
10201 ROL n,<ea> Rotation left.
10202 ROR n,<ea> Rotation right.
10203 ROXL n,<ea> Rotation left with transfer in X flag.
10204 ROXR n,<ea> Rotation right with transfer in X flag.
10205
10206
10207 MOVE DATA INSTRUCTIONS
10208
10209 EXG rn,rn Exchange two register contents (don't confuse
10210 with swap!).
10211 LEA <ea>,an Load an effective address in address register an.
10212 LINK an,#n Build stack range.
10213 MOVE source,dest Carry value over from source to destination.
10214 MOVE SR,<ea> Transfer the status register contents.
10215 MOVE <ea>,SR Transfer the status register contents.
10216 MOVE USP,<ea> Transfer the user stack pointer.
10217 MOVE <ea>,USP Transfer the user stack pointer.
10218 MOVEA <ea>,an Transfer a value to the address register an.
10219 MOVEM regs,<ea> Transfer several registers at once.
10220 MOVEM <ea>,regs Transfer several registers at once.
10221 MOVEP source,dest Transfer data to peripherals.
10222 MOVEQ #n,dn Quickly transfer an eight bit constant to the
10223 data register dn.
10224 PEA <ea> Deposit an address on the stack.
10225 SWAP dn Swap the halves of the register (the upper 16 bit
10226 with the lower).
10227 UNLK an Unlink the stack.
10228
10229
10230
10231
10232EOF