Pl2 LINEA.DOC

From Atari Wiki
Revision as of 20:32, 17 December 2023 by Olivier.jan (talk | contribs)
Jump to navigation Jump to search


--------------------
CHAPTER NR°8:

THE LINEAS

--------------------

*** INTRODUCTION ***
--------------------

- LineAs are graphical functions, they are very simple
  but have the advantage of being really very fast.
  (Much more than the VDI...)

  LineAs are commands of the 'BLITTER', i.e., it is the HARDWARE
  (Some PHYSICAL components of the computer and the routines that
  are executed by the PROCESSOR himself.) that execute these func-
  tions and not the SOFTWARE (The SOFTWARE part of your computer:
  ROM, programs...).
  If your ST is equipped with the BLITTER of course... (The MEGA 2ST and the
  MEGA 4ST are equipped.)
  
  NB: There is a SOFTWARE version of the BLITTER that is available in the public
  --- domain in the form of a desktop accessory...
  
  These functions are very fast since not coming from the SOFTWARE, the
  routines do not need to be interpreted by the PROCESSOR.

- To call the LineAs functions, you will have to provide the appro-
  priate parameters in the VDI TABLE and also in an INTERNAL TABLE
  specific to LineAs.
  Some registers will also be used.

  Indeed, the LineAs use the VDI's CONTROL, PTSIN, PTSOUT,
  INTIN, and INTOUT arrays.
  Registers d0, d1, d2, a0, a1, a2 will also be used, so you will have
  to be careful not to lose their content...
  Some parameters are also provided by the LineAs in return in
  d0, a0 or INTOUT (here again, be careful not to lose d0!)

  We have seen that the LineAs use an INTERNAL TABLE:

  It is in this table that the functions search for the parameters
  that we have deposited, the only problem is that the location of this
  internal table varies (hence its name).

  To find the location of this internal table, just
  call the function $A000 with:

  DC.W  $A000

  What a strange syntax isn't it??

  The explanation is very simple: During the ASSEMBLY step of your
  listing, the ASCII codes representing the instructions and their operands
  will be translated into BINARY because the 68000 only recognizes
  information coded in binary:
  Thus, a NOP will be translated by %100111001110001, a RTS by %0100111
  001110101 etc... and so for all instructions.
  If we translate these codes from binary to HEXADECIMAL, we obtain
  instructions coded in HEX:
  Thus, NOP will be written: $4E71
  and    RTS will be written: $4E75
  etc...

  However,
  --
  You can REPLACE, in an ASSEMBLER program, an instruction
  by its HEX CODE equivalent if it is declared as such in
  the TEXT segment, it would suffice to write:

  DC.W  $4E71 instead of a NOP  (or DC.B  $4E, $71)
  or
  DC.W  $4E75 instead of an RTS ... (or DC.B  $4E, $75)

  This remains valid for all the instructions of the 68000 (Even for
  labels).

  But,
  ----
  No 68000 instruction will be coded in HEX by a WORD of type:

  $A...  (or $F...)

  We have therefore filled this lack (we rather took advantage of it!) by coding
  the LineAs functions in $A...

  NB: There are also $F... routines but we will not use them
  -- because they are not compatible between the OLD ROM and NEW ROM versions
     of the ST.

  It will therefore suffice to write  DC.W  $A...  for the 68000 to decode this
  instruction by the LineA instruction of code $A...

  There are a total of 16 commands that are installed and that can
  be translated this way, these are the 16 LineAs routines:

  To call them simply DECLARE them in the TEXT segment:

 The LineAs:
-----------
$A000: Installs the internal table
$A001: Places 1 point on the screen
$A002: Sets the color of a screen point
$A003: Draws an arbitrary line
$A004: Draws a horizontal line
$A005: Draws a filled rectangle
$A006: Draws a filled polygon
$A007: ?
$A008: Allows text block transfer
$A009: Activates the mouse cursor
$A00A: Deactivates the mouse cursor
$A00B: Modifies the shape of the mouse cursor
$A00C: Erases a sprite
$A00D: Draws a sprite
$A00E: Copies a block of points
$A00F: Identical to VDI's CONTOUR FILL function (opcode=103)

But let's now focus on our $A000 function:

We have seen earlier that it initializes the INTERNAL TABLE in which we will place parameters. This TABLE contains 50 variables, some the size of a word and some the size of a long word. To obtain the address where the table begins, we use the function $A000:

DC.W  $A000

The function provides us with the address where the table is located in A0:

