Z88 Developers' Notes
Previous Contents Next

4. Application Static Structures

Before you can begin to write an application it is necessary to include certain information in the ROM card which tells the system what the card contains. This section explains how to set up the static structures, including menu topic help, which define your application. Following this, actual programming techniques and facilities can be examined.
 

Introduction

The most unusual facet of the Z88 is its ability to deal with many applications and suspend and reactivate them as required. An application may be set up on a ROM or EPROM card and inserted into one of the slots at the front of the machine. If the appropriate data structures are set up on the card, then the operating system can make application appear like the in built programs, such as Pipedream. Applications are rather confusingly divided into 'Applications' and 'Popdowns'. When we talk about applications in general this includes popdowns, but when talking about the two together an application is distinct from a popdown. The actual difference between the two, when a contrast is being drawn, is that a popdown will receive a KILL request from the system whenever the user attempts to switch applications. A popdown is useful for functions like the clock and calculator which on ce they have been used do not really need to remember what they were doing before, so it is perfectly allright to close them down completely and start them up from scratch when they are required again. An application, as opposed to a popdown, can be returned to after application switching, so that the user can continue to use it as before.

Applications are further divided into good and bad types. Most applications are 'good': they only take RAM as they need it, using the memory management routines, and do not demand more than 256 bytes of contiguous RAM. 'Bad' applications, demanding larger blocks of memory, can use up to a 40K of contiguous RAM - this feature was included in order to be able to run standard BBC BASICZ80 - a binary image designed for a normal Z80 system. There is also an 'ugly' application type, which is similar to 'bad' but refers only to popdowns ie. a bad popdown. None of the built in applications is of this type. Applications types are, therefore:
 

Good        An application application not requiring large contiguous
            workspace.

Bad         An application application requiring large contiguous workspace.

Popdown     A popdown application not requiring large contiguous workspace.

Ugly        A popdown application requiring large contiguous workspace.


ROM Headers and Front DORs

Applications are set up as linked lists of DORs, an object linking structure which is explained in 'DORs', one list for each ROM card (including the internal one in Slot 0). The application DORs contain such vital information as where the application entry point is and whether caps lock should be set on entry; more of this below. The root of each link is the 'front DOR'. The first application is linked as a son to this DOR, and subsequent applications are linked together as brothers. For instance, in the internal ROM, the arrangement of application DORs is as follows:

Front DOR | Index DOR - Diary DOR - PipeDream DOR .... Terminal DOR - Imp/Export DOR

When the operating system searches for applications it looks at each slot in turn, starting with the internal ROM or slot 0. The top bank of each slot is examined for the presence of 'OZ' in the uppermost two bytes - if this is found then the card is identified as containing applications. Filing system EPROMs are identified by 'oz' in the top two bytes. The full header which an application card should incorporate at the top of its highest bank is as follows:
 

$3FF8       @0xxxxxxx     Low byte of card ID
$3FF9       @0xxxxxxx     High byte of card ID
$3FFA       @0000xxxx     4 bit country code
$3FFB       $80           Marks external application
$3FFC       x             Size of card in banks, eg. $02 for a 32K card
$3FFD       $00           Subtype of card - future expansion
$3FFE       'OZ'          Card holds applications
The country codes is as follows: The high nibble of the country code byte must be 0 (@0000). The low nibble indicates the language variant of the application, and is coded as follows:
            0000          (0) USA                 1000        (8) Japan
            0001          (1) France              1001        (9) Iceland
            0010          (2) Germany             1010        (A) Norway
            0011          (3) UK                  1011        (B) Switzerland
            0100          (4) Denmark             1100        (C) Turkey
            0101          (5) Sweden              1101        (D) reserved...
            0110          (6) Italy               1110        (E) reserved...
            0111          (7) Spain               1111        (F) reserved...
Before commercial release it is necessary to obtain a card ID. If two commercially released cards shared an ID, then inserting both into the machine could cause serious problems for the card manager, and it is most important that this should not happen. The bits explicitly given above will be true for all external IDs - alternative settings of these bits are reserved for future internal applications.

Next, the card manager expects to find the application front DOR starting in the top bank of the slot, at bank offset $3FC0. This section should be identical for all application cards, apart from the address of the first application DOR.

3 bytes     0 0 0         Link to parent
3 bytes     0 0 0         Link to brother - this may point to the HELP front DOR
3 bytes     x x x         Link to son - this points to the first application DOR

