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 LIST
Listing 1: MACRO1.M65 Download / View Listing 2: MACRO2.M65 Download / View
Listing 3: MACRO3.M65 Download / View
Listing 4: MACRO4.M65 Download / View