We can now access all the variables in this table using an INDIRECT addressing mode. However, since the variables do not all have the same size (word or long word), the (a0)+ and (a0) addressing modes will not be used...

We will use the d(a0) addressing mode to access the different parameters of the table:

So, MOVE.W 0(a0) will place the word=0 in the 1st parameter of the table,
MOVE.W 2(a0) will place the word=0 in the parameter at a0+2,
and so on...

Therefore, we need to know the values of the relative locations of the variables in the table. Since the d(a0) syntax is not very informative, we will define (with EQU) the relative locations of all these variables:

Here they are:
   
; Definition of EQUIVALENCES for the INTERNAL TABLE of LineAs

; Variable NAME = Relative Displacement

v_planes        EQU       0                ;number of planes
v_lin_wr        EQU       2                ;bytes per write line
ticontrol       EQU       4                ;address of T.I CONTROL
tiintin         EQU       8                ;address of T.I INTIN
tiptsin         EQU       12               ;address of T.I PTSIN
tiintout        EQU       16               ;address of T.I INTOUT
tiptsout        EQU       20               ;address of T.T PTSOUT
_fg_bp_1        EQU       24               ;bit 0 of color
_fg_bp_2        EQU       26               ;bit 1 of color
_fg_bp_3        EQU       28               ;bit 2 of color
_fg_bp_4        EQU       30               ;bit 3 of color
_lstlin         EQU       32               ;always =-1
_ln_mask        EQU       34               ;line shape for $A003
_wrt_mode       EQU       36               ;WRITE MODE
_x1             EQU       38               ;X coordinate of the first point
_y1             EQU       40               ;Y coordinate of the first point
_x2             EQU       42               ;X coordinate of the second point
_y2             EQU       44               ;Y coordinate of the second point
_patptr         EQU       46               ;fill address
_patmsk         EQU       50               ;fill number
_multifill      EQU       52               ;details later
_clip           EQU       54               ;clipping flag
_xmn_clip       EQU       56               ;leftmost X for clipping
_ymn_clip       EQU       58               ;highest Y for clipping
_xmx_clip       EQU       60               ;rightmost X for clipping
_ymx_clip       EQU       62               ;lowest Y for clipping
_xacc_dda       EQU       64               ;points to $8000 for TXTBLT  
_dda_inc        EQU       66               ;enlargement factor=$FFFF
_t_sclsts       EQU       68               ;=0                   
_mono_status    EQU       70               ;TEXT EFFECTS type
_sourcex        EQU       72               ;character number in SET  
_sourcey        EQU       74               ;=0  
_destx          EQU       76               ;X coordinate of TEXT
_desty          EQU       78               ;Y coordinate of TEXT  
_delx           EQU       80               ;character width  
_dely           EQU       82               ;character height
_fbase          EQU       84               ;SET address  
_fwidth         EQU       88               ;SET X
_style          EQU       90               ;FLAG for TEXT EFFECTS  
_litemark       EQU       92               ;shading mask  
_skewmask       EQU       94               ;TEXT inclination mask
_weight         EQU       96               ;number of enlargement bits  
_r_off          EQU       98               ;offset for TEXT italic 
_l_off          EQU       100              ;left (Left) offset 
_scale          EQU       102              ;enlargement flag (1/0)       
_chup           EQU       104              ;TEXT rotation angle  
_txt_fg         EQU       106              ;Color of TEXT foreground  
_scrtchp        EQU       108              ;Address of a buffer for effects  
_scrpt2         EQU       112              ;Offset for enlargement  
_text_bg        EQU       114              ;Background color of TEXT  
_copytran       EQU       116              ;FLAG for writing mode  

Here, the structure and composition of the INTERNAL TABLE are very clear:

The names used here are often default names in many works.
We will only use a small part of the variables in the internal table...

The definitions of equivalences for the INTERNAL TABLE are found
in the file: LINEQU.L, and you should include it in your listing
at the beginning of the TEXT segment.

The use of variables will depend on the functions, and the details
will come with the explanations...

In practice:

To change the variable '_patptr' in the Internal Table, you just need
to write:

MOVE  source, _patptr(a0)

To change the variable '_clip' in the Internal Table, you just need
to write:

MOVE  source, _clip(a0) 

and so on...

This is much more readable than writing:
MOVE  source, 46(a0) or MOVE  source, 54(a0)...

Now that our internal table is set up with DC.W $A000,
we still need to provide the addresses of the CONTROL, INTIN, PTSIN,
INTOUT, and PTSOUT TABLES because they are also used!

