|Z88 Developers' Notes|
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.
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 applicationsThe 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 terminatorThe 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.
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 markerWhere 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 byteb
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 0The 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.
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 topicsEach 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 byteb
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 0NOTE: 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 $E3When 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>
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 entryEach 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
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
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 byteb
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 terminatorA 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:
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 retBad 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 retInterLogic 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!
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 datesThe 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:
$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.
|Interfacing with the system||Application Static Structures||Error handling and related issues|