1 byte      $13           DOR type, ROM Front DOR
1 byte      8             DOR length

1 byte      'N'           Key for name field (DT_NAM)
1 byte      5             Length of name and terminator
5 bytes     'APPL', 0     NULL-terminated name
1 byte      $FF           DOR terminator
The 3 byte links consist of a 2 byte offset within a bank (low byte, high byte) followed by a bank number. It is recommended but not necessary that all the application header information, including menus and help, are placed in the top one or two banks. The space between the application front DOR and the card header above it should be padded with zeros. Note: The bank numbers should be offset from the top bank. ie. the top bank should be $3F, the one below $3E etc. In a 128K EPROM the lowest bank should be thought of as $38 and not as $00.
 

The Application DOR

The application DOR(s) may now be placed wherever is convenient (the contain relative data structure pointers), and if there is more than one, chained together via the brother links. An application DOR contains various information relevant to running the application, and may also contain pointers to menu topic help information. The format of an application DOR is as follows:

3 bytes     0 0 0         Link to parent
3 bytes     x x x         Link to brother (this will be 0 0 0 if this is the only
                          application on the card or the last in a chain)
3 bytes     0 0 0         Link to son

1 byte      $83           DOR type, application ROM
l byte      x             Total DOR length
1 byte      '@'           Key to info section
1 byte      x             Length of info section

2 bytes     0 0           Reserved for future expansion

1 byte      'x'           Application key letter, i.e. the letter used in the
                          square sequence to enter the application. If several
                          applications share a letter, then the first is entered
                          by []x, the next by []Zx, the next by []ZZx, etc. A
                          maximum of ZZZZ is possible. However, a bug in v3.0 of
                          the operating system doesn't allow for more than []ZZx.

1 byte      x             Contiguous RAM size required, in 256-byte pages (eg. 32
                          for 8K). This is relevant only to bad applications and
                          must be between 8K and 40K, ie. this byte ranges from
                          32 (32*256=8K) and 160 (160*256=40K). See the section
                          below on bad applications. Use 0 to make your
                          application the default size, which is 8K on an
                          unexpanded machine and 40K on an expanded one, or if
                          your application is good.

2 bytes     0 0           This is an estimate of environment overhead, ie. how
                          much memory is needed to save the state of the
                          application each time it is exited. OZ will 'learn'
                          from experience how much is actually required anyway,
                          so this feature is best ignored.

2 bytes     x x           Unsafe (ie. not preserved over pre-emption) workspace
                          size required in bytes (low byte, high byte).

2 bytes     x x           Safe (ie. preserved over pre-emption) workspace size
                          required in bytes. These workspaces are allocated from
                          the system half of segment 0, downwards from $1FFD,
                          unsafe workspace at the top. They are used when it is
                          important that the workspace is not bound to awkward
                          segments, but rather remains stable in the logical
                          address space. Note that both safe and unsafe workspace
                          draw from the 2K area of memory from $1800 to $2000.
                          This area is also used for the application stack,
                          mailboxes, and some system stack. Therefore you must
                          make sure that all these demands do not exceed the
                          limited supply of available memory. It is probably
                          advisable to limit safe and unsafe workspace to not
                          much more than a couple of pages at the most.

2 bytes     x x           Entry point for application code (logical). Must be in
                          segment 3. Remember low byte, high byte order.

1 byte      x             Desired binding of Segment 0 on entry
1 byte      x             Desired binding of Segment 1 on entry
1 byte      x             Desired binding of Segment 2 on entry
1 byte      x             Desired binding of Segment 3 on entry.

                          Usually you will want to bind the bank containing the
                          code for your application to segment 3 and probably set
                          the other banks to zero. If the application is a bad
                          one, then certain segments will be bound to RAM on
                          entry, depending on the size of contiguous RAM
                          selected. The desired binding of such segments must be
                          set to zero to avoid conflict (RAM is paged in after
                          application is created therefore overriding explicit
                          bank references).