This is done simply by placing these addresses in the tiintin, tiptsin,
tiintout, tiptsout variables of the INTERNAL TABLE:

So, you can write:

MOVE.L    #CONTROL, ticontrol(a0)
MOVE.L    #INTIN, tiintin(a0)
MOVE.L    #PTSIN, tiptsin(a0)
MOVE.L    #INTOUT, tiintout(a0)
MOVE.L    #PTSOUT, tiptsout(a0)

To transfer the addresses into the INTERNAL TABLE.

With this initialization done, you can finally use the LineAs routines.

All the programs you write should look like this if you are using LINEAs:

TEXT

INCLUDE   "INIT_TOS.L"
INCLUDE   "LINEQU.L"     ;Equivalences for the LineAs

SETBLOCK                 ;Initialize GEM

DC.W      $A000          ;Initialize the T.I. (address in a0)


; Placing the addresses of VDI TABLES in the Internal Table (T.I.)

MOVE.L    #CONTROL, ticontrol(a0)
MOVE.L    #INTIN, tiintin(a0)
MOVE.L    #PTSIN, tiptsin(a0)
MOVE.L    #INTOUT, tiintout(a0)
MOVE.L    #PTSOUT, tptstout(a0)

.                        ; Your program here
.
.

DATA

.                        ; Data here
.
.

BSS
.
.

INCLUDE   "TABLEAU.L"    ; VDI Table

END

*** Explanation of Terms Used Below ***
------------------------------------------

- Graphical Coordinates:

  These coordinates are used to define the positions of graphic elements
  based on their coordinates on the X and Y axes.

  The origin of the orthogonal coordinate system (O, x, y) is located at
  the top-left point of your screen with coordinates (0, 0).

  - The X-axis extends from the origin O to the point on the far right
    at the top of the screen.
  - The Y-axis descends from the origin O to the point on the far right
    at the bottom of your screen.

  The number of points available along the X and Y axes depends on the
  resolution:
  
  In LOW resolution  : (OX) = 320 pixels (points) from 0 to 319
                     : (OY) = 200 pixels (points) from 0 to 199
  
  In MEDIUM resolution: (OX) = 640 pixels (points) from 0 to 639
                     : (OY) = 200 pixels (points) from 0 to 199
  
  In HIGH resolution  : (OX) = 640 pixels (points) from 0 to 639
                     : (OY) = 400 pixels (points) from 0 to 399

  Be sure to always respect the graphical constraints to avoid issues.

- Writing Mode: defined by the _wrt_mode variable in the internal table.

  There are 4 writing modes available:

  - If _wrt_mode=0: AND Mode,
  
  Example: BACKGROUND = %111011101110110100
  ------ : DRAWING = %100011011010100011
  ---> RESULT = %100011011010100011 (Background is masked)
  
  We get: BACKGROUND AND DRAWING
  
  - If _wrt_mode=1: OR Mode,
  
  Example: BACKGROUND = %101100011101010011
  ------ : DRAWING = %011011101110001010
  ---> RESULT = %111111111111011011
  
  We get BACKGROUND OR DRAWING
  
  - If _wrt_mode=2: (COLOR AND DRAWING) OR (BACKGROUND NOT DRAWING) Mode,
  
  (This is the TRANSPARENT graphics mode):
  
  Points are placed where there are none yet, and if the point to be placed
  has no color, the point is erased.

  - If _wrt_mode=3: XOR Mode,
  
  Example: BACKGROUND = %1101100111000101
  ------ : DRAWING = %0110011101011010
  ---> RESULT = %0110011101111010
  
  Pixels in the BACKGROUND are inverted, then an OR operation is performed
  with DRAWING.

  We get BACKGROUND XOR DRAWING

  NB: The default graphics mode used is mode 0.

- The 4 _fg_bp_B variables are a total of 4 and are used to indicate the color
  according to the following mode:

  _fg_bp_1 = 1st bit of the color
  _fg_bp_2 = 2nd bit of the color
  _fg_bp_3 = 3rd bit of the color
  _fg_bp_4 = 4th bit of the color

  Each variable can only take a value of 1 or 0.

  So, for example:

  _fg_bp_1 = 0
  _fg_bp_2 = 1
  _fg_bp_3 = 1
  _fg_bp_4 = 0

  The color used will be color number %0110 = 6.

  Please note that the number of available colors varies in different
  graphical resolutions.

