Open the .CONSOLE device, the Console Driver sets the boundaries of the text port to the full 80-column text screen; you can change the boundaries with a control code. The text port keeps track of all important screen-related parameters, including the dimensions of the text port, the cursor position, and the settings of various cursor movement parameters. The cursor position marks where the Console Driver will display the next outputted character. It is set to the top left-hand corner of the text port when you first open the CONSOLE device. To display a character on the screen, use the GS/OS Write command to send the character code to the Console Driver. Table 9-1 indicates these character codes in both normal and inverse modes. (In normal mode, the characters are white, and the background is black; in inverse mode, the characters are black, and the background is white. If MouseText mapping is enabled, MouseText symbols appear instead of inverse uppercase characters.) Notice that you can display inverse characters and MouseText symbols without explicitly enabling inverse mode or MouseText mapping. Just send character codes with the high-order bit set to 1. Control Commands As Table 9-1 indicates, the codes from $00 to $1F do not correspond to visible screen characters. Instead, they represent commands to the Console Driver to perform special screen-related tasks such as clearing portions of the text port, positioning the cursor, scrolling the text port, and enabling MouseText mapping. Table 9-2 gives a complete list of these commands. Many of the commands in Table 9-2 simply involve sending the corresponding code through the output stream. But some require you to follow the code with one or more data bytes. In general, the values of these data bytes are 32 higher than the value you are trying to set. Some of the commands in Table 9-2 refer to global flags in the text port record called cons - DLE, cons - scroll, cons - wrap, cons - LF, and cons - advance. The settings of these variables govern how some cursor movement and scrolling operations are to be performed. To set these flags, use the Set Cursor Movement command (control code $15). Multiple Windows The Console Driver facilitates the development of multiwindow text-screen applica- tions because it has commands for saving and restoring a text port. To create a second text port, for example, use the Push and Reset Text Port ($01) command; then set the dimensions and characteristics of the new text port. To switch back to the original text port, use the Pop Text Port ($04) command. If the text ports overlap, you must also save and restore the screen data for the text port that is about to be inactivated. You can do this with the Return Text Port Data subcommand of the CS/OS DStatus command. To put the data back in the text port, Video Output 337 Table 9-1 Character codes used by the Console Driven $00-$1F $20-$3F $4~$5F $6~$7F $8~$9F $A~$RF $C~$DF $E~$I'F N0TES: Control commands Inverse symbols, digits ($2~ Inverse uppercase ($~$1F)C Inverse lowercase ($~$7F) Normal uppercase ($8~$9F) Normal symbols, digits ($A~ Normal uppercase ($C~$DF) Normal lowercase ($E~$FF) Control commands Normal symbols, digits ($A~RF)h Normal uppercase ($8~$9F) Normal lowercase ($E~$FF) Inverse uppercase ($~$1F) Inverse symbols, digits ($2~$3E) MouseText symbols ($4~$5I') Inverse lowercase ($~7F) aThe exact sequence of characters fom $20 to $7F is the same as the sequence dehned by the ASCII ~e numbers in parentheses indicate the values the Console lDriver actually stores in the video RAM cWhen MouseText mapping is on, MouseText symbols appear for character codes $4~$5F in invcrse mode instead of inverse uppercase characters. use the Restore Text Port Data subcommand of the GS/OS DControl command. Tz subcommands are described in the next section. DEVICE COMMANDS In this section, we summarize the DControl and DStatus subcommands you use communicate with the Console Driver. As we mentioned, these subcommands are r setting up the character input/output environment and returning status information. DControl and DStatus may return two possible errors: $22 bad driver parameter $23 the Console Driver is not open DControl returns error $22 if the amount of data in the control list (request-count bytes) is not enough for the requested operation. DStatus returns error $22 if the status list buffer isn't large enough to hold all the data the operation needs to return. DControl Subcommands Recall from Chapter 4 that one parameter in the DControl parameter list is control - code, a numeric code describing the type of control operation a device driver is to perform. Other important parameters are control - list, a pointer to a control list buffer 338 GS/OS Character Devi"es Table 9-2 The Console Driver's video output commands Command Code Command Description $00 Null. This command does nothing. $01 Push and Reset Text Port. This command saves the current text port and then sets the text port to its default state. $02 Set Text Port Size. This command sets the boundaries of the current text port. It must be followed by four parameters: window left + 32, window top + 32, window right + 32, and window bottom + 32 (in that order). The values of the parameters are relative to the full hard- ware screen and numbering begins with $00. $03 Clear from Beginning of Line. This command erases all characters from the left edge of the current line in the text port up to and in- cluding the character beneath the cursor. $04 Pop Text Port. This command restores the text port saved by Push and Reset Text Port (command $01) and makes it the current text port. $05 Horizontal Scroll. This command shifts the contents of a text port left or right and erases the vacated space. It must be followed by a signed byte describing the direction and extent of the shift: if negative, the shift is to the left; if positive, the shift is to the right. The absolute value of the byte gives the number of columns to shift. $06 Set Vertical Position. This command sets the vertical position of the cursor within the text port. It must be followed by a byte describing the vertical position + 32. $07 Ring Bell. This command beeps the speaker. $08 Backspace. This command moves the cursor one position to the left. If the cursor is already at the left edge of the text port, and cons -wrap is true, it moves to the end of the previous line. If it is at the top left-- hand corner of the text port and cons _ scroll is also true, the text port scrolls backward one line. $09 Null. This command does nothing. $0A Line Feed. This command moves the cursor one line down in the text port without affecting the column position. If the cursor is on the last line of the text port, and cons - scroll is true, the text port scrolls up one line. $0B Clear to End of Text Port. This command erases the characters from the current cursor position to the end of the text port. Device Commands 339 Table 9-2 Continued Command Code Command Description $0C Clear Text Port and Home Cursor. This command erases the entire text port and puts the cursor in the top left-hand corner. $0D Carriage Return. This command moves the cursor to the left edge of the current line in the text port. If cons - LF is true, a line feed operation ($0A) automatically follows. $0E Set Normal Display Mode. This command forces subsequently out- putted characters to be displayed in normal mode. $0F Set Inverse Display Mode. This command forces subsequently out- putted characters to be displayed in inverse mode. $10 DLE Space Expansion. This command is for outputting a sequence of space characters very quickly. If cons - DLE is trne, this command must be followed by a byte containing the number of space characters + 32 to be displayed. If cons - DLE is false, the next byte is ignored, and no space characters are displayed. $11 Set 40-Column Mode. This command turns on the 40-column display mode hardware. $12 Set 80-Column Mode. This command turns on the 80-column display mode hardware. $13 Clear From Beginning of Text Port. This command erases all charac- ters from the beginning of the text port up to and including the character beneath the cursor. $14 Set Horizontal Position. This command sets the horizontal position of the cursor within the text port. It must be followed by a byte describ- ing the horizontal position + 32. $15 Set Cursor Movement. This command sets the cursor movement flags, which are arranged as follows in the byte: 7 6 $ 4 3 2 1 0 bit 4 1 = cons - DLE is true (DLE space expansion can occur) bit 3 1 = cons - scroll is true (text port scrolls if the cursor moves up when on the first line or down when on the last line) 340 G5/OS Character Devices Table 9-2 Continued bit 2 1 = cons wrap is true (cursor moves past the end of a line to the next line) bit 1 1 = consLF is true (carriage return is followed by a line feed) bit 0 1 = cons - advance is true (cursor moves one space to the right after printing a character) Many video output commands check these flags to determine how to behave when certain cursor movement operations are requested. The default settings for all these flags is true. $16 Scroll Down One Line. This command scrolls the text port down one line. The cursor stays put. $17 Scroll Up One Line. This command scrolls the text port up one line. The cursor stays put. $18 Disable MouseText Mapping. This command turns off the conversion of inverse uppercase characters to MouseText icons. $19 Home Cursor. This command moves the cursor to the top left-hand corner of the current text port. $1A Clear Line. This command erases the line in the text port that the cursor is on. $1B Enable MouseText Mapping. This command enables the conversion of inverse uppercase characters to MouseText icons. $1C Move Cursor Right. This command moves the cursor one position to the right. If the cursor is on the right edge of the text port, and cons - wrap is true, the cursor moves to the beginning of the next line. If cons - scroll is also true, and the cursor is on the right edge of the last line, the text port scrolls up one line. $1D Clear to End of Line. This command erases all characters from the current cursor position to the end of the current line. $1E CotoXY. This command positions the cursor within the current text port. It must be followed by bytes describing the horizontal position + 32 and the vertical position + 32. $1F Move Cursor Up. This command moves the cursor up one line without affecting the horizontal position. If the cursor is on the top line of the text port, and cons - scroll is true, the text port scrolls up one line. Device Commands 341 containing the data the control operation needs, and request - count, the size of the control list buffer. We describe each of the important contoolcode operations in the following paragraphs: Set Wait/No-Wait Mode (code $0004). Use this command to set up wait mode or no-wait mode befure commencing a Read operation. Put $0000 in the control list for wait mode or $8000 for no-wait mode. The setting of the wait/no-wait flag is irrelevant as far as UIR operations are concerned because the UIR always operates in wait mode. The request - count is always 2. Set Input Port (code $8000). Use this command to set the input port to a given state. A copy of the input port record must be in the control list, and the requestcount is always 17. Set Ter'ininator est (code $8001). Use this command to set up the terminator list for the Read command to use. The terminator list must be in the control list; it begins with a mask word and a terminator count word, fnllowed by the terminator words (if any). The requestcount must be equal to 4 + 2 X (terminator count). Restore Text Port Data (code $8002) Use this command to copy the video data in the control list to the current text port. The data in the control list is in the same format used by the Save Text Port Data DStatus command: port width byte, port length byte, fullowed by the video bytes for each line in the text port. The request - count for a full 80 by 24 screen is 1922(2 + 80 X 24). Set Read Mode (code $8003). Use this command to select between raw mode and UIR mode. Put $0000 in the control list for UIR mode or $8000 for raw mode. The request - count is always 2. Set Default String (code $8004). Use this command to set up the default string to be used by the UIR. Put the string in the control list and the length in the request count field. If you don't want a default string, set the length to zero. The default string cannot exceed 254 characters. Abort Input (code $8005). Use this command to cancel an input operation that is in progress. If you don't, the next Read command will pick up from where the last one left off. The request - count is always 0. DStatus Subcommands The GS/OS DStatus command uses a status - code parameter describing the nature of the status operation to be performed. A DStatus command returns data in a status - list buffer specified by the application; the number of bytes returned comes back in 342 GS/OS Character Devices the transfcrcount field. Before using the DStatus command, make sure the size of the status list buffer (the value in the request - count field) is large enough for the expected transfer - count. We describe each of the important status - code operations in the fullowing paragraphs: Return Wait/No-Wait Mode (code $0002). This command returns the current Read mode in the status list. Wait mode is active if the result is $0000, and no-wait mode is active if the result is $8000. UIR operations always use wait mode, notwithstanding the status of the wait/no-wait flag, however. The transfer - count is 2. Return Text Port (code $8000). This command returns a copy of the current text port record in the status list. The transfer - count is 16. Return Input Port (code $8001). This command returns a copy of the current input port record in the status list. The translercount is 17. Return Ter'tninator List (code $8002). This command returns a copy of the current terminator list in the status list. The terminator list begins with a terminator mask (word) and a terminator count word, followed by the terminator words (if any). The transfer - count is 4 + 2 X (terminator count). Return Text Port Data (code $8003). This command returns in the status list a copy of the characters that appear in the active text port. The returned data begins with a port width byte and a port length byte and is followed by the screen bytes for each line of the text port. The transfer - count for the full 80 by 24 text screen is 1922(2 + 80 X 24). Return Screen Character (code $8004). This command returns in the status list the screen byte for the character beneath the current cursor position. The screen byte is the value actually stored in video RAM to display the character, not the character code (see Table 9-1). The transfer count is 1. Return Read Mode (code $8005). This command returns the read mode flag in the status list. The result is $0000 if UIR is active and $8000 if raw mode is active. The transfer count is 2. Return Default String (code $8006). This command returns the current default input string in the status list. The maximum transfer - count is 254. CONSOLE DRIVER PROGRAMMING EXAMPLE The program in Table 9-3 illustrates many of the programming techniques you will use when working with the Console Driver. It prompts the user to enter a name and Console Driver Programming Example 343 uses the UIR to handle the response. The terminator list includes two interrupt keys (z-? and z-/) that the program responds to by displaying a dummy help screen, asking the user to press Return to continue, and then returning to the initial Read command to get the rest of the name input. The program ends when the user presses Return or Esc (two other terminator characters) while entering a name. After you assemble the program with the APW assembler, change its file type to 516 (GS/OS system file) before running it. You can do this with the FILETYPE command. The program first calls GetDevNumber to determine the device number for the .CON SOLE device. It stores this number in the parameter tables for all the DControl and DStatus commands the program uses. The program then calls Open to enable access to the Console Driver and copies the reference number Open returns to the necessary parameter tables. Next, the program calls DStatus to return two copies of the default input port. The first copy is used in the DoHelp subroutine. The second copy is the one the main Read command uses, but before the program calls Read, it changes the fill - char field of the input port to $C9 (the code for the MouseText underscore symbol). A call to DControl tells the Console Driver about the change. The last three preliminary steps are to use DControl to set up the default input string (to John Q. Public), set up the terminator list, and enable UIR mode. (Re- member, the default is raw mode.) Four terminator characters are placed in the terminator list: Return, Esc, z-?, and * -/. Return and Esc are ordinary terminators, whereas z-? and * -/ are interrupt terminators. (Bit 13 of the terminator modifier word is set to 1.) Notice that the terminator mask (in the DC - Parms1 parameter table) is set to $A0FF so that only the Open-Apple and interrupt modifier bits (and the ASCII character code) will be significant. The Write command clears the screen, positions the cursor on the middle line, and displays the "Enter your name: "prompt. The program calls the Read command to begin processing user input. On exit, it calls DStatus to retrieve a copy of the current input port so that the exit - type field can be inspected. If exit - type is 3 or 4, a Help key (* -? or *-/) was pressed, and control branches to DoHelp. Any other exit must have been caused by the user pressing Return or Esc, so the program calls the Close command and ends. Since the DoHelp subroutine uses video output and keyboard input commands, it must be sure to preserve the Console Driver's status quo. It uses DStatus to save the data in the text port (the characters on the screen) and uses Write to save the text port record by sending the $01 command just before the help message. The program saves the state of the input operation in progress by saving a copy of the current input port. It then sets up a default input port before calling the Read command to wait for a Return keypress. (In a more general application, the read mode, terminator list, and default string would be saved too.) On return, the input and text ports are restored, as are the data in the text port, and the default string. Control then returns to the main Read command so that the user can finishing entering the name. 344 GS/OS Character Devices Table 9-3 This program shows how to use the GS/OS Console Driver * Console Driver Exerciser ~ * * Copyright 1988 Gary B. Little ~ * * Last modified: September 4, 1988 * KEEP CONSOLE Object code file NCOPY CONSOLE.NAC ;Nacro file Console START PHK PLB _GetDevNrnmber GDN_Parms LDA dev_nrnm STA dev_nrnml STA dev_nrnm2 STA dev_num3 STA devnrnm4 STA dev_nrnmS STA dev_nrnm6 STA dev_nrnm7 Open OpenParms LDA ref_nrnm STA ref_numl STA ref_nrnm2 STA ref_num3 STA ref_num4 STA ref_numS STA ref_num6 LDA #$8OO1 STA 1P_Cmd _DStatrns IP_Parms Get copy of std input port LDA #$8OO1 STA 1P_Cmdl _DStatus 1P_Parmsl ;Get input port * Make changes to the default port: SEP #$2O Console Driver Programming Example 345 Table 9-3 Continued LDA #$C9 New FillChar STA InputRecl+O REP #$2O LONGA ON LDA #$8OOO STA 1P_Cmdl _DControl 1P_Parmsl Set new input port DControl DS_Parms _DControl DC_Parmsl _DControl DC_Parms2 _Write WrParms1 _Read Read_Parms LDA #$8OO1 STA IP_Cmdl _DStatus 1P_Parmsl LDA 1nputRec1+S AND #$OOFF CNP #3 BEQ Dottelp CNP #4 BEQ DoHelp _Close Close_Parms Quit Quit_Parms BRK $00 GetInput Set default string Set terminator list Set U1R mode Set up prompt ;Get input port Exit_type ;Terminator #3? ;Terminator #4? * Here is where we display a help screen and wait for * any key to continue. We must preserve the text port, * the text port data, and the input record. DoHelp ANOP LDA #$8OO3 STA TP_Cmd _DStatus TPParms Write Wr_Parms2 346 GS/OS Character Devices Save text port data ;Push port, display help screen Table 9-3 Continued LDA #$8OO1 STA 1P_Cmd1 DStatus 1P_Parms1 ;Get current input port LDA #$8OOO STA 1PCmd _DControl 1PParms Set up a virgin input port _DControl DSParmsl Set default string to null _Read OneByte LDA #$8OOO STA 1P_Cmdl DControl 1P_Parmsl ;Restore input port _DControl DS_Parms Restore default string Write Wr_Parms3 ;Pop text port LDA #$8OO2 STA TP_Cmd _DControl lPParms Restore text port data JNP GetInput ;Get rest of input Quit_Parms ANOP DC 12'2' DC 14'O' DC 12'O' Open_Parms ANOP DC 12'2' ref_num DS 2 ;Reference number returned here DC 14'Cons_Name' Cons_Name DC 12'8' ;Length word DC C'.CONSOLE' Read_Parms ANOP DC 12'4' ref_num2 DS 2 DC 14'Buffer' DC I4'3O' Request count rd_count DS 4 ;Actual count Buffer DS 30 Console Driver Programming Example 347 Table 9-3 Continued * Parameter table for reading one character: OneByte ANOP DC 12'4' ref_num$ DS 2 DC 14'TheChar' DC 14'1' Request count DS 4 TheChar DS 1 WrParmsl ANOP DC 12'4' refnum3 DS 2 DC 14'Scr_1nit' DC 14'Nsg_Len-Scr1nit' DS 4 5cr_1nit ANOP DC 11'$OC' ;Clear screen DC 11'$1E,$2O,$2C' Move to row 12, column 0 DC CEnter your name: NsgLen ANOP Wr_Parms2 ANOP DC 12'4' ref_num4 DS 2 DC 14'Scr_Help' DC 14'Hsg_Lenl-Scr_Help' DS 4 5cr_Help ANOP DC 11'$O1' ;Push and reset text port DC 11'$OC' Clear screen DC DC DC Nsg_Lenl ANOP Wr_Parms3 ANOP DC refnum6 DS DC DC DS PopTP DC DC 11'$1E,$2A,$2C' C'This is a help screen'.' 11'$1E,$2O,$37' Move to row 23, column 0 C'Press Return to continue: 12'4' 2 14'PopTP' 14' 1' 4 11'$O4' ;Pop text port Move to row 12, column 10 348 GS/OS Character Devices Table 9-3 Continued CloseParms ANOP DC 12' 1' ref_numl DS 2 GDN_Parms ANOP DC 12'2' DC 14'Cons_Name' dev_num DS 2 * Parameter table for setting the * default input string: DS_Parms ANOP DC 12'S' dev_numl DS 2 DC 12'$8OO4' DC 14'Def_Name DC 14'Size-Def_Name' ;Length of list DS 4 DefName DC C'John Q. Public' Size ANOP DS_Parmsl ANOP DC 12'S' dev_num7 DS 2 DC 12'$8OO4' DC 14'Def_Name' DC 14'O' ,No default DS 4 DC_Parmsl ANOP DC 12'S' devnum2 DS 2 DC 12'$8OO1' Set terminator list DC 14'TermList' DC 14'Sizel-TermList' Length of list DS 4 TermList DC 12'$AOFF' ;Terminator mask DC 12'4' ,Count DC 12'$OOOD' Return DC 12'$OO1B' ;Esc DC 12'$AO3F' 0A-? (interrupt) DC 12'$AO2F' 0A-1 (interrupt) Sizel AN0P DC_Parms2 AN0P Console Driver Programming Example 349 Table 9-3 Continued DC 12'$8003' Set read mode DC 14'RN_List' DC 14'2' Length of list DS 4 RN_List DC 12'$0000' ;U1R 1PParns ANOP DC 12'S' devnumS DS 2 * 1P_Cmd = $8001 (return input port) for DStatus * 1P_Cmd = $8000 (set input port) for DControl 1P_Cmd DS 2 Return/set input port DC 14'1nputRec' DC 14'1PR_Size-1nputRec' DS 4 Input_Rec 1PR_Size 1P_Parmsl dev_num4 DS 17 Space for input port record ANOP ANOP DC 12'S' DS 2 * 1P_Cmd = $8001 (return input port) for DStatus * 1P_Cmd = $8000 (set input port) for DControl 1PCmd1 DS 2 Return/set input port 14'1nputRec1' 14'IPR_Size1-InputRec1' 4 _ 17 Space for input port record DC z DC DS Input_Recl DS IPR_Size1 AN0P ******************************************** * Parameter table for saving and restoring * the data in the text port. TP_Parms ANOP DC 12'S' dev_num6 DS 2 350 GS/OS Character Devices Table 9-3 Continued DC 14'TP_Len-TextPort' DS 4 TextPort DS 80*24+2 TP_Len ANOP END Console Driver Programming Example 351 APPEND~ I Assem Two assemblers were used to create the assembly-language example programs in this book. Merlin 8/16 (Roger Wagner Publishing, 1050 Pioneer Way, Suite P, El Cajon, CA 92020, 619/442-0522) was used for the ProDOS 8 programs, and the Apple Programmers Workshop (APW) assembler (APDA, Mail Stop 33-C, 20525 Mariani Avenue, Cupertino, CA 95014,800/282-2732) was used for the CS/OS programs. The reason for using two different assemblers is primarily historical. Merlin 8/16 (previously called Merlin Pro) is probably the most popular assembler available for creating ProDOS 8 applications primarily because it was introduced soon after Apple first released ProDOS 8. Similarly, the APW assembler is the most popular assembler for creating CS/OS applications because it was the only 65816 assembler available when the Apple LEGS came out, and its linker can create CS/OS load files. Even though the current version of Merlin 8/16 now has a linker for creating CS/OS load files, most programmers are more familiar with the APW assembler, so that's the one used for the CS/OS examples. If you want to modifc and reassemble the example programs, and you are not using the same assembler, you may have to make changes to the source code to resolve any differences in syntax and command structure. Differences usually arise in the area of pseudo-instructions; these are commands to the assembler that appear in the instruc- tion field of a line of source code. They can be used to place data bytes at specific locations within the program, to define symbolic labels, to indicate the starting address of the program, and for several other purposes. MERLIN 8/16 Here are the meanings of some of Merlin 8/16's most important pseudo-opcodes: DFB $03 Stores the byte $03 in the object code. 353 DS 16 DA $FDED ADRL $E10OA8 ASC 'ABCD' ASC "ABCD" C0UT EQU $FDED 0RG $0300 STR 'string' Reserves a data space of 16 bytes (to no particular value). Stores the address $FDED in the object code as $ED $FD (that is, low-order byte first). Stores the 65816 long address $E100A8 in the object code as $A8 $00 $E1 $00 (that is, low-order byte first). Stores the ASC11 codes for ABCD in the object code (with bit 7 cleared to 0). Stores the ASC11 codes for ABCD in the object code (with bit 7 set to 1). Equates the symbolic label C0UT with the address $FDED. Instructs the assembler to start assembling the code beginning at $300. Stores the ASC11 codes for the string, preceded by a length byte. The operand formats for most ProDOS 8 assemblers like Merlin 8/16 are generally quite similar. (The opcrand is the part that identifies what data or address an instruc- tion is to act on.) One major difference is the way in which the high- or low-order byte of a 2-byte address is identified as an immediate quantity. With Merlin 8/16, you use an operand of the form #
Address to identify the high-order byte, where Address is the address being examined. Most other assemblers use quite a different method, the most common of which is to use #Address to identifi' the low-order byte and /Address to identify the high-order byte. One assembler, Apple's 6502 Editor/Assembler, uses the same general method, but it reverses the meaning: #> identifies the low-order byte, and # < identifies the high-order byte! Be careful. APW ASSEMBLER Here are the meanings of some of the APW assembler's most important pseudo-opcodes: DC 11 '$03' DS 16 DC 12'$FDED' DC I4'$E100A8' 354 Using Assemblers Stores the byte $03 in the object code. Reserves a data space of 16 bytes (to no particular value). Stores the address $FDED in the object code as $ED $FD (that is, low-order byte first). Stores the 65816 long address $E100A8 in the object code as $A8 $00 $E1 $00 (that is, low-order byte first). DC C'ABCD' Stores the ASC11 codes for ABCD in the object code. By default, the codes are stored with the high-order bit off; you can use the ffiSB ON directive if you want them stored with the high-order bit on. C0UT GEQU $FDED Equates the symbolic label COUT with the address $FDED. The APW assembler permits you to create macros - assembler directives that expand into a series of 65816 instructions. APW comes with a standard set of macros for all CS/OS commands and IIcs tool set functions. The macro name is the same as the command or tool set name except that it begins with an underscore character (). The CS/OS macros require one parameter, the address of the parameter table for the CS/OS command. By using these standard macros, you don't have to memorize CS/OS command num- bers or tool set function numbers. It also makes your source code easier to understand. Here are five other macros some of the examples use: STR Stores an ASC11 string preceded by a length byte. STR1 Stores an ASC11 string preceded by a length word. PushPtr Pushes the address of a data area on the stack. PushWord Pushes a word on the stack. PushLong Pushes a long word on the stack. To use a macro, put its name in the assembler's instruction field. If the macro has a parameter, put it in the operand field. When the source code file is assembled, the 65816 instrnctions that the macro defines are placed in the object code. APW Assembler 355