Pl GEMDOS.DOC

From Atari Wiki
Jump to navigation Jump to search
                            ---------------------
                              CHAPTER 5:  

                             *** THE GEMDOS ***

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


 
                      *** GEMDOS FUNCTIONS ***
                      -------------------------------

- The GEMDOS functions can be directly called in assembly.
  Just:

   .Pass the parameters needed by the function in the system stack
    (WORDS or L-W).

   .Pass the function code in the system stack. (WORD)

   .Call the GEMDOS with a TRAP #1 


- The same is true for BIOS and XBIOS functions.
  (Only the TRAP number changes: TRAP #13 for BIOS and TRAP #14 for
  XBIOS)

- ATTENTION! The GEMDOS, BIOS and XBIOS functions often return
  information: in certain data registers and some
  address registers.
  Care must be taken to preserve the concerned registers before 
  calling one of these functions so as not to lose their content.
  (e.g. using MOVEM)

- Before using the GEMDOS, BIOS and XBIOS functions, it is necessary
  to reserve a certain amount of memory because when the operating
  system launches your program, we must allocate the quantity of memory
  that the program really needs.
  (To avoid overlapping of data in memory)
  The operating system (the GEM Desktop) will read the BASE PAGE which
  is at the start of your .PRG program (see the INTRODUCTION chapter)
  before executing it.
  This BASE PAGE is of size $100 (256) bytes and contains all
  the information needed by the operating system for the loading
  of the PRG, but it is up to us to indicate the size of memory
  that will need to be reserved.
  After loading the program, SP points to the BASE PAGE, so 
  the various data contained in the
  BASE PAGE can easily be read by incrementing SP for example.

  Organization of the BASE PAGE:
                     ------------
  Byte:$00=Start of the Base Page
  ----- $04=Pointer to the end of free memory
        $08=Pointer to the start of the prg
        $0C=Size of the TEXT area
        $10=Pointer to the DATA area
        $14=Size of the DATA area
        $18=Pointer to the BSS area
        $1C=Size of the BSS area
        $20=Pointer to the DTA buffer
        $24=Pointer to the base page of the calling PRG (parent)
        $80=The command line

  To indicate the size of memory to reserve, there is a GEMDOS function, the parameters to pass are:

  .the number of BYTES to reserve (L-W)
  .A L-W which is the pointer to the end of free memory
  .a WORD equal to 0
  
  The function code is $4A (function 'SETBLOCK')

  To find the number of bytes to reserve (the total size of the PRG)
  thanks to the Base Page, we add:

  .The size of the Base Page ($100 bytes)
  .The space occupied by the instructions (L-W at $C(SP) because SP points to
   the start of the base page)
  .The size of the DATA area (L-W at $14(SP) )
  .The size of the BSS area  (L-W at $1C(SP) )
  
  We put the result in a dn register and place it as a parameter
  (L-W) in the system stack (MOVE.L  dn,-(SP) ) followed by a L-W which is
  the pointer to the end of free memory and a WORD equal to 0: 
  (MOVE  #0,-(SP) ) 
  Then we stack the code of the function SETBLOCK: MOVE  #$4A,-(SP)
  and call the GEMDOS with TRAP #1.

  This initialization must be done at the beginning of any program.
  ----------------------------------------------------------------
  To avoid retyping everything each time, we will create a
  MACRO INSTRUCTION that will do it for us.

  A MACRO is delimited by the directives:
  
  MACRO (After the name of the Macro to mark the beginning of the MACRO)
  -----
  ENDM  (At the end of the MACRO to mark the end of it)
  ----

     Example: A MACRO called ADD which adds the low word
     ---- of registers d0 and d1 will be written:


        TEXT

add      MACRO            ;beginning of the macro
        ADD.W    d0,d1   ;the Macro itself
        ENDM             ;End of the Macro

    ; This MACRO can then be used:

        MOVE     #3,d0
        MOVE     #5,d1
        add              ;call of the MACRO 'add'
        MOVE     d1,res

        BSS

res     DS.W     1       ;We will find the word 5+3=8 in 'res'

        END

  The MACRO can be used as many times as you want, but
  care must be taken not to put Labels in your MACRO because they
  would be rewritten multiple times and this would cause errors...

  The MACRO can then be saved in a file.

  To indicate to the LINKER that you are going to use a MACRO that is in
  an external file, you will have to use the DIRECTIVE:

  INCLUDE   "file.xxx"
  -------
  It must be used before the first MACRO from 'file.xxx' is
  used. 
  The entire file will be ASSEMBLED separately, but only the used MACROs
  will be included.
  

  But let's go back to our GEMDOS 'setblock' function:

  The Listing of the SETBLOCK Macro will be:

          TEXT

SETBLOCK  MACRO               ;beginning macro
          move.l    a7,a5     ;USP in a5
          lea       stack,a7  ;'stack' is the address pointing to an area
                              ;of memory reserved for certain 
                              ;functions. 
                              ;(the name of the label is arbitrary...)
                              ;(Of course, you must reserve this area with
                              ;DS.x space: 200 bytes are generally enough)
          move.l   4(a5),a5   ;free memory ending address in a5
          move.l   $c(a5),d0  ;TEXT area length in d0
          add.l    $14(a5),d0 ;adds the size of the DATA zone 
          add.l    $1C(a5),d0 ;adds the size of the BSS zone
          add.l    #$100,d0   ;adds size of Base P. to d0

          move.l   d0,-(sp)   ;STACKS the space to reserve (1st parameter)
          move.l   a5,-(sp)   ;STACKS a5                  (2nd parameter)
          move     #0,-(sp)   ;STACKS word=0              (3rd parameter)
          move     #$4a,-(sp) ;STACKS the CODE of SETBLOCK
          trap     #1         ;GEMDOS call ->execution of the function.
          add.l    #12,sp     ;When returning, SP is incremented to
                              ;regain its initial value.

          ENDM                ;end of the MACRO

          END                 ;end of assembly


 We will save this macro in the file 'INIT_TOS.L'.


 All the programs we write will therefore have to look like this:
 ---------------------------------------------------------------------
 
     TEXT

     INCLUDE   "INIT_TOS.L"   ;Linkage of the file


     SETBLOCK                 ;call of the MACRO SETBLOCK

     .                        ;the instructions 
     .                        ;that form the prg
     .

     DATA                     ;the data zone

     .                        ;with the initialized data
     .
     .

     BSS                      ;the bss zone

     .                        ;with the reservations
     .
     .

     DS.B      200            ;and space reserved for the needs 
stack DS.B      1             ;of the GEMDOS, BIOS, XBIOS functions we
                              ;will use. (Upstream of the
                              ;'stack' label). USP points on 'stack' and 
                              ;will be decremented when passing the 
                              ;parameters to the functions 
                              ;(MOVE.x source, -(SP) )
                              ;:Let's not forget that only the memory that
                              ;the program really needs is 
                              ;reserved after SETBLOCK.
     END


  The listing of the SETBLOCK macro instruction is found in the file
  INIT_TOS.L on this disk and is fully available to you.


 NB:You will therefore always have to make sure to reserve memory in the
 -- BSS zone upstream from the address pointed to by the label we
    named 'STACK'.
    There is no need to economize on space by reserving little memory,
    the size of the BSS segment does not affect the
    size of the PRG...
    

- I will now enumerate the various functions of the GEMDOS.

  Only the commonly used functions will be studied, for the
  others, you will have to refer to THE ST BIBLE, but I doubt you
  will need to use them in the near future...

  For each function, I will give you:

  .The CODE and the NAME of the function
      ----       ---
  .The PARAMETERS to pass
       ----------
  .The PURPOSE of the function
      ---

  .A MACRO INSTRUCTION that uses the studied function if it 
   can be frequently useful to us...

       All these macro instructions that we will create from the 
   GEMDOS, BIOS and XBIOS functions will be collected in the file
   MACROS.L and of course, you can use them whenever
   you desire.



                      *** THE GEMDOS FUNCTIONS ***
                      -------------------------------

$00 (TERM), no parameter
---
TERM allows to end the program and return to the calling program
(or parent program).
That is to say that if we use the TERM function of gemdos, the prg stops and
returns to the GEM DESKTOP (if the program has only been loaded from
the DESKTOP) or to the instruction following the calling instruction, of
the FATHER program. In this latter case, the PRG using the term function is
named SON program and has been loaded by the so called 'FATHER' program.

TERM      MACRO               ;TERM macro named 'TERM'
          CLR.W     -(SP)     ;TERM code
          TRAP      #1        ;GEMDOS call
          ENDM                ;MACRO end


$01 (CCONIN), no parameter
---
CCONIN waits for a character on the keyboard and displays it at the current
cursor position.
The function returns, the ASCII code of the pressed key in the low
byte of the low word of d0 and the SCANCODE of the
key in the low byte of the high word of d0.
The SCANCODE allows to identify keys that do not have an ASCII code
(such as function keys) and it also allows to distinguish between
keys that have the same ASCII code (such as numbers on the numeric
keypad and those on the main block)

The ASCII code and SCANCODE can be reached in this way for
example:

     MOVE      #$01,-(SP)     ;CCONIN CODE
     TRAP      #1             ;-->gemdos
     ADDQ.L    #2,SP          ;we reinitialize SP
     CMPI.B    #'A',d0        ;compare the low byte of the low word of
                              ;d0 with the ASCII code of
                              ;'A' that is $41
     BEQ       yes
     SWAP.W    d0             ;SWAP the 2 words of d0
     CMPI.B    #0,d0          ;is the SCANCODE nill ???
     BNE       no
     etc...
  
NB:You have noticed that I wrote:CMPI  #'A',d0.
-- Writing 'A' or the ASCII code of A that is $41 is identical.
   You can therefore for example replace MOVE  #$42,d0 with MOVE  #'B',d0
   ,this makes the listing more readable if you use instructions
   that must move data representing ASCII codes...
   The assembler will make the correction. (just as MOVE source,an is
   accepted and replaced by MOVEA source,an)
 
CCONIN    MACRO                    ;The equivalent macro
          MOVE      #$1,-(SP)
          TRAP      #1
          ADDQ.L    #2,SP
          ENDM

          
$02  (CCONOUT), WORD=ascii code
---
CCONOUT displays the character represented by the ASCII code that is passed
as a parameter on the stack at the current cursor position.

CCONOUT   MACRO     $\1         ;here, $\1 tells the assembler that we 
                                ;will pass a parameter to the macro.
          move      \1,-(SP)    ;we stack the parameter \1
          move      #2,-(SP)    ;then the code of CCONOUT   
          trap      #1          ;gemdos
          addq.l    #4,SP       ;correction of the stack   
          ENDM                  ;end of the MACRO

As you can see, we have just created a MACRO instruction
that accepts a PARAMETER.
It is indicated to the assembler by the directive: MACRO   $\1
   
The parameter can be for example:#'A' or d0 or #$48 etc...

Examples of using the macro CCONOUT (with a parameter):
--------
     CCONOUT   #'a'

will display an 'a' on the screen

     MOVE      #'a',d0
     CCONOUT   d0

idem

     CCONOUT   #53

will display the character with ASCII code 53.



$03 (CAUXIN), no parameter
---
CAUXIN allows the reception of a character via the RS232 interface.
If there has been no error, the ASCII code of the character returns in
the low byte of d0.

     MOVE      #$3,-(SP)
     TRAP      #1
     ADDQ.L    #2,SP

$04 (CAUXOUT), WORD=ascii code
---
CAUXOUT causes the emission of the character whose ASCII code has been passed
as a parameter in the stack to the RS232 interface.

     MOVE      #'A',-(SP)     ;sends an 'A'
     MOVE      #$4,-(SP)
     TRAP      #1
     ADDQ.L    #4,SP


$05 (CPRNOUT),WORD=ascii code
---
CPRNOUT emits the character whose ASCII code has been stacked to 
the printer.
If the character was well sent, we obtain the word -1 in d0.
If the printer is unable to receive the character, we obtain a
word equal to 0 in d0.

     MOVE      #'A',-(SP)     ;we print an 'A'
     MOVE      #$5,-(SP)      ;CPRNOUT code
     TRAP      #1
     ADDQ.L    #4,SP

$06 (CRAWIO),WORD=$FF or ascii code
---
CRAWIO admits two types of parameters.
If the parameter is a WORD equal to $FF, CRAWIO tests if a key of
the keyboard IS pressed.(like INKEY in BASIC)
If a key was pressed, its ASCII code and its scan code enter
in d0, otherwise d0 remains unchanged.
If the parameter is different from $FF, this value is interpreted as
the ASCII code of a character to send to the screen.

INKEY     MACRO                   ;CRAWIO with $FF as parameter
          MOVE      #$FF,-(SP)
          MOVE      #$6,-(SP)
          TRAP      #1
          ENDM

  Example of using the INKEY macro:
  -------
test       INKEY               ;macro call  INKEY
          CMPI.B    #'A',d0   ;compare the ASCII code of d0 with 'A'
          BEQ       yes       ;key 'A' pressed? If yes, goes to 'yes'
          JMP       test      ;otherwise return to 'test'     
yes       NOP  

As long as the 'A' key is not pressed, we jump to 'test'.


$07 (CRAWCIN), no parameter
---
CRAWCIN waits for a key to be pressed.
The recognized character is not displayed, but the ASCII code and scan code
of the pressed key is transmitted to d0 in return.

WAIT      MACRO               ;waiting macro for a key
          MOVE      #$7,-(SP) ;CRAWCIN code
          TRAP      #1
          ADDQ.L    #2,SP     ;keys codes in d0.
          ENDM
              
$08 (CNECIN), no parameter
---
Identical function to CRAWCIN, except that here, pressing CONTROL-C ends the
PRG (like with PTERM), CONTROL-S stops the display, CONTROL-Q resumes
the display interrupted by control-s.

$09 (PRINT LINE), L-W= address of a string of characters terminated by a 
---                zero byte.

This function allows to display a string of characters on the screen.
The string of characters to be displayed must be located in the  DATA area
and must be terminated by a NULL byte.

PRINTLINE      MACRO     $\1       ;MACRO with \1 parameter: The address of
                                   ;the string of characters to be displayed.
               PEA       \1        ;STACK the address \1.
               MOVE      #$9,-(SP) ;PRINTLINE code
               TRAP      #1
               ADDQ.L    #6,SP
               ENDM
 
Example of using the macro PRINTLINE:
-------
          PRINTLINE      laurent
          PRINTLINE      exp2
          PRINTLINE      exp3

          DATA

laurent   DC.B           'laurent PIECHOCKI 8,impasse Bellevue 57980',0
exp2      DC.B           53,54,56,80,45,25,0
exp3      DC.B           27,'E',7,'LAURENT',25,0


 NB:  To obtain effects such as screen erasing, line jumps... there are special codes that must be transmitted to
 ---  functions such as PRINTLINE,CCONOUT... 

      The codes preceded by the ASCII value 27 (ESC).
      -----------------------------------------------
      27,'E'  :erase the screen
      27,'B'  :positions the cursor one line lower
      27,'A'  :positions the cursor one line higher
      27,'C'  :positions the cursor one line further to the right
      27,'D'  :positions the cursor one line further to the left
      27,'J'  : clear the screen from the current cursor position
      27,'L'  : insert a line
      27,'M'  : delete the line where the cursor is
      27,'I'  : scroll the cursor and text upwards
      27,'H'  : position the cursor at line 1, column 1
      27,'K'  : delete a line from the cursor to the end of the line

      27,'Y',x,y : position the cursor at line x-32 and at column
                  y-32                             
                  ----
                  ----
      27,'b',x   : Change the text color to color number x
      27,'c',x   : Change the background color to color number x
      27,'f'     : Makes the cursor disappear
      27,'e'     : Makes the cursor reappear
      27,'j'     : Memorize the cursor position
      27,'k'     : Position the cursor at the memorized position
      27,'p'     : VIDEO-INVERSE mode of writing
      27,'q'     : Return to normal VIDEO


      Thus, if I write:  
      ------------------
        PRINTLINE  clear
   
        DATA

clear  DC.B       27,'E','laurent',0

      or
      --
        CCONOUT    #27
        CCONOUT    #'E'
        PRINTLINE  laurent

        DATA

laurent DC.B       'laurent',0


Clear the screen (ESC,'E') and display the string:'laurent'


$0A (READLINE), L-M pointing to a buffer
---
READLINE allows the entry of a certain quantity of characters on the screen.
(similar to INPUT in BASIC).
The string can be modified during editing with 
[Backspace] and [Delete] and will be validated by [Return] or [Enter].
(CONTROL-C ends the program)

You must provide the address of a buffer organized as follows:

In BSS area: DS.B   maximum number of characters to enter+2
-----------
You must have placed at the beginning of this buffer a BYTE representing the maximum
number of characters to enter (MOVE.B x,buffer) before using the
READLINE function.

After returning from the function:
In 'buffer'+1 is the number of entered characters
In 'buffer'+2 is the start of the entered character string.

READLINE       MACRO          $\1       ;parameter=buffer address
               PEA            \1
               MOVE           #$0A,-(SP)
               TRAP           #1
               ADDQ.L         #6,SP
               ENDM

   Example of using the READLINE macro:
   ---------------------
     MOVE.B    #5,resu   ;5 characters to enter
     LEA       resu,a5   ;address of 'resu' in a5
     READLINE  resu      ;readline
     addq.l    #2,a5     ;a5 points to the entered character string
     MOVE.B    #0,zero   ;places a NULL BYTE at the end of the string for
     PRINTLINE a5        ;display the string with PRINTLINE
     TOUCH                ;waiting for a key press
     DESKTOP              ;then exit the program     

     BSS

resu DS.B      7         ;reservation for READLINE
zero DS.B      1         ;reservation for the NULL byte that will end the 
                         ;string for PRINTLINE




$0B (CONIN STAT),no parameter
---
Calling this function returns a WORD in d0 equal to -1 if the keystroke buffer contains characters.
d0=0 if there are no characters available in this buffer.

     MOVE      #$B,-(SP)
     TRAP      #1
     ADDQ.L    #2,SP
     TST.W     D0
     BNE       nothing

$0E (SETDRIVE),WORD=drive number to activate.
---
SETDRIVE activates the drive whose number is passed as a parameter in
the system stack.
0=Drive A
1=Drive B etc...

In return, the function gives d0 which is organized in such a way that the
only active bit of d0 represents the last activated drive.
(active bit number=drive number)


DRIVE     MACRO     $\1            ;param. \1=drive number
          MOVE      \1,-(SP)      
          MOVE      #$E,-(SP)
          TRAP      #1
          ADDQ.L    #4,SP
          ENDM

     Example of use:
     ------------------
     DRIVE     #2

Drive C is activated.
If the last active Drive was drive B, we would have:

d0=%0000000000000010
                  |
                 \|/

           bit number1=drive B


$19 (CURRENT DISK),no parameter
---
This function allows you to know which DRIVE is ACTIVE.
The number of the active drive is returned in d0 in the previous format.

WATHDRIVE      MACRO                    ;Which is the active drive?
               MOVE      #$19,-(SP)
               TRAP      #1
               ADDQ.L    #2,SP     
               ENDM

$1A (SETDTA), L-M=address of the DTA buffer
---
SETDTA installs the DTA buffer used by some GEMDOS functions that operate on files.
This buffer must be 44 bytes in size, its address must be 
stacked in the system stack and must be EVEN.

To obtain an even address, you can reset the PC with the
BSS directive or use appropriate directives (but specific to
the assembler used): ALIGN.W for PROFIMAT
                        :CNOP 0,2 for METACOMCO

You can also simply make a correction by adding 1 BYTE
to a lower address (DS.B 1), this has the effect of increasing the value
of the DTA address: odd address+1=even address.

 
          PEA       buffer
          MOVE      #$1A,-(SP)
          TRAP      #1
          ADDQ.L    #6,SP

          BSS

buffer    DS.B      44


$20 (SUPER),L-M=0 or L-M=new SP value
---
Here is the function that allows you to switch to SUPERVISOR MODE.

If the parameter you provide is a L-M=0, SUPER will activate SUPERVISOR MODE and return the SP value in d0.
You must save this address because it will be essential to
return to USER MODE (To exit the program for example)

If you stack another L-M than 0, it will be interpreted as the new 
SP value and d0 will contain the old SP value.

SUPER     MACRO                    ;switching to SUPERVISOR MODE
          CLR.L     -(SP)
          MOVE.W    #$20,-(SP)
          TRAP      #1
          ADDQ.L    #6,SP
          MOVE.L    d0,sauv_sp     ;save SP in 'sauv_sp'
          ENDM

Of course, a L-M must be reserved in 'sauv_sp'!

To return to USER MODE (essential to exit the program
for example...):
Use the same function, but pass it the old
SP value that was saved in sauv_sp.

USER      MACRO                    ;returning to USER MODE
          MOVE.L    sauv_sp,-(SP)  ;restore SP
          MOVE.W    #$20,-(SP)
          TRAP      #1
          ADDQ.L    #6,SP
          ENDM



$2A  (GET DATE),no parameter
---
Allows you to obtain the DATE of the GEM desktop clock in d0 as follows:

Bits 0 to  4=day
Bits 5 to  8=month
Bits 9 to 15=(year-1980)

     MOVE      #$2A,-(SP)
     TRAP      #1
     ADDQ.L    #2,SP

Example: if d0=%0001000000100001

The date is:

DAY:bits 0 to 4 :%00001=the 1st
MONTH:bits 5 to 8 :%00001=January
YEAR :bits 9 to 15:%0001000=8+1980=1988

$2B (SET DATE),WORD=date 
---
SET DATE allows setting the GEM clock to the date you provide as a parameter.

The date (WORD) is in the format previously described.

bits 0 to 4: day
bits 5 to 8: month
bits 9 to 15: (year-1980)

If the date is incorrect (45/20/1745...), d0 returns with the value -1,
otherwise, it returns with the value 0.

     MOVE      #%00010000000100001,-(SP)     ;January 1st, 1988
     MOVE      #$2A,-(SP)
     TRAP      #1
     ADDQ.L    #4,SP


$2C (GET TIME),no parameter
---
GET TIME returns the time from the GEM clock in d0 in the form:

bits 0 to 4  :(seconds/2)
bits 5 to 10 :minutes 
bits 11 to 15:hour 

     Example:

test MOVE      #$2C,-(SP)     ;GET TIME
     TRAP      #1
     ADDQ.L    #2,SP
                              ;d0 contains the time
     AND.W     #%11111,d0     ;we MASK bits 0 to 4 of d0:
                              ;bits 5 to 15 of d0 are therefore cleared.
                              ;it leaves the seconds.

     MULS      #2,d0          ;x2 because seconds=(seconds/2) in d0
     CMPI      #30,d0         ;do we have seconds=30?
     BEQ       yes            ;if yes: go to 'yes'
     JMP       test           ;otherwise, return and request the time again. 

$2D (SET TIME),WORD=time
---
SET TIME sets the time of the GEM clock with the parameter provided.

The time must be coded in the form:

bits 0 to 4  :(seconds/2)
bits 5 to 10 :minutes 
bits 11 to 15:hours 

     Example:

     MOVE      #%0001000000100001,-(SP)
     MOVE      #$2D,-(SP)
     TRAP      #1
     ADDQ.L    #4,SP

We set the clock to 2h, 1 min, 2 sec


$31 (KEEP PROCESS),WORD=0,L-M=number of bytes to protect.
---
KEEP PROCESS, like PTERM, ends the program and returns to the 'parent' program.

With PTERM, the exited program is permanently erased from memory,
while with KEEP PROCESS, a certain amount of BYTES in memory (parameter 2) is reserved and the program to exit is placed there.

This is important for interrupt-driven programs, for example, 
we will talk about this again... 

KEEP      MACRO     $\1            ;parameter=number of bytes to reserve
          CLR.W     -(SP)
          MOVE.L    #\1,-(SP)     
          MOVE      #$31,-(SP)
          TRAP      #1
          ADDQ.L    #8,SP
          ENDM

Example of use:

          KEEP   1024

We place the PRG in the reserved KO and exit...

NB: Be careful that you reserve enough memory...
--

$3C (CREATE),WORD=file attribute,L-M=address of the file name
---

CREATE allows creating a file in which you can place data.

The first parameter is the file attribute:

0=file accessible in Read and Write
1=file accessible in Read only
2=invisible file
4=system file (invisible to desktop)
8=volume label file (invisible to desktop)

The second parameter is the address pointing to the file name:

Organized like this:      'A:\file\name.ext',0

If the name of the program to create is 'name.ext' and if it is in the
'file' (unnecessary if it is not in a file...).
'A:' indicates that it is on the floppy disk unit A.
The character string must end with a NULL byte.

In return, CREATE returns in d0 the FILE HANDLE number of the file.
This number is used to distinguish the different external programs loaded.


CREATE     MACRO     $\1,$\2,$\3         ;CREATE with 3 parameters
          MOVE      #\1,-(SP)           ;\1=file attribute
          PEA       \2                  ;\2=address of the name 
          MOVE      #$3C,-(SP)
          TRAP      #1
          ADDA.L    #8,SP
          MOVE      d0,\3               ;\3=address to save d0.
          ENDM

Example of use:

          CREATE     0,prg,handle        ;file in Read/Write mode

          DATA

prg       DC.B      'A:\laurent.gag',0  ;name of the file to create

          BSS

handle    DS.W      1                   ;1 Word for the handle

$3D  (OPEN),WORD=attribute,L-M=address of the file name to open
---
OPEN allows opening a file created with CREATE for later use (reading or writing).

The first parameter to provide is the attribute of the file to open
The second parameter to provide is the address of the name of the file to open.

If OPEN encounters no problems (file present and accessible),
d0 returns with the file handle number, otherwise, it returns with a
negative value. (This is an error code, see the list at the end of the 
chapter.)

OPEN    MACRO     $\1,$\2,$\3    ;OPEN with 3 parameters
        MOVE      #\1,-(SP)      ;\1=attribute
        PEA       \2             ;\2=address of the file name
        MOVE      #$3D,-(SP)
        TRAP      #1
        ADDQ.L    #8,SP
        MOVE      d0,\3          ;\3=address to save the handle
        ENDM

Example of use:

        OPEN    0,prg,handle   ;opening the file (Read/Write attribute)

        DATA

prg     DC.B      'A:\name.ext',0 ;name of the file to open

        BSS

handle  DS.W      1              ;1 Word for the handle


$3E (CLOSE),WORD=handle number
---
If the file was opened with OPEN, it will be closed by CLOSE, you must
pass the file handle number as a parameter.

In return, if the file was correctly closed, d0=0.

CLOSE    MACRO     $\1            ;MACRO with 1 parameter
          MOVE      \1,-(SP)       ;\1=handle number
          MOVE      #$3E,-(SP)
          TRAP      #1
          ADDQ.L    #4,SP
          ENDM

Example of use: 

          CLOSE    handle

          BSS

handle   DS.W      1         ;here was placed the file handle.



$3F (READ),L-M=buffer address,L-M=number of bytes to read,WORD=handle number
---
READ allows reading a file opened by OPEN.
The following parameters must be provided to READ:
1st: The address of a buffer where the read data will be placed
2nd: The number of bytes to read from the file
3rd: The file handle number

D0 returns with the number of bytes read or a negative error code.

READ      MACRO          $\1,$\2,$\3    ;MACRO with 3 parameters
          PEA            \1             ;\1=buffer address
          MOVE.L         \2,-(SP)       ;\2=number of bytes to read
          MOVE           \3,-(SP)       ;\3=handle number
          MOVE           #$3F,-(SP)
          TRAP           #1
          ADDA.L         #12,SP
          ENDM

Example of use:

          READ      buffer,#1024,handle ;read 1 KB of data

          BSS

buffer    DS.B      1024 ;the buffer for the 1024 bytes to read
handle    DS.W      1    ;here is the handle number



$40 (WRITE),L-M=address of the data buffer to write,L-M=number of bytes
---         to write,WORD=handle number.

WRITE allows writing data to a file opened with OPEN.

The parameters to pass are:
1st: The address of the buffer containing the data to write to the file.
2nd: The number of bytes to write to the file
3rd: The handle number

D0 returns with 0 if everything is OK or with a negative error code.


WRITE     MACRO     $\1,$\2,$\3         ;3 parameters
          PEA       \1                  ;\1=buffer address
          MOVE.L    \2,-(SP)            ;\2=number of bytes to write
          MOVE      \3,-(SP)            ;\3=handle number
          MOVE      #$40,-(SP)
          TRAP      #1
          ADDA.L    #12,SP
          EDNM

     Example of use:

          WRITE    data,#10,handle

          BSS

data      DS.B      10   ;the 10 bytes to write
handle    DS.W      1    ;here was saved the handle


$43 (FATTRIB),WORD=attribute,WORD=write or read,L-M=address of the name of 
---           the file to modify

FATTRIB allows changing or reading the attribute of a file.
The parameters to pass are:

1st: The attribute to write (if you want to change it, otherwise put 0)

 0=file accessible in Read and Write
 1=file accessible in Read only
 2=invisible file
 4=system file (invisible to desktop)
 8=volume label file (invisible to desktop)
10=sub-directory file (for reading only!)
$20=file written and closed correctly (for reading only!)

2nd: A Word equal to 1 if FATTRIB should CHANGE the attribute
   A Word equal to 0 if FATTRIB should READ the attribute, in this case,the attribute
   of the file returns in d0. (or a negative error code)
 
3rd: The address pointing to the name of the file to modify or read

FATTRIB    MACRO          $\1,$\2,$\3         ;macro with 3 parameters
          MOVE           \1,-(SP)            ;\1=attribute
          MOVE           \2,-(SP)            ;\2=write or read
          PEA            \3                  ;\3=address of the file name
          MOVE           #$43,-(SP)
          TRAP           #1
          ADDA.L         #10,SP
          ENDM

     Example of use:

          FATTRIB         #$02,#1,prg

          DATA

prg       DC.B           'A:\auto\laurent.tab',0

FATTRIB will hide the file 'laurent.tab' from the 'auto' file on the desktop.


$4B (PEXEC),L-M=environment address,L-M=command line address,L-M=program name address,WORD=loading mode                          

PEXEC allows loading an external file in 3 modes.

In mode 0: The program is loaded, PEXEC passes the command line and the en-
          vironment to the loaded program and then executes it.
          (the command line and the environment are parameters that
           can be passed to programs like .TTP or .APP) 
In mode 3: The program is loaded, PEXEC passes the command line and the en-
          vironment to the program and the address where it is located
          is obtained in d0.
In mode 4: The program loaded in mode 3 is executed.(in this case,the environment
          and the command line should not be used)

The parameters to pass to PEXEC are:

1st: The environment address
2nd: The command line address
3rd: The program name address
4th: The loading mode (0,3 or 4)

The program using PEXEC is called the PARENT program, the program loaded by
PEXEC is the CHILD program.
The PARENT program remains in memory after using PEXEC.

PEXEC     MACRO     $\1,$\2,$\3    ;MACRO with 3 parameters
          PEA       \1             ;\1=environment address
          PEA       \2             ;\2=command line address
          PEA       \3             ;\3=program name address
          MOVE      \4,-(SP)       ;\4=mode
          MOVE      #$4B,-(SP)
          TRAP      #1
          ADDA.L    #16,SP
          ENDM

     Example of use:

          PEXEC     nul,zero,prg,#0

          DATA

nul       DC.B      0                    ;no environment
zero      DC.B      0                    ;no command line
prg       DC.B      'A:\laurent.prg\',0  ;the program to load and execute in
                                         ;mode 0

NB: For possible inclusions of ASSEMBLER files under a
--  program in GFA BASIC, simply use the EXEC function
    of the GFA, and pass the parameter in the command line.
    The CHILD program in assembler will read the parameter which 
    is at the $80th byte of the base page, it will then execute
    taking into account the parameter, and using the
    PTERM function of Gemdos, it will hand back control to the
    PARENT program in GFA...

$4E (SEARCH),WORD=file attribute,L-M=file name address to
---          search for
  
SEARCH checks if the file whose name is given is present
on the floppy disk.
If it is present, d0 returns with the value 0 and the DTA buffer, which will
have been previously installed with the SETDTA function ($1A), will be organized
as follows:

Byte  21     : file attribute
Bytes 22 to 23: File installation time
Bytes 24 to 25: File installation date
Bytes 26 to 29: File size in bytes
Bytes 30 to 43: NAME and SUFFIX of the found file

If the file is not found by SEARCH, d0 returns with the error
code -33 (file not found)

Note: Files with the Volume Label attribute cannot be recognized
-- by SEARCH...

   If the file name is of the type:

.  'A:\file.*',0 : The SUFFIX of the file is not considered
   -----------
.  'A:\*.ext',0  : Only the SUFFIX is considered
   ----------
.  'A:\*.*',0    : =All files
   --------
.  'A:\A??.ext',0: The ? can be any letter 
   ------------
   (for example ABC.ext and AXX.?AA can be identified by A??.*)
  
But in these cases, several names are suitable for SEARCH (for example, if we
search for 'A:\PRG.*',0: 'A:\PRG.EXT',0 and 'A:\PRG.DOC',0 are suitable),
SEARCH will then take the first file from the directory that fits.


SEARCH    MACRO     $\1,$\2,$\3    ;MACRO with 3 parameters
          PEA       \1             ;\1=DTA buffer address (44 bytes)
          MOVE      #$1A,-(SP)     ;SETDTA
          TRAP      #1
          ADDQ.L    #6,SP          ;The DTA buffer is installed

          MOVE      \2,-(SP)       ;\2=file attribute
          PEA       \3             ;\3=file name address
          MOVE      #$4E,-(SP)     ;SEARCH
          TRAP      #1
          ADDQ.L    #8,SP
          ENDM

     Example of use:

          SEARCH    dta,#0,prg          ;attribute=Read/Write
          CMPI      #-33,d0             ;file not found ??
          BEQ       file_not_found      ;then go to file_not_found

          DATA


prg       DC.B      'A:\file\name.ext',0   ;The program to search for

          BSS

dta       DS.B      44                       ;44 bytes reserved for the DTA


$4F (SEARCH NEXT),no parameter
---          
If we use SEARCH and look for files whose name can vary
(PRG.* for example) and if several files correspond to this name, we have
seen that the first file from the directory that fits is selected.
With SEARCH NEXT, we can search for other files that fit the
multiple-choice file name.
SEARCH NEXT returns a NULL value in d0 if there are no more files
whose name fits the searched file name.
So, for example (To find files of the type 'x.*'), we can test
the existence of other fitting files by integrating SEARCH
NEXT in a loop by testing d0 (if d0=0 we have to exit: thus, we will use
TST.W d0 then DBEQ dn,loop...)
  
     MOVE      #$4F,-(SP)
     TRAP      #1
     ADDQ.L    #2,SP


$56 (FRENAME),L-M=new name address,L-M=old name address,
---           WORD=0

FRENAME allows changing the name of a file.
Just pass the address pointing to the new file name and
the address pointing to the old file name as parameters.

D0 returns with a null value or a negative error message.

RENAME    MACRO     $\1,$\2   ;MACRO with 2 parameters
          PEA       \1        ;\1=new file name address
          PEA       \2        ;\2=old name address
          MOVE      #0,-(SP)  ;\3=0
          MOVE      #$56,-(SP)
          TRAP      #1
          ADDA.L    #12,SP
          ENDM
          
     Example of use:

          RENAME new_name,old_name

          DATA

new_name  DC.B      'A:\zzzzz.zzz',0    ;new file name
old_name  DC.B      'A:\zzzzz.aaa',0    ;old name



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

APPENDIX: GEMDOS error codes:
-------
-32: Invalid function number
-33: Nonexistent file
-34: Nonexistent access name
-35: Too many files open
-36: Impossible to input
-37: Invalid reference number
-39: Insufficient memory
-46: Invalid floppy disk unit
-49: No more other files


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

  That's it for the GEMDOS functions.

  I have not enumerated all the GEMDOS functions, the others will
  hardly ever be useful to you:
  Only the interesting functions have been presented here.

  You can now head to your ASSEMBLER and create your 
  first programs:
  They may not yet be brilliant, but at least they will have
  the merit of being in ASSEMBLER and allowing you to progress.
  Good luck...

  Others, please read the next chapter on BIOS and
  XBIOS functions which is on disk number 2.
                                ----------------
  The exercises will follow, and with them YOUR first programs in
  ASSEMBLER worthy of the name...


  PIECHOCKI Laurent
  8, impasse Bellevue                    continued in: BIOS.DOC (DISK 2)
  57980 TENTELING                                  -----------------

Back to ASM_Tutorial