- In LOW RESOLUTION:
  ------------------- 
  You can use all the _fg_bp_B variables.

- In MEDIUM RESOLUTION:
  ----------------------
  You can only use the _fg_bp_1 and _fg_bp_2 variables. 
  _fg_bp_3 and _fg_bp_4 should be set to 0 because you have only 4 colors available.

- In HIGH RESOLUTION:
  --------------------
  You can only use the _fg_bp_1 variable because only 2 colors are available at a time in this resolution.

- CLIPPING allows you to define the boundaries within which your graphics can be drawn on the screen.

  To do this, you need to modify the _xmn_clip, _ymn_clip, _xmx_clip, and _ymx_clip variables in the internal table:

  - _xmn_clip and _ymn_clip define the X and Y coordinates of the top-left corner of the CLIPPING FRAME.
  - _xmx_clip and _ymx_clip define the X and Y coordinates of the bottom-right corner of the CLIPPING FRAME.

  A FLAG (or semaphore) is also used, which is a variable that is tested to determine if CLIPPING is active or not.

  - If you DO NOT USE CLIPPING, the _clip variable must be set to 0.
  - Otherwise, you set the _clip(a0) word in the internal table to any non-zero value.

  Example:
  --------
  _clip=1   (different from 0, so clipping is active)
   
  _xmn_clip=0, _ymn_clip=0
  _xmx_clip=50, _ymx_clip=50

  If you draw a rectangle with starting coordinates of 10,10 and ending coordinates of 75,75:
  Only the part of the rectangle with starting coordinates of 10,10 and ending coordinates of 50,50 will be drawn because the rest of the rectangle is outside the CLIPPING FRAME.

  CLIPPING allows you to modify the 'action radius' of the graphic functions.

  Note: Exceeding the CLIPPING FRAME does not result in an error, but graphics drawn outside the frame will not be displayed.

- The _multifill variable in the internal table allows you to create multicolored fill patterns (for fill options).

  We will always set this variable to 0 (monochrome fill). This variable in the internal table is used with functions that fill surfaces.

- PAT (PATTERN) is used for functions $A004, $A005, $A006 and allows you to define the type of line and fill pattern used.

  The pattern normally used by these functions is '%1111111111111111' (SOLID PATTERN). Modifying PAT allows you to change the type of lines and fill patterns used by functions $A004, $A005, and $A006.

  For example, if PAT is set to %1010101010101010 (DOTTED) and if you use function $A004, it will draw a dotted line. If PAT is set to %1111000011110000 (DOTTED), you will get wider and more spaced dots.

  PAT is defined by 2 variables in the internal table:
  - _patptr (L-M) is the address where a sample filling pattern defined by an EVEN number of WORDs is located (see below).
  - _patmsk (WORD) contains the number of data (WORDS) to be read - 1. This is always an ODD number (even-1).

  So, if _patptr points to 'TABLE', and at this address, you find the words:

  TABLE    DC.W      %1111000011110000    ; address 'TABLE': the PATTERN
           DC.W      %0000111100001111
           DC.W      %1010101010101010
           DC.W      %0101010101010101    ; EVEN number of WORDs

  _patmsk will be equal to 4-1 = 3.

  The filling pattern that will be used will be a pattern with a width of 16 pixels (the 16 Bits of the different WORDs, 1 = active bit, 0 = off bit) and a height of 4 lines (4 WORDs).

  Note: The binary representation of the data is more descriptive here.

  Examples of use:
  --------
  Suppose you want to define lines with wide dots. Modify the PAT as follows:

      DC.W     $A000               ; a0 points to the T.I.
      
      move.l   #TABLE,_patptr(a0)  ; set the address of the PATTERN in _patptr
      move     #0,_patmsk(a0)      ; 1-1=0 in _patmsk

  DATA

  TABLE DC.W     %1111000011110000   ; the PATTERN

- To achieve a filling with small squares using the $A005 function (filled rectangle), modify the PAT as follows:

      DC.W     $A000               ; a0 points to the T.I.

      move.l   #TABLE,_patptr(a0)  ; set the address of the PATTERN in _patptr
      move     #5,_patmsk(a0)      ; 8-1=7 in _patmsk
      
      DATA

TABLE DC.W     %1111111111111111 ; the PATTERN (8 WORDs)
      DC.W     %1100000000000011 
      DC.W     %1101111111111011 ; 0 = off pixel
      DC.W     %1101111111111011
      DC.W     %1101111111111011 ; 1 = active pixel
      DC.W     %1101111111111011
      DC.W     %1100000000000011
      DC.W     %1111111111111111