1 byte      x             Application type byte 1. Set it to a combination of the
                          following bits. Note the bits are not all orthogonal,
                          eg. if 4 is set 8 must be too.

            AT_GOOD = 1   Good application
            AT_BAD  = 2   Bad application
            AT_UGLY = 4   Ugly application, bad popdown
            AT_POPD = 8   Popdown, kill on pre-emption
            AT_ONES = 16  Only one instantiation is allowed (e.g. Diary).
            AT_DRAW = 32  OZ should attempt to preserve screen over pre-emption
                          (ranging from right edge of topic window to left edge
                          of OZ window). This should not be set unless absolutely
                          necessary, ie. when the application cannot reasonably
                          redraw its own screen in response to an RC_DRAW return.
                          Programmer laziness is not sufficient grounds! Note
                          that when memory is low OZ will fail to preserve the
                          screen anyway and will return RC_DRAW after screen
                          corruption.
            AT_FILM = 64  File manager ID, used by the Filer, DO NOT SET.
            AT_BOOT = 128 Application auto-boot, used by the Index, DO NOT SET.

1 byte      x             Application type byte 2. Given by combination of:

            AT2_CL  = 1   Set CAPS lock on entry
            AT2_ICL = 2   Set inverted CAPS lock on entry (should not be set
                          without bit 1 set too or the effect is undefined).
            AT2_IE  = 128 Ignore error returns - internal use only, DO NOT SET.

1 byte      'H'           Key to help section
1 byte      x             Length of help section
3 bytes     x x x         Extended pointer to topics
3 bytes     x x x         Extended pointer to commands
3 bytes     x x x         Extended pointer to application help
3 bytes     x x x         Extended pointer to token base.

                          If no menus, help or diamond sequences are required
                          then the above should all point to three zeros. E.g. an
                          extended pointer to the beginning of the current
                          application DOR would be suitable (it always contains
                          three zeros).

1 byte      'N'           Key to name section
1 byte      x             Length of name
x bytes     'xxxx',0      Null-terminated application name. If this too long then
                          it will look rather odd in the Index. 12 characters is
                          about the maximum sensible length.
                          Screen driver codes is allowed in the name (e.g. bold).
1 byte      $FF           DOR terminator byte.


Menu, Topic, Help (MTH)

Each application can have a set of 'topics' associated with it. These topics appear in the topic window on the left hand edge of the screen, below the application name. Normally all the topics are in grey but when the menu key is pressed a topic name is highlighted and a menu display is brought up. The menu consists of up to three columns of commands, which may be selected with a highlight bar or by using a special keyboard sequence also shown on the menu. Each topic and each command may have a page of help text associated with it and in addition the application itself may have a page of help text, perhaps for a general description of its function. An extra information topic, not displayed in the topic window, may be added to provide access to a series of help pages which are not directly associated with keyboard commands. This is useful to explain general features of the application or tips of command usage.
 

Topic information

The 'pointer to topics' is of the form of a 2 byte offset in a bank, followed by a bank number. The pointer should point to a series of topic definitions arranged like this:

            1 byte        0           Start marker
            x bytes                   <first definition>
            x bytes                   <second definition>
            ...
            ...
            x bytes                   <last definition>
            1 byte        0           End marker
Where each definition has the following form:
a           1 byte        b-a         length byte
            n bytes       'xxxxx'     topic name
            1 byte        0           optional null-terminator (see below)
            2 bytes       x x         Optional pointer to topic help page, if
                                      any. This is a 2-byte pointer relative to
                                      the start of the help text. NOTE: it is
                                      stored as high byte, low byte sequence
                                      (reverse of the conventional order).
            1 byte        x           topic attribute byte
            1 byte        b-a         length byte
b

The topic attribute byte:

bit 0       set for an 'An' topic eg. 'An Edit topic' - default is 'A'
bit 1       set for an information topic - see below
bits 2-3    should be 0
bit 4       set if topic entry has a pointer to a help page
bits 5-7    should be 0
The topic name terminator can simply be a null, but in fact any control character (ie. $00-$1F) will serve perfectly well. Therefore it is possible to use the attribute byte, or the high byte of the help pointer (hence the high byte, low byte ordering - although this won't apply if the help text length is more than 8K - the high byte becoming $80) to terminate the name. The system looks at the attribute and help pointers by counting back from the end of the topic entry, so there is no confusion between a term inator and an attribute byte or help pointer.

NOTE: Due to a bug in OZ it is necessary when creating information topics (bit 1), that the definitions must be placed before any command topics otherwise they are not recognized by the system.
 

Command Information

The 'pointer to commands' is of the form of a 2 byte offset in a bank, followed by a bank number. The pointer should point to a series of command definitions arranged like this:

            1 byte        0           Start marker
            x bytes       def(1,1)    first command of first topic
            x bytes       def(1,2)    second command of first topic
            ...
            x bytes       def(1,x)    last command of first topic
            1 byte        1           End of this topic

            x bytes       def(2,1)    first command of second topic
            ...
            x bytes       def(2,x)    last command of second topic
            1 byte        1           End of this topic

            x bytes       def(x,1)    first command of last topic
            x bytes       def(x,y)    last command of last topic

            1 byte        0           End of all topics
Each of these definitions should have the following form:
a           1 byte        b-a         length byte
            1 byte        x           command code (see below)
            x bytes       'xxx',0     null-terminated keyboard sequence for
                                      command.
            x bytes       'xxxxx'     Command name. The total length of the name
                                      and keyboard sequence must be 25 characters
                                      or less. Any control characters which you
                                      need to use must be brought in via tokens.

            1 byte        0           optional null-terminator (see below)
            2 bytes       x x         Optional pointer to command help page, if
                                      any. This is a 2-byte pointer relative to
                                      the start of the help text. NOTE: it is
                                      stored as high byte, low byte sequence
                                      (reverse of the conventional order).
            1 byte        x           command attribute byte
            1 byte        b-a         length byte
b

The command attribute byte:

bit 0       set to make this entry the first in a new column. Note: the last
            entry in a column has no special attribute. Set this bit even
            though the previous column is used up, otherwise the system gets
            confused in displaying the entries.

bit 1       should be set to 0

bit 2       set to make a hidden entry. The command name and key sequence will
            not appear on the menu display. This is useful for commands which
            need to key sequences. eg. in PipeDream <>TAB is a hidden entry
            which does the same thing as <>CFC, by having the same command
            code. Hidden entries may have Help text, but this text will never
            be displayed. Note: A hidden entry must never be the last in a
            topic. If it is the Help system will not be fully traversable and
            the system will crash if the user moves through help in a certain
            way.

bit 3       set to make safe. Setting this bit forces to use the user to use
            the keyboard sequence rather than selecting the command with the
            highlight bar in the menu display. This is used by the system for
            the Index commands <>KILL and <>PURGE. An attempt to access these
            commands through the highlight bar results in a double bleep. These
            entries should have their command name in tiny text, by convention.
            This has to be done using a token, since control characters will
            terminate a command name.

bit 4       set if command entry has a pointer to a help page.

bit 5-7     should be set to 0
NOTE: The same trick of treating the attribute byte, or high byte of the help pointer as a terminator, can be used in menu entries. The command name terminator simply needs to be in the range ($00 - $1F).

The format of the keyboard sequence is as follows:

For a conventional diamond sequence, simply use the upper case letters of the sequence, eg. for the PipeDream New command the entry would be the following bytes "BNEW" & 0 . For commands using other keys the keyboard decoder codes are used. For example <SHIFT><UP><ARROW> is represented by a key sequence consisting of one byte. IN_SUP ($FB) and the terminator, $00. The system automatically generates the graphic sequence from this code. The menu exceptions, which correspond to the screen driver codes, are:

            Key           Symbol      Code
            <SPACE>       MU_SPC      $E0
            <ENTER>       MU_ENT      $E1
            <TAB>         MU_TAB      $E2
            <DEL>         MU_DEL      $E3
When an application reads the keyboard then valid keyboard sequences are intercepted so instead of returning the raw characters, the routine will return a zero, indicating a command - note this means the NUL can never be read in as a normal character. The next keyboard read will then return the relevant command code as specified in the above definition. One way of dealing with this behaviour is for the user to set up a 'read character' routine which will return normal characters without change, but intercept and obey command sequences. The following code fragment indicates a possible arrangement, although you will need to have read "Error handling and related issues" and "Input and the keyboard decoder" to follow it properly.
.rdch       call_oz(OS_In)            ; perform OS_In
            jr   nc, rdch2            ; if no error, continue
            cp   RC_SUSP              ; check RC_SUSP
            jr   z, rdch              ; and ignore if it occurs
            SCF
            RET                       ; return with system error enabled

.rdch2      or   a                    ; reflect on input
            ret  nz                   ; return if character is not NUL
            call_oz(OS_In)            ; read command code
            or   a                    ; set flags
            ret  z                    ; return if a NUL has been read

            <deal with command code in A>


Help Information

The 'pointer to commands' is of the form of a 2 byte offset in a bank, followed by a bank number. The pointer should point to a series of help page definitions arranged like this:

            x bytes       help page for the application (or 0 for a blank page)
            x bytes       help entry (see below)
            ...
            ...
            x bytes       last help entry
Each help entry will produce one page of help text. It consists of a series of lines, where DEL ($7F) is used for newline, terminated by a NUL ($00). The DEL character is used for newline to facilitate embedding screen driver codes into the help text. For example you can use special keyboard icons, arrow symbols or box characters, eg. for the 'ENTER' icon use the sequence 1 & SD_ENT. The help page is displayed with centred justfification switched on, but you could include a command to switch off centering in your help strings. This should only be done where necessary, to avoid disrupting the overall style of the help pages. The pointer to the help text, which is an offset from the base of the help text, defined in the application DOR, in topic and command entries, should point to the first character of the first line. A help entry might look like this:
.helppage   defm "This is a simple help page" & $7F
            defm "and this is the second line" & 0


Token information

The 'pointer to token base' is of the form of a 2 byte offset in a bank, followed by a bank number. The token table format is shown below.

base        1 byte                    Recursive token boundary (1 - 127)
            1 byte                    Number of tokens (1 - 127)
            2 bytes       first-base  pointer to first token
            2 bytes       second-base pointer to second token
            ...
            ...
            2 bytes       last-base   pointer to last token
            2 bytes       end-base    pointer to byte after nth token

.first      x bytes       defm "xxx"  first string (no terminators)
.second     x bytes       defm "yyy"  second string
            ...
.last       x bytes       defm "zzz"  last string
.end

NOTE: the token table must not be allowed to cross a bank boundary (16K).

Tokens may be embedded in the help text or within the text for topic and command names. The first token has a code of $80 and subsequent tokens count up from here. Recursive tokens may contain tokens in their text. Tokens above the boundary level set by the 'first recursive token' may contain tokens themselves, providing those tokens are below the boundary. The example below is in assembly format to improve clarity:

.tok_base   defb $04                              ; recursive token boundary
            defb $05                              ; number of tokens
            defw tok0 - tok_base
            defw tok1 - tok_base
            defw tok2 - tok_base
            defw tok3 - tok_base
            defw tok4 - tok_base
            defw end - tok_base

.tok0       defm "file"
.tok1       defm " the "
.tok2       defm "EPROM"
.tok3       defb $01, 'T'                         ; Tiny text token
.tok4       defm ' ' & $80 & "s "
.end
 

Information topics

The information topic is selected by pressing <HELP> from within the application. If the topic is present then a menu of commands will be brought up. In an application with no other topics, pressing <MENU> will bring up the information topic name in the topic window. The command entries for an information topic topic differ from ordinary commands in that there is no keyboard sequence associated with them. The command entries should look like this:

a           1 byte        b-a         length byte
            1 byte        0           NULL command code
            1 byte        0           NULL keyboard sequence
            x bytes       'xxxxx'     Command name. The total length of the name
                                      must be 25 characters
            1 byte        0           optional null-terminator
            2 bytes       x x         pointer to help page
            1 byte        x           command attribute byte
            1 byte        b-a         length byte
b

The attribute byte should always be $10 (help page) or $11 (help page and first entry in a new column).
 

Help Front DOR

If the brother link in the application front DOR is not set to zero it is taken as pointing to a help front DOR. The help front DOR looks like this:

3 bytes     0 0 0         Link to parent
3 bytes     0 0 0         Link to brother
3 bytes     x x x         Link to son, this points to the first Help DOR

1 byte      $13           DOR type, application Front DOR
1 byte      8             DOR length

1 byte      'N'           Key for name field
1 byte      5             Length of name and terminator
5 bytes     'HELP', 0     NULL-terminated name
1 byte      $FF           DOR terminator
A help DOR entry looks like an application DOR entry, but without the information record:
3 bytes     0 0 0         Link to parent
3 bytes     x x x         Link to brother (points to another Help DOR or set to
                          zero)
3 bytes     0 0 0         Link to son

1 byte      $83           DOR type, application ROM
1 byte      x             total DOR length
1 byte      'H'           Key to help section
1 byte      x             Length of help section
3 bytes     x x x         Extended pointer to topics
3 bytes     x x x         Extended pointer to commands
3 bytes     x x x         Extended pointer to application help
3 bytes     x x x         Extended pointer to token base.

1 byte      'N'           Key to name section
1 byte      x             Length of name
x bytes     'xxxx',0      Null-terminated application name. Must be the name of
                          an existing application.
1 byte      $FF           DOR terminator byte.
The Help in a Help DOR takes priority over the Help in the application DOR, but for ROM applications it is not necessary to use a separate DOR. The use of the Help DOR is mainly in providing Help for internal applications or applications in other ROM cards. If you intend to provide Help for an internal application you will need to provide all the same command codes for the commands. Therefore, it will be necessary to examine the structure of the intrenal application carefully. This is readily achieved by opening the application with GN_Opf and A = OP_DOR to get a DOR handle, and reading the addresses of the Help structures out of the Help record. The application name can be retrieved by letting FILER provide the filename: try listing all application names with the ":ROM.*//*" wildcard.
 

Limitations and conventions

There are some limitations and conventions regarding menu topics and help; the limitations are:

  1. Diamond sequences should consist of no more than 5 characters, although these may be special characters like arrow keys and Delete.

  2. The first possible match will be selected, so if a diamond sequence 'AB' exists, there is no point having 'ABC' as it cannot be selected.

  3. No command code should be zero, as two zeroes from 'OS_In' are used to represent NUL. Note also that the <SPACE>, <TAB>, <ENTER> and the arrow keys all return command codes and you must make sure you do not clash with these. See "Input and the Keyboard Decoder" for details of these codes.

  4. There should be no more than 7 topics per application and no more than 24 commands per topic. Each command name should consist of no more than 25 characters.

  5. If any commands in a topic have help, then it is strongly recommended that all the topics have help, even if this is just a blank page (set the help pointer to point to a NUL) and the topic itself must have help.

  6.  
The conventions, we recommend you subscribe to, are:
  1. Make the first letter of a diamond sequence the first letter of the topic name (eg. PipeDream has BNEW in the Blocks topic).

  2. If topic names coincide with the internal ones, then the order should be the same, eg. 'CURSOR' before 'FILES'.

  3. Commands associated with the arrow keys should be in the order: Right, Left, Up and Down.

  4.  
Bad Applications

An application can be made 'bad' (or a popdown 'ugly') if it requires a large area of contiguous memory since the Z88 cannot allocate more than 256 bytes to an application at any time. Although this appears to be very restrictive, most programs can be made to work under this regime. All the internal applications, bar BBC BASIC, are 'good', and BBC BASIC is only bad because it was not written for the Z88 but simply imported. If, however, you are simply unable to write an application without large contiguous areas, you may have to make your application bad. Similarly if your application is intended to be the only one running on the Z88, there is no problem with it being bad.

Bad application memory is provided from address $2000 onwards. The amount given depends on the value of the 'Contiguous RAM size' byte in the application DOR header. This byte should be set to the number of 256 byte pages required. If it is set to zero then the default value is used (40K in an expanded machine, 8K in an unexpanded machine). The value of the defualt can be changed, via the PANEL, but bear in mind this is something which affects the whole system, and should not be undertaken lightly. When a bad application is first entered, the IX register points to an information block as follows:

            1 byte        $03         Number of information bytes
            1 byte        x           Start page of contiguous memory, $20
            1 byte        x           End page of contiguous memory, this cannot
                                      be used, for example $C0 for a 40K bad
                                      application.
            1 byte        x           Ususally zero. Reserved for future
                                      expansion.
Whenever BBC BASIC is exited an area of unused memory, between the program and the stack, is given back to the system. When BBC BASC is re-entered memory is found to fill this hole back up again. It is this mechanism that allows several 40K BBC BASIC's to co-exist on a 128K Z88 computer. All the BBC BASIC's have a 40K contiguous space while they are active and running, but when inactive (pre-empted) they occupy considerably less memory. To give memory back to the system, the enquiry entry point is used. The enquiry entry point is three bytes above the application entry point and must be in segment 3, which effectively forces all entry points into segment 3. Normally the enquiry entry point should simply return with Fc = 1. However, if Fc = 0 the memory starting from the address specified in register BC and ending at the address specified in register DE (not including the byte at (DE)) is given back to the system. The following code might be used:
.app_entry                jp   main_entry         ; JP instruction 3 bytes long
.app_enquiry              ld   bc, (hole_start)   ; enquiry entry point
                          ld   de, (hole_end)
                          or   a                  ; Fc = 0
                          ret
Bad applications not giving memory back to the system (and all other application) should use the following code for the enquiry entry point:
.app_entry                jp   main_entry
.app_enquiry              scf                     ; enquiry entry point
                          ret
InterLogic comment: We've had no problems with good applications & popdowns that ignores the above <SCF> header, even though the original documentation explicitly specifies it to be coded.

Bad applications place a lot of strain on the system, by using large areas of memory. A 40K bad application which gives no memory back to the system is unlikely to co-exist well with other applications, so it is strongly recommended that if you must write bad applications you give memory back to the system. It is almost always possible to design data structures so that a contiguous block can be kept empty. Programmer laziness is not an excuse to use a 40K bad application by default!
 

Mailboxes

The Z88 provides a facility for applications to pass on information to the next application started up. This is used by PipeDream and the Diary to read the name of a marked file from the Filer. The way this works is that the Filer drops the address and length of the name of the last marked file into a mailbox from time to time. When the Filer is exited (eg. by pressing <ESC>) the system looks at the mailbox and if there is something there, it copies the information to a safe area of memory. When another application is started it can ask the system if there is any mail. All mail is tagged by an name, which describes the type of information, and an application must give the system the name of the information it is after. If information is present then the system copies it from the safe area into the bottom stack area of the application's memory. The interface for mailboxing is provided by the OS_Sr call with the reason codes SR_WPD (write parameter data) and OS_RPD (read parameter data). See OS_Sr reference for details of parameter specification.

The system uses two information types; filenames and dates. These have the information type names of "NAME" and "DATE", both null-terminated. If you transfer information of one of these types, then you must use the appropriate name, otherwise the internal appliations will not be able to collect your mail. Similarly you won't be able to receive mail from the Filer, Calendar, Diary, etc., unless you try and read mail with these names. If you do use the mail system please inform the programmers in your documentation of the information type name you use (which should be a mnemonic upper case alpha string), so other applications can share data with yours. The internal applications use mail as follows:

            Filer         exports filenames
            Diary         imports filenames, imports dates, exports dates
            PipeDream     imports filenames
            Calendar      imports dates, exports dates
            Alarm         imports dates
The mailboxing system can be seen in operation using PipeDream and the Filer. Use <>FL from PipeDream and enter the Filer from this menu. Mark a file (eg. with <TAB>) and press <ESC> to return to PipeDream. The marked file will then be copied into the 'Name of file to load' field. Similarly selecting the Diary from the Calendar will set the Diary date to the date which was highlighted by the Calendar. When you go to the Calendar from the Diary, the Calendar moves to the Diary date.
 

Environment on entry to an application

When you enter an application the stack pointer is established and you will have a stack space of the order of 1.5K. The memory used for the stack is a shared resource, however. The 2K space between address $1800 and address $2000 is used for the following purpose:

  1. As the system stack. This will usually be quite lightly used, but can be quite big in some circumstances.

  2. For the safe and unsafe workspace which applications request. The bigger these are, the less stack you will have.

  3. For storing mailbox information between application switches. If a lot of lengthy mail is being passed around, the maximum stack size is reduced. We recommend that mail is restricted to a maximum of 64 bytes.
The stack space looks like this:
 
$2000       +------------------+
            | System use       |
            |------------------|
$1FFD       | Unsafe workspace |
            |------------------|
            | Safe workspace   |
            |------------------|
            | Stack pointer    |
            |------------------|
            |                  |
            | Stack expands    |
            | downwards...     |
            |                  |
            |------------------|
            | Mailbox data     |
$1800       | from here...     |
            |------------------|
$17FF       | System use       |
            ...
            ...
$0000       +------------------+
Even with all these demands it is unlikely that you will have much less than 1.5K to use for the stack, but clearly if you might need more space you will need to make your own arrangements, such as allocating memory and implementing you own stack procedures, or if really necessary using a bad application to provide contiguous memory for a stack.

If you change the stack pointer within your application you must save the old stack pointer and restore it (below $2000 in segment 0) before making any system calls. This is because system calls swap memory banks during execution; the stack may get 'paged' out and a system crash would then most likely occur.

If your applications requires access to other banks in your card then you can use the bank switching call, OS_Mpb, to bind them in. However, your card could be placed in any of the three slots so you need to determine where your card is. This can simply be done by using OS_Mgb while running ROM'ed code and then using bank offsets relative to this value.


Previous Contents Next
Interfacing with the system Application Static Structures Error handling and related issues