Assembly language
Shortcuts to Success
A Guide to Atari Macro Graphics
by Thomas McNamee
Synopsis
This article explains the use of macros in assembly-language programming, and supplies a library of macros for graphics programming. To use the accompanying programs, you must use MAC/65, a macro assembler from Optimized Systems Software. The macros and demonstration program will run on any Atari computer.Quick! Identify the following language:
0250 GRAPHICS 3 0260 COLOR 1 0270 SETCOLOR 4,0,4 0280 SETCOLOR 0,4,14 0290 PLOT 5,5 0300 DRAWTO 5,15 0310 DRAWTO 15,5 0320 DRAWTO 15,5 0330 DRAWTO 5,5It's not BASIC, of course - that would have been too easy. But, when executed, it draws the same pink square on a grey background that BASIC would have drawn. This is, or will become, assembly language. More precisely, it is a series of commands, called macro calls, which can be expanded and compiled into executable 6502 machine code by a powerful tool called a macro assembler.
This article will explain macro assembly and demonstrate the ways in which macros can be used to simplify program generation. It will also provide you with a graphics library that can be used as easily as the above listing suggests. The MAC/65 macro assembler from Optimized Systems Software (OSS) must be used to run the macros and the demonstration program- included in this article.
What is Macro Assembly?
There is an unwritten rule in commercial software development: Never write the same code twice. Because macros are reusable, tested modules, they allow you to stick to this guideline. Also, because numeric and string parameters can be passed on to them, their execution can be affected during compilation without making it necessary to change the code.I should explain at this point that there is an important distinction between run-time and compile-time behavior. Run-time behavior is, quite simply, what the code does during the process of execution. Once the assembler produces machine code, run-time behavior is frozen. For example, an LDA #$FF always loads 255 into the accumulator. Compile-time behavior, on the other hand, concerns the disposition of operations, operands, and pseudo-ops as they go through the assembly process.
Take a calculation, for example: LDA #$C0 + 1 becomes LDA #$Cl in machine code. Compile-time behavior depends to a significant degree on the assembler being used.
Consider this simple macro:
.MACRO LOADX .IF %1 <255 LDX #%1 .ELSE LDX %1 .ENDIF .ENDMAll keywords that start with "." are commands to the assembler. They only affect compile-time behavior, and do not appear in the machine code after assembly. For example, a two- or three-byte LDX instruction would be compiled from the above listing.
Several commands are introduced in LOADX. The command % 1 means parameter 1." This parameter is passed in the macro call as shown in the following example:
0250 LOADX 7The seven replaces every occurrence of % 1 in the macro. First, the .IF statement determines if it's less than 255. The .IF/.ELSE/.ENDIF assembler commands all make conditional assembly possible. In this case, the <255 test is true, so LDX #7 is compiled. If it were false, the assembler would assume that the passed parameter was a non-Zero-Page memory location, and the LDX would be compiled to a three-byte, absolute-addressed instruction.
As a macro call is assembled, it goes through a process called expansion. Listing 1 shows an example of this. Note that each time you call a macro, it is included in the program in its expanded form. As a result, if you use large macros, your program begins to consume huge amounts of memory. This is an important consideration when you're using macros. Because of this, it's usually more practical to incorporate a subroutine call to a single macro into your programs.
Macro Advantages
The use of macros is advantageous primarily because passed parameters can be used to customize a macro for any application. The GRAPHICS macro in Listing 3 will accept any argument that the BASIC GRAPHICS command will; it will also use a memory location if the argument is nine or greater. Another advantage is that once you've tested a macro, you have a known, useful piece of software at your disposal. Thus, a macro library, such as the one in Listing 3, constitutes a collection of reusable, tested routines that can be used any time they're needed in a program.
Library and Equate Files
Listing 3 contains macros that simulate many BASIC graphics commands. Once you've typed it in and saved it, you can use .INCLUDE to incorporate it into any of your programs. The use of macro libraries adds a great deal of efficiency to the process of program development, because it saves a good deal of composition and testing time.It's also helpful to use function-oriented EQUate files in your programs These files give standard Atari mnemonic labels to commonly-used locations, and they can also be .INCLUDEd during assembly.
Listing 2 contains equates used by Listing 3, and should be .INCLUDEd before assembling the graphics macros.
The Graphics.lib File
The commands included in Listing 3 simulate Atari BASIC's commands as closely as possible. When compiled, however, they execute many times faster than BASIC. The following list describes each of these macros in brief:GRAPHICS - Allows you to call Graphics Modes 0-8. However, you must allocate enough memory to permit the S: driver to open the screen. To do this, first calculate the memory requirements for the screen, display list and text window. Subtract this quantity from the address of the top of RAM, and store the result in APPMHI, which is equated in Listing 2. This macro uses all registers; upon exit, the Y-register contains the status.
COLOR - Stores the selected color-register number in a spare byte that is equated in Listing 2. Only the accumulator is used.
POSITION - Positions the cursor at the selected screen location. Only the accumulator is used. Note that the passed parameters must be literals, not memory locations.
PLOT - Plots a point in the selected COLOR at the X and Y coordinates, which are passed as %1 and % 2.
DRAWTO - Draws a straight line from the last point plotted to the passed coordinates. All registers are used.
SETCOLOR - Sets the selected register to the indicated hue and color. All registers are used.
Demonstration Program
Listing 4 is a short program that demonstrates the use of the above graphics macros, as well as the use of .INCLUDEd files. Before you assemble it, make sure that you have all four .INCLUDE files on a disk in your drive. GREQU.M65 is Listing 2 and GRAPHICS.LIB is Listing 3.These listings and the application program detail the use of each graphics macro. With some experience, you can create your own library, thereby saving yourself a fair amount of programming and testing time. A good starting point would be to code two routines: SAVEREG and RESTORE. These should allow you to preserve all registers while making a subroutine jump or macro call.
Thomas McNamee is a software engineer for ManTech International in Alexandria, Virginia. He programs in FORTH, C, BASIC and 6502 assembly language, and has written for a number of computer publications.
Listing 1 0350 COLOR 1 =0001 M .IF %1<16 3000 A901 M LDA #%1 M .ELSE M LDA %1 M .ENDIF 3002 8DF502 M STA SPARE1 M .ENDM 0360 SETCOLOR 4,0,4 = 0001 M .IF %1<16 3005 A204 M LDX #%l M .ELSE M LDX %l M .ENDIF =0000 M .IF %2>16 M LDA %2 M ASL A M ASL A M ASL A M ASL A .ELSE 3007 A900 M LDA #%2*16 M .ENDIF =0001 M .IF %3<16 3009 A004 M LDY #%3 M .ELSE M LDY %3 M .ENDIF 300B 9DC402 M STA COLOR0,X 300E 98 M TYA 300F 290E M AND #$0E 3011 18 M CLC 3012 7DC402 M ADC COLOR0,X 3015 9OC402 M STA COLOR0,X M .ENDM Listing 2 0100 ;FILENAME: GREQU.M65 0110 .TITLE "GRAPHICS EQUATE FILE" 0120 .PAGE "GRAPHICS EQUATES" 0130 ; 0140 ; CURSOR 0150 ROWCRS = $54 ; FULL SCREEN 0160 COLCRS = $55 0170 TXTROW = $0290 ; SPLIT SCREEN 0180 TXTCOL = $0291 0190 ; 0200 ; SCREEN MEMORY 0210 SAVMSC = $58 ; FULL SCREEN 0220 TXTMSC = $0294 ; SPLIT SCREEN 0230 ; 0240 ; GRAPHICS MODE 0250 DINDEX = $57 ; FULL SCREEN 0260 TINDEX = $0293 ; SPLIT SCREEN 0270 ; 0280 ; SCREEN MARGINS 0290 LMARGN = $52 0300 RMARGN = $53 0310 ; 0320 ; DISPLAY LIST 0330 VDSLST = $0200 ; VECTOR FOR DLI 0340 SDLSTL = $0230 ; START OF DL 0350 WSYNC = $D40A 0360 ; 0370 ; MISC. 0380 BOTSCR = $02BF ; LINES IN SCRE EN (4 OR 24) 0390 SPARE1 = $02F5 ; SPARE BYTES 0400 SPARE2 = $02F6 0410 SPARE3 = $02F7 0420 SPARE4 = $02F8 0430 SPARE5 = $02F9 0440 ATACHR = $02FB ; USED BY FILL & DRAW 0450 ; 0460 ; CHARACTER SET 0470 CHBAS = $02F4 ; SHADOW 0480 CHBASE = $D409 ; HARDWARE 0490 CHACT = $02F4 ; CHAR. MODE REG 0500 ; 0510 ; COLORS 0520 ; SHADOW REGISTERS 0530 COLOR0 = $02C4 0540 COLOR1 = $02C5 0550 COLOR2 = $02C6 0560 COLOR3 = $02C7 0570 COLOR4 = $02C8 0580 ; HARDWARE REGISTERS 0590 COLPF0 = $D016 0600 COLPF1 = $D017 0610 COLPF2 = $D018 0620 COLPF3 = $D019 0630 COLBK = $D01A 0640 ; 0650 ; INTERRUPT CONTROL 0660 NMIEN = $D40E ; NMI ENABLE 0670 NMIST = $D40F ; NMI STATUS 0680 NMIRES = $D40F ; NMI RESET 0690 ;BIT: 7 6 5 43210 0700 ; DLI VBI RESET..... 0710 ; 0720 ; SCROLLING 0730 HSCROL = $D404 0740 VSCROL = $D405 0750 ; 0760 ; CIO COMMANDS 0770 CDRAW = $11 0780 CFILL = $12 0790 ; Listing 3 0100 ;FILENAME: GRAPHICS.LIB 0110 .TITLE "GRAPHICS LIBRARY" 0120 .PAGE "GRAPHICS MACRO" 0130 ; 0140 .IF .NOT .DEF ROWCHS 0150 .ERROR "GREQU.M65 missing!" 0160 .ENDIF 0170 .IF .NOT .DEF CPALOC 0180 .ERROR "SYSEQU.M65 missing!" 0190 .ENDIF 0200 ; 0210 ;MACRO: GRAPHICS 0220 ; 0230 ;FORM: GRAPHICS N 0240 ;If N is <9, then N is a memory 0250 ;location, else N is a literal 0260 ; 0270 .MACRO GRAPHICS 0280 ; 0290 JMP @CONT 0300 @AX1 0310 .BYTE 0 0320 @AX2 0330 .BYTE 0 0340 @CONT 0350 XIO 12,6,0,0,"S:" 0360 .IF %1<9 0370 LDA #%1 0380 .ELSE 0390 LDA %1 0400 .ENDIF 0410 STA @AX2 0420 AND #$F0 0430 EOR #$10 0440 ORA #$0C 0450 STA @AX1 0460 OPEN 6,@AX1,@AX2,"S:" 0470 .ENDM 0480 ,PAGE "COLOR, POSITION & PLOT MACROS" 0490 ; 0500 ;MACRO: COLOR 0510 ; 0520 ;FORM: COLOR N 0530 ;If N < 16, then N is literal 0540 ;Else N is a memory location. 0550 ; 0560 .MACRO COLOR 0570 .IF %1<16 0580 LDA #%1 0590 .ELSE 0600 LDA %1 0610 .END IF 0620 STA SPARE 1 0630 .ENDM 0640 ; 0650 ;MACRO: POSITION 0660 ; 0670 ;FORM: POSITION X,Y 0680 ;X and Y must be literals, not 0690 ; memory locations 0700 ; 0710 .MACRO POSITION 0720 LDA # <%1 0730 STA COLCRS 0740 LDA # >%1 0750 STA COLCRS+1 0760 LDA #%2 0770 STA ROWCHS 0780 .ENDM 0790 ; 0800 ;MACRO: PLOT 0810 ; 0820 ;FORM: PLOT X,Y 0830 ; X and Y must be literals , not 0840 ;memory locations 0850 ; 0860 .MACRO PLOT 0870 POSITION %1,%2 0880 @CH 6 0890 LDA #CPBINR 0900 STA ICCOM,X 0910 LDA #0 0920 STA ICBLEN,X 0930 STA ICBLEN+1,X 0940 LDA SPARE1 0950 JSR CIO 0960 .ENDM 0970 .PAGE "DRAWTO & SETCOLOR MACR 0S" 0980 ; 0990 ;MACRO: DRAWTO 1000 ; 1010 ;FORM: DRAWTO X,Y 1020 ; X and Y must be literals as in 1030 ;POSITION 1040 ; 1050 .MACRO DRAWTO 1060 POSITION %1,%2 1070 LDA SPARE1 1080 STA ATACHR 1090 @CH 6 1100 LDA #CDRAW 1110 STA ICCOM,X 1120 LDA #CCLOSE 1130 STA ICAUX1,X 1140 LDA #0 1150 STA ICAUX2,X 1160 JSR CIO 1170 .ENDM 1180 ; 1190 ;MACRO: SETCOLOR 1200 ; 1210 ;FORM: SETCOLOR REG,HUE,LUM 1220 ;Any parameter <16 is considered 1230 ;a memory location 1240 ; 1250 .MACRO SETCOLOR 1260 .IF %1<16 1270 LDX #%1 1280 .ELSE 1290 LDX %1 1300 .ENDIF 1310 .IF %2>16 1320 LDA %2 1330 ASL A 1340 ASL A 1350 ASL A 1360 ASL A 1370 .ELSE 1380 LDA #%2*16 1390 .ENDIF 1400 .IF %3<16 1410 LDY #%3 1420 .ELSE 1430 LDY %3 1440 .ENDIF 1450 STA COLOR0,X 1460 TYA 1470 AND #$0E 1480 CLC 1490 ADC COLOR0,X 1500 STA CDLOR0,X 1510 .ENDM 1520 ; 1530 ;*** END OF GRAPHICS.LIB *** Listing 4 0100 ;FILENAME: GRTEST.M65 0110 .OPT NO LIST ; Don't list ] INC LUDE filies 0120 ; 0130 ;These fiIes are on MAC/65 d1sk 0140 .INCLUDE #D:SYSEQU.M65 0150 .INCLUDE #D:IOMAC.LIB 0160 ; 0170 ; See text for these files 0180 .INCLUDE #D:GREQU.M65 0190 .INCLUDE #D:GRAPHICS.LIB 0200 ; 0210 GRMEM = 460 ;Bytes of memory for GR. 3 0220 ; 0230 *= $3000 0240 ; 0250 .OPT LIST 0260 ; 0270 ;Set top of applications memory 0280 LDA # <$BFFF-GRMEM 0290 STA APPMHI 0300 LDA # >$BFFF-GRMEM 0310 STA APPMHI+1 0320 ; 0330 ; This Iooks like BASIC . . . 0340 GRAPHICS 3 0350 COLOR 1 0360 SETCOLOR 4,0,4 0370 SETCOLOR 0,4,14 0380 PLOT 5,5 0390 DRAWTO 5,15 0400 DRAWTO 15,15 0410 BRAWTO 15,5 0420 DRAWTO 5,5 0430 ; 0440 ;Loop until SYSTEM RESET 0450 END JMP END 0460 .OPT NO LISTListing 1: MACRO1.M65 Download / View
Listing 2: MACRO2.M65 Download / View
Listing 3: MACRO3.M65 Download / View
Listing 4: MACRO4.M65 Download / View