*** LINEAS ROUTINES ***
------------------------

I will now describe the interesting LINEAS routines, and I will provide examples in the next file. Exercises will follow.

- $A000
  -----
  Provides the address of the internal table in a0 and d0.
  Also gives the address of another table pointing to the 3 sets of characters used by the $A008 routine in a1.

  Call it as follows:

  DC.W   $A000     ; In the TEXT segment
                   ; (you can also write DC.B $A0,$00)
                   ; Values returned in a0, a1, d0 (be careful not to lose these values; save them if necessary!)

  Note: Before using the other functions, make sure to initialize the ticontrol, tiintin, tiptsin, tiintout, and tiptsout variables in the internal table...

- $A001 (PUT PIXEL)
  -----
  Allows you to place a point at coordinates (X, Y) on the screen.

  Parameters to pass:
 
  . X in ptsin   
  . Y in ptsin+2
  . Color of the point (0 to 15) in intin (WORD)

  Call it as follows:

  DC.W   $A001     ; In the TEXT segment

- $A002 (GET PIXEL)
  -----
  This function allows you to obtain the color of a point at coordinates (X, Y) on the screen.

  Parameters to pass:

  . X in ptsin
  . Y in ptsin+2
  
  The color (WORD from 0 to 15) is returned in intout.

  Call the function as follows:

  DC.W  $A002  ; In the TEXT segment

- $A003 (LINE)
  -----
  Allows you to draw any line with starting coordinates (A, B) and ending coordinates (C, D) on the screen.
  You can also modify the line's color using _fg_bp_B, line type using _ln_mask, and writing mode using _wrt_mode.

  Parameters to pass:

  . A in _x1
  . B in _y1
  . C in _x2
  . D in _y2

  You can choose the line's color, which is passed in the variables:  

  . _fg_bp_B (Bits B used depending on the resolution)

  You can also modify the line type used with the variable:

  . _ln_mask (WORD)

  For example, if _ln_mask is %1111111111111111, the line will be solid. If _ln_mask is %0000111100001111, you will get large dashes, and so on.
  
  You can also choose the writing mode using the variable:

  . _wrt_mode (WORD = 0 to 3)

  Then, call the function as follows:

  DC.W    $A003   ; In the TEXT segment

- $A004 (H-LINE)
  -----
  Allows you to draw a horizontal line (only HORIZONTAL...).
  The starting coordinates are (A, B), and the ending coordinates are (C, D) such that B = D (horizontal line).
  Just like with $A003, you can modify the line's color, writing mode, and PAT (using _patptr and _patmsk).

  H-LINE is a basic function and is used by the functions $A003, $A005, $A006:
  A curved line (routine $A003) is essentially a sequence of horizontal line segments:
  This explains why H-LINE is faster than LINE.

  Parameters to pass:

  . A in _x1
  . B in _y1
  . C in _x2
  . D in _y2      ; _y1 = _y2 (horizontal line)

  You can choose the line's color, which is passed in the variables:  

  . _fg_bp_B (Bits B used depending on the resolution)

  You can also modify the line type used with the variables:

  . _patptr (L-M): the address of the PATTERN
  . _patmsk (WORD): the number of data - 1

  You can also choose the writing mode using the variable:

  . _wrt_mode (WORD = 0 to 3)

  Call the function as follows:

  DC.W    $A004   ; In the TEXT segment


- $A005 (FILLED RECTANGLE)
  -----
  Allows you to fill a rectangle with coordinates (A, B) for the top-left corner and (C, D) for the bottom-right corner.
  You can modify the rectangle's color, fill type, and writing mode.
  The function also uses CLIPPING if desired.
 
  In fact, the $A005 function uses the $A004 function to draw the rectangle...

  Parameters to pass:

  . A in _x1
  . B in _y1
  . C in _x2
  . D in _y2     

  You can choose the rectangle's color, which is passed in the variables:  

  . _fg_bp_B (Bits B used depending on the resolution)

  You can also modify the PAT type used with the variables:
  
  . _patptr (L-M): the address of the PATTERN
  . _patmsk (WORD): the number of data - 1

  You can choose the writing mode using the variable:

  . _wrt_mode (WORD = 0 to 3)

  You can also set the CLIPPING FRAME with coordinates:

  . _xmn_clip   ; Top-left X
  . _ymn_clip   ; Top-left Y
  . _xmx_clip   ; Bottom-right X
  . _ymn_clip   ; Bottom-right Y

  and
  
  . _clip       ; 0 if unused
  
  Call the function as follows:

  DC.W    $A005   ; In the TEXT segment

