------------------------------------- Turbo Macro Pro, General Overview ------------------------------------- The Turbo Macro Pro (TMP) toolset consists of several different but very similar versions, each one made for a specific machine/hardware config. The tools in the current release of TMP are: TMP v1.2 - for c64 with no REU expander. TMP+REU v1.2 - for c64 with an REU (1764, 1700, 1750), which offers 128k, 256k, or 512k of extra himem. JB REU v1.1 - emergency jumpbacker for REU/R2 source re-entry TMP(x2) v1.2 - for a dual c64 system where coding occurs on one machine, and assembled data is transmitted over a custom cable to a second machine for execution. TMP(r2) v1.2 - for a dual c64 system where the coding machine also has an REU (this merges the REU and X2 mods). TMP+DTV v1.2 - for the DTV joystick system which offers an extra 64k bank of himem. JB DTV v1.1 - emergency jumpbacker for DTV source re-entry TMP+PTV v1.2 - for the PAL DTV (PTV for short) and Hummer which offers an extra 2 megs of himem (only the top 512k are used by TMP). JB PTV v1.1 - emergency jumpbacker for PTV source re-entry TMPPREFS V1.2 - preferences editor for altering and saving a customized TMP v1.2 binary. The tools also work on a c128, in c64 mode of course. In addition to the actual assembler tools, there is also an emergency restore tool for each different configuration of extra memory. These tool are called 'jumpbackers' - they enable the user to detect existing instances of TMP in the extra memory banks of the REU, DTV, or PTV and retrieve that back into the c64's main memory, effectively re-entering the tool where it was last left off. The jumpbacker can be used in cases where a user is executing assembled code and the c64 main memory becomes corrupted or otherwise, preventing any built-in jumpback routine from working. See below for a more detailed explanation of how this fits in with the extra memory features of TMP. Each version of TMP is entered in the same way, by jmp'ing to $8000 from inside a monitor or toolcart (e.g. Super Snapshot) or by executing from BASIC using 'sys 8*4096'. This starts the TMP program, which initializes various things and places you directly into the interactive editor. One important feature of TMP (and all versions of TA/TAM) is that re-entrance into the program does not initialize or erase your source code data; you can exit and re-enter the program multiple times and each time you are back to where you left off within the source code. ------------------------------------- Turbo Macro Pro, Extra RAM Concepts ------------------------------------- While TMP offers a number of additonal features and bug fixes against the OriTAM, the most vital to understand is how TMP handles extra memory in the REU, R2, DTV, and PTV mods. Each of these mods adopts a 'bank' concept which treats the extra RAM as one or more 64k banks. TMP then assigns to each bank some role in the code-test-code cycle. These roles are: Assembly: the assembly bank is where assembled code (the machine code output from the assembler) is placed. Object : the object bank is a non-volatile storage bank for additional binary object data, such as data tables, bitmaps, or even pre-assembled code libraries. When a separate object bank is used, TMP will copy it into the assembly bank *prior* to assembling. The use of an object bank therefore allows a user to preload all the binary data necessary only one time, and then code and test repeatedly without having to reload the binary data each time. Source : a source bank holds a complete instance of the TMP program with one specific source code. TMP allows a quick way to swap between source banks, effectively changing the source code that is currently active and editable. Hardware configurations with 512k of extra RAM actually allow six (6) separate source codes to remain resident in memory at a time. Only one is active (in the c64's main memory) at any given moment. Whatever source code is currently active is the one that will be assembled to the assembly bank. Once a source code is assembled the user is prompted to execute the code, and if they do, TMP swaps the assembly bank into the c64 main memory while the active source code is swapped out to the assembly bank. At that moment there are actually two identical copies of the source code in himem - one in the assembly bank and one in whatever source bank it was originally assigned to. After this swap, the assembled code is executed. TMP will by default store a short routine in memory which can be jmp'd to and which will re-swap the assembly bank back into c64 main memory and re-enter TMP, returning to the code editor where it was left off prior to assembling. There are typically 4 different extra memory size configurations: 64k: Effective in the DTV mod. Because there is only one bank available, TMP treats it as a combined assembly/object bank. It is not possible to store and swap between other source codes, and obviously the object data is not separated into it's own non-volatile bank; but the extra bank still enables a rapid code-test-code cycle at least without being required to reload the assembler and code after each test run. 128k: Effective in the REU mod. Bank 0 is used as the assembly bank and bank 1 is used as the object bank. It is not possible to store and swap between other source codes, but the object data remains uncorrupted after each test run. 256k: Effective in the REU mod. Bank 0 is the assembly bank. Bank 1 is the default object bank but this can be altered to any bank 1-3. There are two extra banks available to hold up to two different source codes at once. 512k: Effective in the REU and PTV mods. Bank 0 is the assembly bank. Bank 1 is the default object bank but can be altered to any bank 1-7. There are six extra banks available to hold up to six different source codes at once. ------------------------------------- Turbo Macro Pro, Dual c64 Concepts ------------------------------------- Our X2/R2 mods function essentially the same as similar 'dual c64' mods from the past which enabled development to occur on a primary or 'master' system and then transmit and execute code over a cable to a secondary or 'slave' system. X2 refers to a version of TMP geared for users with 2 c64 systems but no REU. R2 is a version unlike any Turbo mod before it, because it combines TMP+REU's powerful REU modifications with the capability to assemble the object code to the second c64 as well. To use the X2/R2 mods, first install the 'x2rec' object code to the slave system - this code will run and wait to receive the assembled code from the master system. The source for the x2rec code, as well as a prebuilt binary located at $334, are included in the toolset. Once you have executed the code on the slave (e.g. jmp $334 for the prebuilt x2rec), then you are ready to perform a {back-arrow}+% command on your TMP instance running on the master system. Doing so sends the assembled object code across the X2 cable to the slave. When the xfer is complete, the code automagically starts on the slave. Assuming the x2rec code is not overwritten in the course of testing you may simply reset and rerun the x2rec code to prepare for another assemble and test run. Instructions on making the cable are included in the 'x2rec' source code file; it is really quite simple, straight wiring a few pins from each user port together. ------------------------------------- Turbo Macro Pro, Editor Overview ------------------------------------- The TMP editor is an almost-full screen line-based text editor. The bottom two lines are reserved for a message line which displays program generated errors/feedback, and a status line which displays the current horizontal cursor position/column, the bottom of source code memory, the editing modes re: character and line insertion, the current serial device number, and in the case of mods supporting extra memory, the current object and source bank numbers. Cursor keys work as expected, and the user is free to scroll up and down in the source code listing. Edits can be made in place, and TMP will automatically format each edited line, keeping the actual code (opcodes or pseudo ops) aligned against one column. TMP will also detect syntax errors in realtime, highlighting the offending line and give error feedback on the message line. ------------------------------------- Turbo Macro Pro, Editor Commands ------------------------------------- Special editor commands are accessed by pressing the 'command key', followed by another key to invoke a specific command. Certain commands will themselves invoke a submenu of additional commands. Several other commands may prompt for user input such as filenames, memory locations, and so on. The command key in all versions of TA, TAM, and TMP is the {back arrow} which is located to the immediate left of the number 1 key. The table below shows all the commands that are invoked by first pressing the command key, following by the key in the 'KEY' column below: KEY ACTION 1 exit-basic: Leaves TMP to a BASIC prompt. TMP can be re-entered immediately after doing this with a 'sys 8*4096'. ! view-seq: Prompts for a SEQ filename, then displays the contents of the file on screen; CBM pauses output, run/stop aborts. 2 paste-separator: Outputs a 'separator' comment line to the current cursor line, overwriting anything else there. 3 assemble: Assembles to the assembly bank, which is bank 0 in all mods supporting extra RAM, or simply directly to c64 main memory on the unexpanded c64 mod. # assemble-to-object: Assembles to the current object bank; only enabled on mods supporting extra RAM. 4 print-source: Prompts for a filename to which a source code print out will be saved as a SEQ file. Instead of a filename, enter '?' by itself to print directly to a printer (device 4) or '*' by itself to output to the screen (CBM pauses output, run/stop aborts). 5 assemble-to-disk: Prompts for a filename to which assembled code is saved on disk. % assemble-to-slave: Assembles across a cable to a slave machine; only enabled in the X2/R2 mods. 6 make-data: Prompts for a region of memory (start and end address). Data in that region are read and translated into .byte statements which are inserted into the source code at the current cursor line. In mods supporting extra RAM, the data is read from the current object bank; otherwise the data is read from the c64 main memory. 7 set-tab-return: Takes the current cursor location and sets that as the column at which the cursor is placed after pressing return. 8 set-tab-source: Takes the current cursor location and sets that as the column at which the source code (opcode/pseudo) is aligned at. + add-hex: Prompts for two 16bit values, adding them and outputting the result in hex and decimal. - sub-hex: Prompts for two 16bit values, subtracting the second from the first and outputting the result in hex and decimal. DEL delete-line: Removes the entire line under cursor, moving subsequent lines up by one. INST toggle-line-insert: Switches the editing mode for line insertion; when off, hitting return does not insert a new blank line. ^ copy-line-buffer: Copies the line under cursor to the line buffer. # paste-line-buffer: Pastes the line buffer to the current cursor line. q cursor-left-edge: Move cursor to column 0 (the leftmost column) w write-seq: Prompts for a filename to which the current source is saved to disk as a SEQ file. e enter-seq: Prompts for a filename from which lines of source code are read off disk and inserted at the current cursor line. r replace-string: Prompts for search and replacement strings and then finds the first occurance of the search string, leaving the cursor at that occurance. R ram-submenu: Activate the expansion RAM submenu (where applicable), with these additional key commands: l load-to-ram: Prompts for a filename. A second prompt is given for a load address, using the file's actual load address as a default. Then the file is loaded into the current object bank at the given address. b backup-to-bank: Prompts for an available source bank number, and then copies the active source code into that bank. o set-object-bank: Prompts for an available RAM bank and uses that as the new object bank. s swap-to-bank: Prompts for an available source bank number; if the selected bank contains a TMP/source instance, then the active source code is backed up to it's assigned bank and the selected bank is swapped into c64 main memory, becoming the new active source code. TMP will not allow swapping in a bank that doesn't already have a TMP instance in it. j set-jumpback: Prompts for an address, which will be the location to which the jumpback routine will be copied when executing an assembled code. If the address is set to $0000 then TMP will not copy the jumpbacker at all. The default address is $0140. t replace-one: Executes one replacement of a just-found search string and then searches for the next occurance, moving the cursor to it. y replace-all: Executes replacements for every occurance of the search string located from the current cursor location to the bottom of the source code. u list-labels: Prompts for a filename to which a listing of each label and the memory address that it resolves to will be saved to disk as a SEQ file. Instead of a filename, enter '?' by itself to print directly to a printer (device 4) or '*' by itself to output to the screen (CBM pauses output, run/stop aborts). Note that the output is based on the label resolutions from the last time the source code was assembled, and if list-labels is invoked prior to assembling any source code, the output will be empty. U list-labels-vice: Identical to list-labels, except the format of the output is compatible for loading into the VICE emulator monitor. i find-label: Prompts for a string to search for as a label, then places the cursor at the first occurance of that string where it is used as a label definition. p preferences-submenu: Activates the preferences editor submenu which can be used to modify the separator style and color scheme: 0 Edits the color used for $d020 (border). 1 Edits the color used for $d021 (background). 2 Edits the color used for the message line. 3 Edits the color used for the status line. 4 Edits the color used for regular source. 5 Edits the color used for source with a syntax error. 6 Edits the color used for source in the current marked block. s Edits the separator template ^ Prompts for a filename, to which a complete copy of the newly customized TMP program is written to disk. @ disk-command: Prompts for a string that is sent to the current serial device as a disk command, the results of which are displayed on the message line. Entering a '@' by itself will send a status command to the device. * view-directory: Outputs a directory listing from the current serial device to the screen; CBM pauses output, run/stop aborts. a petscii-mode: Sets the editor into a literal petscii mode; the cursor flashes slightly faster to indicate the setting. During this mode, all keypresses are taken literally as petscii sequences which are stored on the line. This mode is useful for entering color or cursor movement codes into .text strings that can be 'printed' from within your program. Hitting the {back-arrow} key will quit this mode and return to normal editing. s save-source: Prompts for a filename, to which the current source code is saved to disk as a binary PRG file. d increment-device: Selects the next available device number on the bus between 8 and 15. f find-string: Prompts for a string and then searches for the first occurance in the source code. g goto-mark: Prompts for a mark (1-9, s, e) and moves the cursor to the line number corresponding to the selected mark. h find-next: Finds the next occurance of the search string. k define-fkeys: Prompts for a redefinable function key (f3-f6) then allows the user to enter a new definition for the selected key. K reset-fkeys: The function keys f3-f6 are all reset to TMP's internal defaults. This is used when loading a source code that has a different set of key definitions than TMP. l load-source: Prompts for a filename, from which source code is read. Note, the loaded source code will *replace* any current source! : list-marks: Displays the current line numbers associated with each mark. ; kill-mark: Prompts for a mark (1-9, s, e) and blanks out the line number corresponding to the selected mark. z undo-edit: Undos whatever current line editing has occured. This can only be used as long as the cursor has not left the current line where editing has taken place! c cold-start: This performs a hard reset of TMP, initializing and blanking out the current source code. b block-submenu: Activates the block commands submenu, with these additional key commands: w write-block: Prompts for a filename to which the source code within the current marked block is saved to disk as a SEQ file. c copy-block: Copies the current marked block to the current cursor position. m move-block: Moves the current marked block to current cursor position. k kill-block: Erases the current marked block n goto-line: Prompts for a line number and then moves the cursor to the entered line. m set-mark: Prompts for a mark (1-9, s, e) and then sets the selected mark to the current cursor line. 's' and 'e' stand for start and end; setting these marks defines a contiguous set of lines upon which subsequent block operations (invoked by the block-submenu) will operate. = join-line: The remainder of the current line (everything to the right and under the current cursor location) is moved into the same location on the line immediately above, deleting the old line in the process. / blank-to-end: Blanks out everything on the current line to the right and under the current cursor location. RTRN split-line: The remainder of the current line (everything to the right and under the current cursor location) is moved into a new line which is inserted immediately below the current line. SPACE blank-line: Blanks out the current line CRSR-R cursor-right-edge: Moves the cursor to column 39 CRSR-L cursor-left-edge: Moved cursor to column 0 CRSR-D : Moves the cursor down by 200 lines CRSR-U : Moves the cursor up by 200 lines BARROW : The back arrow key, when pressed twice in a row, outputs an actual backarrow character. The next table shows all the behaviour of additional keys that are not combined with first pressing the command key: KEY ACTION INST toggle-char-insert: Switches the editing mode for character insertion; when off, new key presses overwrite instead of insert. F1 : Moves the cursor up by 20 lines F2 : Moves the cursor to line 0 (top of the source) F7 : Moves the cursor down by 20 lines F8 : Moves the cursor to the bottom of the source Function keys f3-f6 are redefinable, and have these default operations: KEY ACTION F3 Identical to {back-arrow}+CRSR-U (cursor up by 200 lines). F4 Assembles (as with {back-arrow}+3) and then auto executes the code. F5 Identical to {back-arrow}+CRSR-D (cursor down by 200 lines). F6 Identical to {back-arrow}+R which invokes the RAM submenu. ------------------------------------- Turbo Macro Pro, Assembler Overview ------------------------------------- TMP's assembler component provides the mechanism for parsing and translating source code into machine code. TMP source code consists of the following basic elements: labels: Something like variable names, a label is used to refer to a specific memory address. Labels are assigned to a memory address explicitly or get assigned by the assembler as it resolves unassigned labels. opcodes: These are the standard 6502 mnemonics, in the form of three letter abbreviations. pseudo ops: Assembler directives that instruct TMP to invoke some advanced operation instead of merely translating an opcode into machine code. comments: Simple way to annotate source code; comments are completely ignored by the assembler. ------------------------------------- Turbo Macro Pro, Assembler Details ------------------------------------- ------------------------------------ - Constant Values Constant values can be expressed in either decimal, hexadecimal, binary, or as characters depending on how the value is written. The largest constant value TMP can recognize is $ffff (65,535). $ denotes a hexadecimal value % denotes a binary value (limited to single bytes) 'a' denotes a character value, which translates to a byte Any value that is not preceded by $ or % or wrapped in quotes is treated as a decimal value. -=> Examples $20 = hex $20, dec 32 $2000 = hex $2000, dec 8192 15 = hex $0f, dec 15 %10001000 = hex $88, dec 135 '1' = hex $31, dec 49 ------------------------------------ - Labels Valid labels in TMP can be composed of any combination of letters, numbers, and the underscore character (obtained by pressing CBM+@). However, labels must begin with a letter, and can be no longer than 15 characters. Label names can be used in expressions (see below) in the same manner as constant values. To define a label explicitly, set the label to either an absolute memory address, to another label, or to an expression which will be resolved into an address. -=> Examples bah = $1000 ;sets the label 'bah' to $1000. lab = bah ;sets the label 'lab' to equal whatever address bah ; resolves to (in this case, it would also be $1000). tmp = bah+$8 ;sets the label 'tmp' to equal the address that the ; expression 'bah+$8" resolves to ($1008). There is a special label, which is called the 'program counter' and is represented in source code as the asterisk (*). It is important to set the value of * at the top of your code. When TMP assembles your source, * is used to tell the assembler where the machine code should be assembled to. Set the value of * just like a label: * = $1000 ;sets the program counter to $1000. Note that unlike normal labels, you can reset the value of * anywhere you want in your source code. Each time you redefine *, the assembler simply uses the new value and continues assembling machien code at the new address. ------------------------------------ - Expressions Expressions in Turbo Macro Pro can be formed with the following operators, all of which are binary operators (i.e. they require a value on the right AND left side of the operator): + for addition - for subtraction * for multiplication / for division & for bitwise and . for bitwise or : for bitwise eor Values used with expressions can be constant values described above, or labels. Note that you can also use parenthesis and as you would expect they affect the order in which the expression is evaluated: -=> Examples $20 + 4 = hex $24, dec 36 15 - %00000011 = hex $0c, dec 12 $ff & $f0 = hex $f0, dec 240 (2*$10)+1 = hex $21, dec 33 2*($10+1) = hex $22, dec 34 Unlike standard expressions in C/C++, there is no operator precedence. For example, multiplication has no higher precedence than addition: 2*$10+1 = hex $21, dec 33 1+2*$10 = hex $20, dec 32 In the first example above, the multiplication is resolved first, followed by the addition. In the next example, the addition is processed first! As this is a simplified way of resolving expressions than is more commonly seen in programming languages, it is important to keep in mind. Careful use of parenthesis can help make the expected results explicit. The special '*' label can also be used in expressions, and it will always resolve to whatever the current program counter is where the assembler is outputting machine code to: *= $1000 ;sets the program counter to $1000 jmp *+$03 ;assembles as jmp $1003 jmp * ;also assembles as jmp $1003 because the program counter at this line will actually be $1003. The value of an expressions can also be modified by the following characters, which must appear at the very front of the expression: < denotes that the low byte of the following constant or expression should be taken > denotes that the hi byte of the following constant or expression should be taken ! denotes an expression whose value may currently or later be determined as needing only 1 byte (i.e. 0-255) but which should be expanded into 2 bytes for the purposes of outputting machine code. See below for an example. -=> Examples >$0314 = hex $03 <$0314 = hex $14 <$0400+(6*$28) = hex $f0 Examples of the use of '!' are shown below. Keep in mind that the editor will not allow you to enter a constant value like $0002 or $00ff; it will automatically shorten it to $02 or $ff. This may be seen as a deficiency of the editor but you have a way around this when you really need to specify lines like lda $0002: lda $02 assembles as lda $02 lda !$02 assembles as lda $0002 Another use of the '!' is to prevent phase errors. A phase error occurs when the length of code as determined by pass one and pass two of the assembler do not match. One way this can occur is by labels referenced before they are defined: lda bah ; here, bah is undefined and TMP assumes it is a word rts bah = $02 ; bah is now defined as a byte value Assembling this code block results in a phase error, because TMP assumes undefined labels represent words during the first pass. If the label is then found defined as a byte value, or if it actually resolves to a byte value, then the second pass will be shorter than the first and a phase error occurs. To prevent the phase error change the code to look like: lda !bah rts bah = $02 The '!' tells TMP that the expression following should be treated as a word no matter how the label was defined. Obviously the best choice would be to define labels before referencing them but in our own experience this is sometimes undesired so using '!' notation will help avoid the woes of phase errors. ------------------------------------ - Comments You can add comments to your source code by using the ';' (semicolon). Any ';' found by turbo will cause the assembler to ignore whatever follows the ';' til the end of that line. So comments can follow an opcode, or a psuedo-op, or they can be on a line by themselves. -=> Examples ; this is a comment lda #$01 ; this is a comment sta $d020 ; so is this! ------------------------------------ - Pseudo ops: Tables The table pseudo ops are the standard way to make data or string tables. Note that values are not necessarily constrained to constants - they can be complete expressions as shown above. .byte - takes a list of byte values which can be decimal, hex, binary or character constants and produces a table of bytes. .word - takes a list of word values which can be decimal or hex and produces a table of bytes where the words are arranged in low-byte hi-byte order. .rta - takes a list of word values which can be decimal or hex and produces a table of bytes where the words are decremented by 1 and set in low-byte hi-byte order; this is useful for doing stack manipulation with e.g. return addresses. .text - takes a quoted string and produces from it a table of bytes. .null - takes a quoted string and produces from it a table of bytes terminated with a null (0) byte. .shift - takes a quoted string and produces from it a table of bytes where the last byte has its high-bit set to 1. -=> Examples .byte 25,"a",$cc = $19 $41 $cc .text "hi" = $48 $49 .null "hi" = $48 $49 $00 .shift "hi" = $48 $c9 .word $fce2 = $e2 $fc .rta $fce2 = $e1 $fc ------------------------------------ - Pseudo ops: Conditional Assembly These pseudo-ops allow TMP to assemble chunks of code based on the evaluation of an expression - if it is equal or not equal to zero or if it is positive or negative. You can use the functionality to selectively assemble code based on the value of a label, for example, or even the current value of the program counter. .if - tests value or expression for inequality with zero. (same as .ifne) .ifne - tests value or expression for inequality with zero. (same as .if) .ifeq - tests value or expression for equality with zero. .ifpl - tests value or expression for positive. .ifmi - tests value or expression for negative. .endif - marks the end of the code block that is assembled when the conditional test is met. -=> Examples cycle = 65 .ifne cycle-65 ;if cycle != 65 nop ;produce one nop .endif ------------------------------------ - Pseudo ops: Local Label Blocks The block psuedo-ops allow a very useful operation: marking a section of code so that it can contain its own local labels, which can be redefined outside of the block or within a different block! Using blocks when coding reusable subroutines can ease their integration into new code... when the blocked subroutine is inserted into another source, a coder needn't worry that the labels used inside the subroutine block will conflict with any labels already defined in the other code. .block - starts a code block .bend - ends a code block -=> Examples tmp = $02 ;tmp is defined as $02 lda tmp ;assembles as lda $02 sub ;our subroutine label name, 'sub' .block tmp = $ff ;tmp is defined as $ff but only applies in the block clc adc tmp ;assembles as adc $ff, not adc $02! rts .bend lda tmp ;assembles as lda $02 again... ------------------------------------ - Pseudo ops: Assembler Variables Assembler variables basically define special kind of label that can be redefined (even without worrying about localized blocks). This is the only way to change the value of a label in the same context without getting a 'double defined' error. These are most useful when combined with other pseudos like conditionals (see above) and goto (see below). .var - defines a variable identified by the label preceeding '.var', which is set to the value following the '.var'. -=> Examples va .var $01 ;defines a var named va with value of 1 lda #va ;results in lda #$01 va .var va+1 ;redefines va to it's current value+1 lda #va ;results in lda #$02 ------------------------------------ - Pseudo ops: Unconditional Goto These psuedo-ops force the assembler to jump to a given label and continue assembling from there. This can be extremely useful for repeating a byte or short code block 10, 100, or even more times. Only labels flagged with a .lbl psuedo-op can be referenced by a .goto! .lbl - identifies a label that can be referenced by a .goto .goto - causes assembler to goto the label referenced and continue assembling from that point on. -=> Examples cnt .var $0100 ;cnt = $100 loop .lbl ;label 'loop' is prepared to be a .goto target nop cnt .var cnt-1 ;dec cnt .ifne cnt ;if cnt != 0 .goto loop ;goto loop .endif ;until all $100 nop's are assembled ------------------------------------ - Pseudo ops: Macros Macros are a means of inserting a larger chunk of code by using a short macro label followed by 0 to 8 arguments. This macro label is expanded into the chunk of code at assembly time, with substitutions made for arguments given. A macro call is identified by a '#' follwed by the macro-label. .macro - starts a macro definition and automatically makes a block around the macro .segment - starts a macro definition but without a block .endm - ends a macro definition -=> Examples poke .macro ;start macro def lda #\2 ;the \2 means an argument substitution, in this case the ; second macro argument will replace the \2 sta \1 ;another substitution .endm ;end macro def In the source code, a macro call using the above would look like: #poke $d020,0 Upon assembly that macro call is expanded, and substitutions are made (in this case \1 is replaced by $d020 and \2 is replaced by 0) resulting in the following assembly being generated to replace the macro call: lda #$00 sta $d020 Here is a more complex example showing recursion with macros: table .macro ;start macro def cnt .var \1+1 ;set var cnt to arg 1 plus 1 #tab ;a macro call within a macro! .endm ;end macro def tab .segment ;start macro def cnt .var cnt-1 ;decrement cnt .if cnt ;if cnt != 0 #tab ;then recursively macro call itself .endif ;end of the if .byte cnt ;assemble a byte with current value of cnt cnt .var cnt+1 ;increment cnt .endm ;end macro def #table 64 ;call the macro to create a byte table from 0 to 64 Here is an example of using a text parameter in a macro definition and call: error .macro ;start macro def lda #tx ;hi-byte of tx jsr $ab1e ;print it jmp end ;skip text data tx .null "@1" ;@1 is replaced by a textual argument end .endm ;end macro def #error "doc too boring" So you see, use \x for numerical arguments, and @x for text arguments, where x denotes the argument number. Text arguments can be even used to modify an opcode! Example: do .segment .block loop .endm while .segment ;start macro def b@1 loop ;the @1 will be replaced by a text argument .bend .endm ;end macro def ldx #5 ;start of code #do ;call macro do ldy #2 lda #"*" #do ;call macro do jsr $ffd2 dey #while "pl" ;call macro 'while' using parameter "pl" lda #" " ;print space jsr $ffd2 dex #while "ne" ; call macro 'while' with parameter "ne" ------------------------------------ - Pseudo ops: Includes The .include psuedo-op allows you to assemble in large chunks of code or label data. For example, you could use .include to assemble in a SEQ file with label definitions for all of the kernal jumptable, or you could keep small subroutines in SEQ form and include them in as you need them. .include - load and assemble a specified file from disk during the current assembly; the file must be a SEQ file! -=> Example .include "kernel.s" ------------------------------------ - Pseudo ops: Code Offsets The .offs pseudo op is used to alter the 'effective location' of assembled code, unlike redefining * which changes the location where assembled code is put. In other words, code following a .offs will be treated as though it were being assembled at a different memory address even though it is still placed at the whatever the current program counter is (as set by *). If used in a slightly odd looking manner you can assemble code so that it will execute properly in a different part of memory than where the code itself is located in the assembled output. .offs - change the location that code is assembled to. -=> Example (this code) -> (assembles as) * = $2000 start bit base0 bit $2009 bit base bit $8000 jmp * jmp $2006 base0 * = $8000 base .offs base0-* lda #>start lda #$20 jmp * jmp $8002 This code is assembled from $2000 to $200d; by using an expression for the .offs we can generate code in a contiguous memory chunk, even though part of the code has been assembled to execute at a different memory address (in this case, $8000). naturally this can be extremely useful for coding routines that need to execute in zero page, e.g., or for coding routines to run in drive memory. ------------------------------------ - Pseudo ops: Printer Control The printer psuedo-ops allow some control during printing of source to printer, disk, or screen when activated with key command {back-arrow}+4. .proff and .pron allow you to skip printing sections of code, while .hidemac and .showmac let you control whether the expanded macro gets printed or just the macro call (see below). .pron - turn on printing .proff - turn off printing .hidemac - show unexpanded calls .showmac - show expanded calls ------------------------------------ - Pseudo ops: Miscellaneous Though we've not yet seen a good reason for these last two, they are nevertheless available for your use. .eor - followed by some value, with which all code after the .eor is eor'd with. .end - terminate assembling ------------------------------------- Turbo Macro Pro, Preferences Editor ------------------------------------- The TMPPREFS tool is a new offering that replaces the former preferences editor embedded within the assembler itself and previously accessed with BA+p. TMPPREFS can load any of the six v1.2 mods, and then resave it with settings set by you, using: BA+c = alter color preferences, works like v1.1 did; first pick a color to alter: 0 Edits the color used for $d020 (border). 1 Edits the color used for $d021 (background). 2 Edits the color used for the message line. 3 Edits the color used for the status line. 4 Edits the color used for regular source. 5 Edits the color used for source with a syntax error. 6 Edits the color used for source in the marked block. Then you need to hit CTRL or CBM and a number key just like you were setting the current cursor color! BA+o = flip through color sets from some well known Turbo versions BA+2 = alter 4 character separator template BA+j = alter jumpback location BA+k = alter function key definitions BA+7 = alter return tab (column that cursor sits after return) BA+8 = alter source tab (column that opcodes/pseudos start) You may also use BA+d (increment-device) and BA+* (directory) which are identical to their assembler counterparts. Once your settings are set the way you want, use BA+s to save the newly-customized version. ***** v1.2 Sep'06