- $A006 (FILLED POLYGON)
  -----
  Allows you to draw a POLYGON (a geometric figure with N sides).
  $A006 uses the basic function $A004 (H-LINE).
  You can modify the polygon's color, fill type, and writing mode.
  The function also uses CLIPPING if desired.

  Parameters to provide:

  . sptsin contains the number of vertices in your polygon.

  In the ptsin array, you place the coordinates of the N vertices of the
  polygon (as WORDs). You must end your array with the coordinates of the
  1st vertex to close the figure.

  . In ptsin, the X coordinate of the 1st vertex
  .
  .
  .

  . In ptsin+Z, the X coordinate of the Nth vertex
  . In ptsin+(Z+2), the Y coordinate of the Nth vertex
  . In ptsin+(Z+4), the X coordinate of the 1st vertex
  . In ptsin+(Z+6), the Y coordinate of the 1st vertex

  You can choose the polygon's color, which is passed in the variables:

  . _fg_bp_B (Bits B used depending on the resolution)

  You can also modify the PAT type used with the variables:

  . _patptr (L-M): the address of the PATTERN
  . _patmsk (WORD): the number of data - 1

  You can choose the writing mode using the variable:

  . _wrt_mode (WORD = 0 to 3)

  You can also set the CLIPPING FRAME with coordinates:

  . _xmn_clip   ; Top-left X
  . _ymn_clip   ; Top-left Y
  . _xmx_clip   ; Bottom-right X
  . _ymn_clip   ; Bottom-right Y

  and

  . _clip       ; 0 if unused

  The function is called in a very specific way:
  ------------------------------------------------------
  After providing all the necessary parameters, you must use the $A006 routine FOR EACH LINE of your polygon.

  In other words, you will need to use $A006 multiple times so that for each HORIZONTAL line that makes up your polygon, the lines within the space defined by the polygon will be displayed.
  $A006 indeed uses the H-LINE routine but only draws the lines (for which you provide the ordinate as a parameter) that are within the previously defined polygon.

  The ordinate of the polygon line to be drawn must be passed in _Y1.
  
  By using $A006 in a loop that varies _y1 (from 0 to 199 for LOW and MEDIUM resolution, from 0 to 399 for HIGH resolution), you will perform a screen scan, and the different lines that make up the polygon will be displayed with each function call.

  Call the function as follows:

  DC.W   $A006   ; In the TEXT segment:

  In a loop where you vary _y1 (from 0 to 199 for LOW and MEDIUM resolution, from 0 to 399 for HIGH resolution).
 
  Of course, it is not necessary to scan the entire screen with $A006 to display the defined polygon; only the lines that actually contain the polygon need to be drawn...

  Example of use:
  ---------------------
  You want to draw a SQUARE with starting coordinates (0,0) and a width of 20 pixels (also a height of 20 pixels since it's a square...)
  
  Set:

  . 4 in sptsin: The 4 vertices of the square

  The coordinates of the vertices in PTSIN:

  . 0 in ptsin         (0,0): 1st vertex 
  . 0 in ptsin+2
  
  . 19 in ptsin+4      (19,0): 2nd vertex
  . 0  in ptsin+6
         
  . 19 in ptsin+8      (19,19): 3rd vertex
  . 19 in ptsin+10

  . 0  in ptsin+12     (0,19): 4th vertex
  . 19 in ptsin+14
 
  . 0 in ptsin+16      (0,0): to close the figure
  . 0 in ptsin+18

  Call the $A006 routine for each horizontal line of the polygon to display the portion of the line that fits within the square:
  Our square has a height of 20 lines (from 0 to 19).

  Vary _y1 for these 20 lines in a loop and call $A006 for each of them.

        move      #0,d0       ; 0 in d0

LOOP    move      d0,_y1(a0)  ; Ordinates of the 20 lines of the square from d0
                              ; to _y1
        DC.W      $A006       ; We draw the portion of H-LINE that fits
                              ; within the defined square
        add       #1,d0       ; We add 1 to d0
        cmpi      #20,d0      ; Is d0 = 19+1=20?
        bne       LOOP        ; No? Then we start over with d0=d0+1  

- $A009 (SHOW MOUSE)
  -----
  Allows you to redisplay the mouse cursor after using the $A00A (HIDE MOUSE) function.
  In reality, calling this function increments an internal counter, and if it equals 0, the mouse cursor reappears.
  Since the $A00A (HIDE MOUSE) function decrements the counter with each call, you will need to use the $A009 function N times if you used the HIDE MOUSE function N times previously...

  Parameters to pass:

  0 in sptsin
  1 in sintin
   
  Call the function as follows:

  DC.W   $A009   ; In the TEXT segment

  Note: There is a very simple way to avoid confusion with the HIDE and SHOW MOUSE counters. If you place 0 in INTIN before using $A009, the counter will be set to 0, and the mouse cursor will always reappear.

- $A00A (HIDE MOUSE)
  -----
  This is the complementary function to the $A009 function, and it allows you to hide the mouse cursor from the screen.

  $A00A decrements the counter mentioned earlier by 1 with each call...


  But BE CAREFUL when using this function:

  Indeed, HIDE MOUSE instructs the computer that in the next screen refresh, the mouse cursor should disappear, and THEN what is under the current cursor position should be displayed again. (See the chapter on VBL further on.) However, during the execution time of the function, the user can move the mouse, causing a rectangular HOLE to appear instead of the part of the screen that was supposed to be restored.

  Therefore, you should use HIDE MOUSE before clearing your screen but never when the mouse may be under graphics.

  $A00A does not accept parameters. To call it, you write:

  DC.W   $A00A  ; In the TEXT segment

- $A00C  (UNDRAW SPRITE)
  -----
  Allows you to erase a SPRITE defined by the complementary routine $A00D.
  
  The SPRITES we can draw are euphemistically called ATARI SPRITES: They are drawings with a height and width of 16 pixels, and they are monochrome (only BACKGROUND color and DRAWING color). For example, the mouse cursor...
  The SPRITE can then be displayed on the screen at the coordinates you specify without having to redefine it.

  But you first need to define the SPRITE itself, which is done with:

  . A foreground: The SPRITE drawing (the arrow of the mouse...)
  
  . A Mask: Also known as a background that surrounds the drawing with a color so that it always remains visible, even on a drawing of the same color as the foreground.

  . 2 different colors: One for the foreground and one for the mask.

  . A hot spot: From this point, you define the coordinates of the SPRITE.
                  For example, the hot spot of the mouse arrow is at the tip of the arrow: It is the cursor's point of action, and it cannot go off the screen.

  . A format: VDI (graphic mode AND) or XOR (XOR mode)

  All this data must be defined with $A00D (DRAW SPRITE). To erase an already defined SPRITE, pass the following parameter to $A00C:

  Parameter for UNDRAW SPRITE:

  . Address of the SPRITE backup buffer in a2

  Call the function as follows:

  DC.W   $A00C    ; In the TEXT segment

- $A00D  (DRAW SPRITE)
  -----
  Allows you to define and display a SPRITE.

  The parameters to pass to $A00D are:

  . X coordinate of the SPRITE in d0

  . Y coordinate of the SPRITE in d1

  . Address of the SPRITE definition block in a0

  This block has a size of 74 bytes and should be organized as follows:

  Address:          Value (WORDS)

  a0                Relative X coordinate for the hot spot
  a0+2              Relative Y coordinate for the hot spot      
  a0+4              Format (0 for VDI, 1 for XOR)
  a0+6              Mask color
  a0+8              Foreground color
  a0+10             16 bits defining the 1st line of the mask
  a0+12             16 bits defining the 1st line of the foreground
  a0+14             Same for the 2nd line of the mask     
  a0+16             Same for the 2nd line of the foreground
  .
  .
  .
  a0+70             Same for the 16th line of the mask
  a0+72             Same for the 16th line of the foreground                 

  So, if you want to draw a SPRITE that represents a 1, the data defining the SPRITE might look like this:

  DC.W     %0000000000000000    ;0 = no point
  DC.W     %0000000000000000    ;1 = active pixel
  DC.W     %0000000010000000
  DC.W     %0000000110000000
  DC.W     %0000011110000000
  DC.W     %0000111110000000
  DC.W     %0000000110000000
  DC.W     %0000000110000000
  DC.W     %0000000110000000
  DC.W     %0000000110000000
  DC.W     %0000000110000000
  DC.W     %0000000110000000
  DC.W     %0001111111110000
  DC.W     %0000000000000000
  DC.W     %0000000000000000
  DC.W     %0000000000000000

  The SPRITE has a size of 16 pixels (16 columns) and 16 lines. Binary notation is used here as it is the most readable.

  The mask data would be:

  DC.W     %*000000000000000    ;0 = no point
  DC.W     %0000000010000000    ;1 = active pixel
  DC.W     %0000000111000000    ;* = hot spot (ATTENTION:=0)
  DC.W     %0000001111000000
  DC.W     %0000111111000000
  DC.W     %0001111111000000
  DC.W     %0000001111000000
  DC.W     %0000001111000000
  DC.W     %0000001111000000
  DC.W     %0000001111000000
  DC.W     %0000001111000000
  DC.W     %0011111111111000
  DC.W     %0011111111111000
  DC.W     %0011111111111000
  DC.W     %0000000000000000
  DC.W     %0000000000000000

  The hot spot is also selected. In my example, the hot spot noted * has coordinates (0,0).

  Our definition block for $A00D can be represented as follows based on this example:

  If a0 points to the definition block and the SPRITE is in VDI format, with the foreground color at 0 and the mask color at 1:

  In                We should have:
  --                --------------
  a0                0: Relative X coordinate for the hot spot
  a0+2              0: Relative Y coordinate for the hot spot      
  a0+4              0: Format (0 for VDI, 1 for XOR)
  a0+6              1: Mask color
  a0+8              0: Foreground color
  a0+10             %0000000000000000: Mask WORD for line 1
  a0+12             %0000000000000000: Foreground WORD for line 1
  a0+14             %0000000010000000: Mask WORD for line 2
  a0+16             %0000000000000000: Foreground WORD for line 2
  a0+18             %0000000111000000 and so on...
  a0+20             %0000000010000000
  a0+22             %0000001111000000
  a0+24             %0000000110000000
  a0+26             %0000111111000000
  a0+28             %0000011110000000
  a0+30             %0001111111000000
  a0+32             %0000111110000000
  a0+34             %0000001111000000
  a0+36             %0000000110000000
  a0+38             %0000001111000000
  a0+40             %0000000110000000
  a0+42             %0000001111000000
  a0+44             %0000000110000000
  a0+46             %0000001111000000
  a0+48             %0000000110000000
  a0+50             %0000001111000000
  a0+52             %0000000110000000
  a0+54             %0011111111111000   
  a0+56             %0000000110000000
  a0+58             %0011111111111000
  a0+60             %0001111111110000
  a0+62             %0011111111111000
  a0+64             %0000000000000000
  a0+66             %0000000000000000
  a0+68             %0000000000000000
  a0+70             %0000000000000000: Mask WORD for the 16th line
  a0+72             %0000000000000000: Foreground WORD for the 16th line

  But let's get back to our $A00D (DRAW SPRITE) function:

  There is still one parameter to provide:

  . The address of a backup buffer for the SPRITE in a2
  
  This buffer must have a size of:
  
  . 266 bytes for low resolution
  . 138 bytes for medium resolution
  . 74 bytes for high resolution

  (The size increases with the number of available colors)

  Afterwards, you can simply call the function with:

  DC.W    $A00D  ; In the TEXT segment

- $A00B (TRANSFORM MOUSE)
  -----
  Allows you to change the shape of the mouse cursor.

  I kept this routine for last because you will understand it more easily after seeing DRAW SPRITE.

  The parameters that define the new mouse cursor should be transferred to INTIN.
  You will need to place 34 WORDS there:

  In              You should find:

  INTIN+6         : Mask color (WORD)
  INTIN+8         : Foreground color (WORD)

from INTIN+10       : Data defining 
to   INTIN+40       : the MASK (16 WORDS)

from INTIN+42       : Data defining
to   INTIN+64       : the FOREGROUND (16 WORDS)

  Handling $A00B is much easier than $A00D (DRAW SPRITE) because here, the data defining the MASK and the FOREGROUND do not need to be interleaved...

  You define the MASK and FOREGROUND data in the same way as for the DRAW SPRITE function.

  Given the organization of variables in the INTIN array: 
  You can deposit the mask data AND THEN the foreground data with suitable addressing mode ((an)+ ...) in the INTIN array... (phew!!)

  Call the function as follows:

  DC.W   $A00B   ; In the TEXT segment

  -----------------

  That's it for the theory. Please reread everything carefully, and note it down on a card if necessary...

  In the next chapter, you will use LineAs in various exercises where all the important routines will be used and highlighted.

  PIECHOCKI   Laurent
  8, impasse Bellevue             CONTINUED in the file: EXOS_3.DOC
  57980   TENTELING                                     ----------

Back to ASM_Tutorial