O p @`  @`! #@%`')+-/13@o79=?AE`IMOQ S@U`WY[]_a c@e`gikmoq s@u`wy{} @` ` @ ` @ ` @ ` ǀ ɠ @ ` ׀ ٠  @`@`  @`! #@%`')+-/13@o79=?AE`IMOQ S@U`WY[]_a c@e`gikmoq s@u`wy{} @` ` @ ` @ ` @ ` ǀ ɠ @ ` ׀ ٠  @`ATARI S %7BUGS S %w:CODE S %6@CODE65 S %0CONV65 MAN %2 CONV65 PRG %5HEXAMPLE S %;EXAMPLE1S %BEXAMPLE2S %CIIMAGES S %D` INSTMAC S %Gb M PRG %JMAC PRG %K"MAC PRN %HREADME  %SHIFT S %  .nlist ; 21-Jul-1987 lmd ; N *< ; O * PRELIMINARY ATARI ST EQUATES AND MACROS. * ; T * THIS FILE IS STILL MISSING DEFINITIONS, AND * ; E * MAY HAVE BUGS WE HAVEN'T CAUGHT YET. * ; !!! *< .subttl 'Hardware Locations' ; ; Atari ST hardware locations ; memconf = $f8001 ; memory controller dbaseh = $f8201 dbasel = $f8203 ; display base low, high vcounthi = $f8205 ; display counter low, medium, high vcountmid = $f8207 vcountlow = $f8209 syncmode = $f820a ; video sync mode color0 = $f8240 ; color registers 0..15 color1 = $f8242 color2 = $f8244 color3 = $f8246 color4 = $f8248 color5 = $f824a color6 = $f824c color7 = $f824e color8 = $f8250 color9 = $f8252 color10 = $f8254 color11 = $f8256 color12 = $f8258 color13 = $f825a color14 = $f825c color15 = $f825e shiftmd = $f8260 ; shifter mode (resolution) ;--- DMA chip ; diskctl = $f8604 ; disk controller data access fifo = $f8606 ; DMA mode control dmahigh = $f8609 ; DMA base high, medium, low dmamid = $f860b dmalow = $f860d ;--- 1770 registers ; cmdreg = $80 ; 1770/FIFO command register select trkreg = $82 ; 1770/FIFO track register select secreg = $84 ; 1770/FIFO sector register select datareg = $86 ; 1770/FIFO data register select ;--- Sound Chip ; giselect = $f8800 ; (W) sound chip register select giread = $f8800 ; (R) sound chip read-data giwrite = $f8802 ; (W) sound chip write-data gitoneaf = 0 ; channel A fine/coarse tune gitoneac = 1 gitonebf = 2 ; channel B gitonebc = 3 gitonecf = 4 ; channel C gitonecc = 5 ginoise = 6 ; noise generator control gimixer = 7 ; I/O control/volume control register giaamp = 8 ; channel A, B, C amplitude gibamp = 9 gicamp = $a gifienvlp = $b ; envelope period fine, coarse tune gicrnvlp = $c giporta = $e ; GI register# for I/O port A giportb = $f ; Centronics output register ;--- Bits in "giporta": ; xrts = 8 ; RTS output dtr = $10 ; DTR output strobe = $20 ; Centronics strobe output gpo = $40 ; "general purpose" output ;--- 68901 (MFP) ; mfp = $fa00 ; mfp base gpip = mfp+1 ; general purpose I/O aer = mfp+3 ; active edge reg ddr = mfp+5 ; data direction reg iera = mfp+7 ; interrupt enable A & B ierb = mfp+9 ipra = mfp+$b ; interrupt pending A & B iprb = mfp+$d isra = mfp+$f ; interrupt inService A & B isrb = mfp+$11 imra = mfp+$13 ; interrupt mask A & B imrb = mfp+$15 vr = mfp+$17 ; interrupt vector base tacr = mfp+$19 ; timer A control tbcr = mfp+$1b ; timer B control tcdcr = mfp+$1d ; timer C & D control tadr = mfp+$1f ; timer A data tbdr = mfp+$21 ; timer B data tcdr = mfp+$23 ; timer C data tddr = mfp+$25 ; timer D data scr = mfp+$27 ; sync char ucr = mfp+$29 ; USART control reg rsr = mfp+$2b ; receiver status tsr = mfp+$2d ; transmit status udr = mfp+$2f ; USART data ;--- 6850s ; keyctl = $fc00 ; keyboard ACIA control keybd = $fc02 ; keyboard data midictl = $fc04 ; MIDI ACIA control midi = $fc06 ; MIDI data .subttl 'BIOS Variables' ; ; BIOS Variables ; etv_timer = $400 ; vector for timer interrupt chain etv_critic = $404 ; vector for critical error chain etv_term = $408 ; vector for process terminate etv_xtra = $40c ; 5 reserved vectors memvalid = $420 ; indicates system state on RESET memcntlr = $424 ; mem controller config nibble resvalid = $426 ; validates 'resvector' resvector = $42a ; [RESET] bailout vector phystop = $42e ; physical top of RAM _membot = $432 ; bottom of available memory; _memtop = $436 ; top of available memory; memval2 = $43a ; validates 'memcntlr' and 'memconf' flock = $43e ; floppy disk/FIFO lock variable seekrate = $440 ; default floppy seek rate _timr_ms = $442 ; system timer calibration (in ms) _fverify = $444 ; nonzero: verify on floppy write _bootdev = $446 ; default boot device palmode = $448 ; nonzero ==> PAL mode defshiftmd = $44a ; default video rez (first byte) sshiftmd = $44c ; shadow for 'shiftmd' register _v_bas_ad = $44e ; pointer to base of screen memory vblsem = $452 ; semaphore to enforce mutex in vbl nvbls = $454 ; number of deferred vectors _vblqueue = $456 ; pointer to vector of deferred vfuncs colorptr = $45a ; pointer to palette setup (or NULL) screenpt = $45e ; pointer to screen base setup (|NULL) _vbclock = $462 ; count of unblocked vblanks _frclock = $466 ; count of every vblank hdv_init = $46a ; hard disk initialization swv_vec = $46e ; video change-resolution bailout hdv_bpb = $472 ; disk "get BPB" hdv_rw = $476 ; disk read/write hdv_boot = $47a ; disk "get boot sector" hdv_mediach = $47e ; disk media change detect _cmdload = $482 ; nonzero: load COMMAND.COM from boot conterm = $484 ; console/vt52 bitSwitches (%%0..%%2) trp14ret = $486 ; saved return addr for _trap14 criticret = $48a ; saved return addr for _critic themd = $48e ; memory descriptor (MD) _md = $49e ; (more MD) savptr = $4a2 ; pointer to register save area _nflops = $4a6 ; number of disks attached (0, 1+) con_state = $4a8 ; state of conout() parser save_row = $4ac ; saved row# for cursor X-Y addressing sav_context = $4ae ; pointer to saved processor context _bufl = $4b2 ; two buffer-list headers _hz_200 = $4ba ; 200hz raw system timer tick _drvbits = $4c2 ; bit vector of "live" block devices _dskbufp = $4c6 ; pointer to common disk buffer _autopath = $4ca ; pointer to autoexec path (or NULL) _vbl_list = $4ce ; initial _vblqueue (to $4ee) _dumpflg = $4ee ; screen-dump flag _prtabt = $4f0 ; printer abort flag _sysbase = $4f2 ; -> base of OS _shell_p = $4f6 ; -> global shell info end_os = $4fa ; -> end of OS memory usage exec_os = $4fe ; -> address of shell to exec on startup scr_dump = $502 ; -> screen dump code prv_lsto = $506 ; -> _lstostat() prv_lst = $50a ; -> _lstout() prv_auxo = $50e ; -> _auxostat() prv_aux = $512 ; -> _auxout() .subttl '"Line A" Equates' ; ; "Line A" Equates ; VPLANES = 0 VWRAP = 2 CONTRL = 4 INTIN = 8 PTSIN = 12 INTOUT = 16 PTSOUT = 20 COLBIT0 = 24 COLBIT1 = 26 COLBIT2 = 28 COLBIT3 = 30 LSTLIN = 32 LNMASK = 34 WMODE = 36 X1 = 38 Y1 = 40 X2 = 42 Y2 = 44 PATPTR = 46 PATMSK = 50 MFILL = 52 CLIP = 54 XMINCL = 56 YMINCL = 58 XMAXCL = 60 YMAXCL = 62 XDDA = 64 DDAINC = 66 SCALDIR = 68 MONO = 70 SRCX = 72 SRCY = 74 DSTX = 76 DSTY = 78 DELX = 80 DELY = 82 FBASE = 84 FWIDTH = 88 STYLE = 90 LITEMSK = 92 SKEWMSK = 94 WEIGHT = 96 ROFF = 98 LOFF = 100 SCALE = 102 CHUP = 104 TEXTFG = 106 SCRTCHP = 108 SCRPT2 = 112 TEXTBG = 114 COPYTRAN = 116 SEEDABORT = 118 .subttl '"Line A" Macros' ; ; "Line A" macros ; .macro A_init dc.w $a000 .endm .macro A_putpix dc.w $a001 .endm .macro A_getpix dc.w $a002 .endm .macro A_abline dc.w $a003 .endm .macro A_habline dc.w $a004 .endm .macro A_rectfill dc.w $a005 .endm .macro A_polyfill dc.w $a006 .endm .macro A_bitblt dc.w $a007 .endm .macro A_textblt dc.w $a008 .endm .macro A_showcur dc.w $a009 .endm .macro A_hidecur dc.w $a00a .endm .macro A_chgcur dc.w $a00b .endm .macro A_drsprite dc.w $a00c .endm .macro A_unsprite dc.w $a00d .endm .macro A_copyrstr dc.w $a00e .endm .macro A_seedfill dc.w $a00f .endm .subttl 'Operating System Macros' .macro Bios trpno, clean ; trap to BIOS move.w #\trpno,-(sp) trap #13 .if \clean <= 8 addq #\clean,sp .else add.w #\clean,sp .endif .endm .macro Xbios trpno, clean ; trap to XBIOS move.w #\trpno,-(sp) trap #14 .if \clean <= 8 addq #\clean,sp .else add.w #\clean,sp .endif .endm .iif !(^^defined GEMDOS), GEMDOS = 1 .macro Gemdos trpno, clean ; trap to GEMDOS move.w #\trpno,-(sp) trap #GEMDOS .if \clean <= 8 addq #\clean,sp .else add.w #\clean,sp .endif .endm ; ; String "foobar" (push onto stack) ; String "foobar",a0 move address of string somewhere ; .macro String str,loc .if \?loc move.l #.\~,\loc .else pea .\~ .endif .data .\~: dc.b \str,0 .text .endm .subttl 'Bios Traps' ;--- Character Device Numbers ; PRT = 0 ; printer AUX = 1 ; RS-232 CON = 2 ; console (vt-52 emulator) MIDI = 3 ; MIDI port IKBD = 4 ; ikbd (out only) RAWCON = 5 ; console (raw characters) .macro Getmbp ptr move.l \ptr,-(sp) Bios 0,4 .endm .macro Bconstat dev move.w \dev,-(sp) Bios 1,4 .endm .macro Bconin dev move.w \dev,-(sp) Bios 2,4 .endm .macro Bconout dev, char move.w \char,-(sp) move.w \dev,-(sp) Bios 3,6 .endm .macro Rwabs rwflag, buf, count, recno, dev move.w \dev,-(sp) move.w \recno,-(sp) move.w \count,-(sp) move.l \buf,-(sp) move.w \rwflag,-(sp) Bios 4,14 .endm .macro Setexc vecnum, vec move.l \vec,-(sp) move.w \vecnum,-(sp) Bios 5,8 .endm .macro Tickcal Bios 6,2 .endm .macro Getbpb devno move.w \devno,-(sp) Bios 7,4 .endm .macro Bcostat devno move.w \devno,-(sp) Bios 8,4 .endm .macro Mediach devno move.w \devno,-(sp) Bios 9,4 .endm .macro Drvmap Bios 10,2 .endm .macro Kbshift mode move.w \mode,-(sp) Bios 11,4 .endm .subttl 'Extended BIOS Traps' .macro Initmous type, param, vec move.l \vec,-(sp) move.l \param,-(sp) move.w \type,-(sp) Xbios 0,12 .endm .macro Physbase Xbios 2,2 .endm .macro Logbase Xbios 3,2 .endm .macro Getrez Xbios 4,2 .endm .macro Setscreen logloc, physloc, rez move.w \rez,-(sp) move.l \physloc,-(sp) move.l \logloc,-(sp) Xbios 5,12 .endm .macro Setpallete ptr move.l \ptr,-(sp) Xbios 6,6 .endm .macro Setcolor colnum, color move.w \color,-(sp) move.w \colnum,-(sp) Xbios 7,6 .endm .macro Floprd buf, devno, sectno, trackno, sideno, count move.w \count,-(sp) move.w \sideno,-(sp) move.w \trackno,-(sp) move.w \sectno,-(sp) move.w \devno,-(sp) clr.l -(sp) ; (filler) move.l \buf,-(sp) Xbios 8,20 .endm .macro Flopwr buf, devno, sectno, trackno, sideno, count move.w \count,-(sp) move.w \sideno,-(sp) move.w \trackno,-(sp) move.w \sectno,-(sp) move.w \devno,-(sp) clr.l -(sp) ; (filler) move.l \buf,-(sp) Xbios 9,20 .endm .macro Flopfmt buf,devno,spt,trackno,sideno,interlv,magic,virgin move.w \virgin,-(sp) move.l \magic,-(sp) move.w \interlv,-(sp) move.w \sideno,-(sp) move.w \trackno,-(sp) move.w \spt,-(sp) move.w \devno,-(sp) clr.l -(sp) ; (filler) move.l \buf,-(sp) Xbios $a,26 .endm .macro Midiws cnt1,ptr move.l \ptr,-(sp) move.w \cnt1,-(sp) Xbios $c,8 .endm .macro Random Xbios $11,2 .endm .macro Protobt buf,serialno,disktype,execflag move.w \execflag,-(sp) move.w \disktype,-(sp) move.l \serialno,-(sp) move.l \buf,-(sp) Xbios $12,14 .endm .macro Flopver buf, devno, sectno, trackno, sideno, count move.w \count,-(sp) move.w \sideno,-(sp) move.w \trackno,-(sp) move.w \sectno,-(sp) move.w \devno,-(sp) clr.l -(sp) ; (filler) move.l \buf,-(sp) Xbios $13,20 .endm CURS_HIDE = 0 CURS_SHOW = 1 CURS_BLINK = 2 CURS_NOBLINK = 3 CURS_SETRATE = 4 CURS_GETRATE = 5 .macro Cursconf func,op move.w \op,-(sp) move.w \func,-(sp) Xbios $15,6 .endm .macro Settime datetime move.l \datetime,-(sp) Xbios $16,6 .endm .macro Gettime Xbios $17,2 .endm .macro Kbdvbase Xbios $22,2 .endm .macro Vsync Xbios $24,2 .endm .macro Supexec where move.l \where,-(sp) Xbios $26,6 .endm .subttl 'Gemdos Traps' .macro Dsetdrv drive move.w \drive,-(sp) Gemdos $e,4 .endm .macro Pterm0 clr.w -(sp) trap #GEMDOS illegal .endm .macro Pterm code .if \?code move.w \code,-(sp) .else clr.w -(sp) .endif move.w #$4c,-(sp) trap #GEMDOS illegal .endm .macro Super clr.l -(sp) move.w #$20,-(sp) trap #GEMDOS addq #6,sp move.l d0,-(sp) move.w #$20,-(sp) .endm .macro User trap #GEMDOS addq #6,sp .endm .macro Puts string move.l \string,-(sp) Gemdos 9,6 .endm .macro Tgetdate Gemdos $2a,2 .endm .macro Tsetdate date move.w \date,-(sp) Gemdos $2b,4 .endm .macro Tgettime Gemdos $2c,2 .endm .macro Tsettime time move.w \time,-(sp) Gemdos $2d,4 .endm .macro Fgetdta Gemdos $2f,0 .endm .macro Sversion Gemdos $30,2 .endm .macro Dfree buf,drive move.w \drive,-(sp) move.l \buf,-(sp) Gemdos $36,8 .endm .macro Fopen file, mode move.w \mode,-(sp) move.l \file,-(sp) Gemdos $3d,8 .endm .macro Fcreate file, mode move.w \mode,-(sp) move.l \file,-(sp) Gemdos $3c,8 .endm .macro Fread handle, count, buf move.l \buf,-(sp) move.l \count,-(sp) move.w \handle,-(sp) Gemdos $3f,12 .endm .macro Fwrite handle, count, buf move.l \buf,-(sp) move.l \count,-(sp) move.w \handle,-(sp) Gemdos $40,12 .endm .macro Fclose handle move.w \handle,-(sp) Gemdos $3e,4 .endm .macro Fdelete file move.l \file,-(sp) Gemdos $41,6 .endm .macro Fseek offset, handle, mode move.w \mode,-(sp) move.w \handle,-(sp) move.l \offset,-(sp) Gemdos $42,10 .endm .macro Fsetdta addr move.l \addr,-(sp) Gemdos $1a,6 .endm .macro Ptermres count, retcode move.w \retcode,-(sp) move.l \count,-(sp) Gemdos $31,8 .endm .macro Mshrink block, newsiz move.l \newsiz,-(sp) move.l \block,-(sp) clr.w -(sp) Gemdos $4a,12 .endm .macro Malloc amount move.l \amount,-(sp) Gemdos $48,6 .endm .macro Mfree addr move.l \addr,-(sp) Gemdos $49,6 .endm .macro Pexec mode, p1, p2, p3 move.l \p3,-(sp) move.l \p2,-(sp) move.l \p1,-(sp) move.w \mode,-(sp) Gemdos $4b,16 .endm .macro Fsfirst fspec, attr move.w \attr,-( sp) move.l \fspec,-(sp) Gemdos $4e,8 .endm .macro Fsnext Gemdos $4f,2 .endm .subttl 'Structures' ; ; Basepage Format ; .ABS Plowtpa: ds.l 1 Phitpa: ds.l 1 Ptbase: ds.l 1 Ptlen: ds.l 1 Pdbase: ds.l 1 Pdlen: ds.l 1 Pbbase: ds.l 1 Pblen: ds.l 1 Pxdta: ds.l 1 Pparent: ds.l 1 ; ; Searchfirst/Searchnext DTA structure ; .ABS ds.b 21 DTA_attr: ds.b 1 DTA_time: ds.w 1 DTA_date: ds.w 1 DTA_size: ds.l 1 DTA_name: ds.b 14 .TEXT .eject .list  ;-G: ; : ; Silly Bugs Demo : ; : ;- : ; 30-Nov-1986 lmd Hacked it up. : ; : ;-G: .include "atari.s" ; get ST equates and macros ;- ; ; Imports ; .globl _images ; -> table of images (->) .globl _masks ; -> table of masks (->) .globl mksh ; construct shifted images ;- ; ; Exports ; .globl draw ; draw an image .globl undraw ; undraw (erase) an image .globl upd_gravity ; update an image, with gravity ;- ; ; Bug structure ; .abs BGcritno: ds.b 1 ; critter number (0=dead) BGstate: ds.b 1 ; critter state BGxpos: ds.l 1 ; int+frac X and Y positions BGypos: ds.l 1 BGxvel: ds.l 1 ; int+frac Y and Y velocities BGyvel: ds.l 1 BGtimer: ds.w 1 ; timer BGimage: ds.w 1 ; image number BGscraddr: ds.l 1 ; starting address on screen BGimgaddr: ds.l 1 ; -> image BGmskaddr: ds.l 1 ; -> mask BGimgsize: ds.l 1 ; = image size (0, 4, 8 ...) BGSIZE: ds.l 1 ; (size of bug structure) ;- ; ; Global variables ; NBUGS equ 16 ; number of bugs .bss screen: ds.l 1 ; -> screen memory mode: ds.w 1 ; screen resolution (0, 2, 4) modex4: ds.w 1 ; screen resolution (0, 4, 8) width: ds.w 1 ; = screen width maxx: ds.w 1 ; max X position for 16-wide sprite maxy: ds.w 1 ; max Y position for 16-high sprite linshft: ds.w 1 ; shift amount for X index computation linmask: ds.w 1 ; mask for X index computation gravity: ds.l 1 ; int+frac gravity oldrez: ds.w 1 ; old screen resolution savedColors: ds.w 16 ; saved pallette freemem: ds.b $8000 ; space for shifted images ["enough" space] bugs: ds.b BGSIZE*NBUGS ; bugs database .data ourColors: dc.w $000,$700,$070,$770 ; our pallette dc.w $007,$707,$077,$555 dc.w $333,$733,$373,$773 dc.w $337,$737,$377,$654 .text ;- ; ; Top level ; move.l #$04000,gravity ; set force of gravity bsr inivideo ; initialize video parameters lea freemem,a1 ; a1 -> free memory bsr mksh ; make shifted fonts ;- setup initial positions and velocities from ; a list of initial values. ; lea bugs,a5 lea i_xpos,a0 lea i_ypos,a1 lea i_xvel,a2 lea i_img,a3 moveq #NBUGS-1,d0 ilp1: clr.l BGxpos(a5) clr.l BGypos(a5) move.w (a0)+,BGxpos(a5) move.w (a1)+,BGypos(a5) move.l (a2)+,BGxvel(a5) move.w (a3)+,BGimage(a5) clr.l BGscraddr(a5) ; clobber screen addr (never drawn) lea BGSIZE(a5),a5 dbra d0,ilp1 ;--- Bugs loop: ; o refresh all bugs ; o sync with vblank ; o test for a keypress, punt on any keystroke ; loop: moveq #NBUGS-1,d6 ; d6 = #bugs-1 lea bugs,a5 loop1: bsr upd_gravity ; update a bug lea BGSIZE(a5),a5 ; advance to next one dbra d6,loop1 ; (loop for more) move.w #$25,-(sp) ; Vsync() trap #14 addq #2,sp Bconstat #CON ; key ready? tst.w d0 beq loop ; (no --- loop) Bconin #CON ; eat the keypress bsr restore_video ; restore video Pterm0 ; and terminate ;--- initial image numbers i_img: dc.w 0,1,2,0 dc.w 0,1,2,0 dc.w 0,1,2,0 dc.w 0,1,2,0 ;--- initial X and Y posititions i_xpos: dc.w $00,$10,$20,$30 dc.w $40,$50,$60,$70 dc.w $80,$90,$a0,$b0 dc.w $c0,$d0,$e0,$f0 i_ypos: dc.w $00,$08,$10,$18 dc.w $20,$28,$30,$38 dc.w $40,$48,$30,$38 dc.w $20,$28,$10,$18 ;--- Initial X velocities i_xvel: dc.l $08000 dc.l $0c000 dc.l $00010 dc.l $00014000 dc.l $08000 dc.l $0c000 dc.l $00010 dc.l $08000 dc.l $00014000 dc.l $0c000 dc.l $00010 dc.l $08000 dc.l $0c000 dc.l $00014000 dc.l $00010 dc.l $00014000 ;- ; ; Video parameter setup ; inivideo: Physbase ; screen = Physbase() move.l d0,screen Supexec #saveColors ; save pallette Supexec #setColors ; initialize pallette with our colors Getrez ; mode = Getrez() << 1 move.w d0,oldrez ; save old resolution cmp.w #1,d0 ; medium rez? bne.s .1 ; (no) moveq #0,d0 bsr setRez ; set rez to low moveq #0,d0 .1: add.w d0,d0 move.w d0,mode move.w d0,modex4 ; mode4 = Getrez() << 2 add.w d0,modex4 move.w xwidth(pc,d0.w),width move.w xmaxx(pc,d0.w),maxx move.w xmaxy(pc,d0.w),maxy move.w xlinshft(pc,d0.w),linshft move.w xlinmask(pc,d0.w),linmask rts saveColors: lea color0,a0 lea savedColors,a1 move.w #16-1,d0 .1: move.w (a0)+,(a1)+ dbra d0,.1 rts setColors: lea ourColors,a0 lea color0,a1 move.w #16-1,d0 .1: move.w (a0)+,(a1)+ dbra d0,.1 rts ;+ ; Resolution-dependent parameter tables ; ;- xwidth: dc.w 160,160,80 ; screen width (bytes) xmaxx: dc.w 303,623,623 ; max X position for 16-wide sprite xmaxy: dc.w 183,183,383 ; max Y position for 16-high sprite xlinshft: dc.w 1,2,3 ; shifts for X index computation xlinmask: dc.w $f-7,$f-3,$f-1 ; masks for X index computation ;- ; ; Restore original screen resolution ; restore_video: Supexec #restoreColors ; restore pallette cmp.w #1,oldrez ; was in medium? bne.s .ret ; (no --- leave it alone) move.w oldrez,d0 ; set rez back to medium bsr setRez .ret: rts setRez: move.b d0,.temp Supexec #.1 rts .1: move.b .temp,shiftmd rts bss .temp: ds.w 1 .text restoreColors: lea savedColors,a0 lea color0,a1 move.w #16-1,d0 .1: move.w (a0)+,(a1)+ dbra d0,.1 rts ;- general-purpose return instruction return: rts ;- ; ; Draw bug; ; - compute addresses of things and fill-in bug structure ; - setup registers for drawing ; - do drawing ; ; Passed: a5 -> bug ; Returns: nothing ; Fills-in: BGscraddr(a5) ; BGimgaddr(a5) ; BGmskaddr(a5) ; BGimgsize(a5) ; Uses: a0-a4/d0-d4 ; draw:: move.w BGypos(a5),d0 ; d0 = ypos * width mulu width,d0 move.w BGxpos(a5),d1 ; d1 = (xpos >> linshft) & linmask move.w d1,d2 ; (save xpos for later) move.w linshft,d3 lsr.w d3,d1 and.w linmask,d1 add.w d1,d0 ; d0 += d1 move.l screen,a0 ; a0 = screen + (ypos * width) + add.w d0,a0 ; (xpos >> linshft) & linmask move.l a0,BGscraddr(a5) ; save screen addr for cmp and undraw moveq #0,d3 ; assume 1x and.w #$000f,d2 ; see if on 16-pixel boundary beq.s .1 ; (yes --- it's 1x) moveq #4,d3 ; no --- it's 2x .1: move.w d3,BGimgsize(a5) ; set image size, keep d3=image size move.w BGimage(a5),d0 ; d0 = image number to draw lsl.w #2,d0 ; turn into longword index move.w BGxpos(a5),d1 ; d1 = (x_position & 15) << 2 and.w #15,d1 lsl.w #2,d1 lea _images,a1 move.l (a1,d0.w),a1 ; a1 -> image base move.l (a1,d1.w),a1 ; a1 -> image move.l a1,BGimgaddr(a5) ; save image addr for cmp and undraw lea _masks,a2 move.l (a2,d0.w),a2 ; a2 -> image's mask base move.l (a2,d1.w),a2 ; a2 -> image's mask move.l a2,BGmskaddr(a5) ; save mask addr for cmp and undraw move.w width,d1 ; d1 = screen width move.w modex4,d0 ; d0 = longword rez index move.l axdraw(pc,d0.w),a4 ; a4 -> vector of drawing routines move.l (a4,d3.w),a4 ; a4 -> drawing routine jmp (a4) ;+ ; Table of ptrs to drawing routines ; ;- axdraw: dc.l lxdraw,hxdraw,mxdraw lxdraw: dc.l ld1x16,ld2x16 hxdraw: dc.l return,return mxdraw: dc.l md1x16,md2x16 ;+ ; Draw a 1x16 image in low-rez ; ; a0 -> screen base ; a1 -> image base ; a2 -> mask base ; d1 = screen width ; ;- ld1x16: moveq #16-1,d2 ; d2 = scanline count .1: move.w (a2)+,d4 ; d4 = mask ;--- plane 0 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0) ; stuff result onto screen ;--- plane 1 move.w 2(a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,2(a0) ; stuff result onto screen ;--- plane 2 move.w 4(a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,4(a0) ; stuff result onto screen ;--- plane 3 move.w 6(a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,6(a0) ; stuff result onto screen add.w d1,a0 ; bump screen ptr to next scanline dbra d2,.1 ; loop for more lines rts ;+ ; Draw a 2x16 image in low-rez ; ; a0 -> screen base ; a1 -> image base ; a2 -> mask base ; d1 = screen width ; ;- ld2x16: sub.w #16,d1 ; adjust screen width for image stride moveq #16-1,d2 ; d2 = scanline count ld2_1: move.w (a2)+,d4 ; d4 = mask ;--- plane 0 part 0 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen ;--- plane 1 part 0 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen ;--- plane 2 part 0 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen ;--- plane 3 part 0 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen move.w (a2)+,d4 ; d4 = mask ;--- plane 0 part 1 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen ;--- plane 1 part 1 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen ;--- plane 2 part 1 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen ;--- plane 3 part 1 move.w (a0),d0 ; d0 = screen and.w d4,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0)+ ; stuff result onto screen add.w d1,a0 ; bump screen ptr to next scanline dbra d2,ld2_1 ; loop for more lines rts ;+ ; Draw a 1x16 image in monochrome ; ; a0 -> screen base ; a1 -> image base ; a2 -> mask base ; d1 = screen width ; ;- md1x16: moveq #16-1,d2 ; d2 = scanline count md1_1: move.w (a0),d0 ; d0 = screen and.w (a2)+,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0) ; stuff result onto screen addq.w #6,a1 ; bump past color planes add.w d1,a0 ; bump screen ptr to next scanline dbra d2,md1_1 ; loop for more lines rts ;+ ; Draw a 2x16 image in monochrome ; ; a0 -> screen base ; a1 -> image base ; a2 -> mask base ; d1 = screen width ; ;- md2x16: moveq #16-1,d2 ; d2 = scanline count md2_1: move.w (a0),d0 ; d0 = screen and.w (a2)+,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,(a0) ; stuff result onto screen addq.w #6,a1 ; bump past color planes move.w 2(a0),d0 ; d0 = screen and.w (a2)+,d0 ; clobber bits in mask or.w (a1)+,d0 ; or-in bits from image move.w d0,2(a0) ; stuff result onto screen addq.w #6,a1 ; bump past color planes add.w d1,a0 ; bump screen ptr to next scanline dbra d2,md2_1 ; loop for more lines rts ;- ; ; Undraw bug ; ; Passed: a5 -> bug ; Returns: nothing ; Uses: a0-a4/d0-d4 ; undraw:: move.l BGscraddr(a5),d0 ; if BGscraddr == NULL beq.s .ret ; then return; move.l d0,a0 move.l BGmskaddr(a5),a2 move.w width,d1 move.w BGimgsize(a5),d0 move.w modex4,d2 move.l axundraw(pc,d2.w),a4 move.l (a4,d0.w),a4 jmp (a4) .ret: rts ;+ ; Table of ptrs to undraw routines ; ;- axundraw: dc.l lxundraw,hxundraw,mxundraw lxundraw: dc.l lu1x16,lu2x16 hxundraw: dc.l return,return mxundraw: dc.l mu1x16,mu2x16 ;+ ; Undraw a 1x16 image in low rez ; ; a0 -> screen base ; a2 -> mask base ; d1 = screen width ; ;- lu1x16: sub.w #8,d1 ; adjust screen width for image stride moveq #16-1,d2 ; d2 = scanline count .1: move.w (a2)+,d0 ; d0 = mask and.w d0,(a0)+ and.w d0,(a0)+ and.w d0,(a0)+ and.w d0,(a0)+ add.w d1,a0 ; bump to next screen location dbra d2,.1 ; loop for more scanlines rts ;+ ; Undraw a 2x16 image in low rez ; ; a0 -> screen base ; a2 -> mask base ; d1 = screen width ; ; Uses: ; d4 = ~mask ; d5 = mask ;  ;  ; ;- lu2x16: sub.w #16,d1 ; adjust screen width for image stride moveq #16-1,d2 ; d2 = scanline count .1: .rept 2 move.w (a2)+,d0 ; d5 = mask and.w d0,(a0)+ and.w d0,(a0)+ and.w d0,(a0)+ and.w d0,(a0)+ .endr add.w d1,a0 ; bump to next screen location dbra d2,.1 ; loop for more scanlines rts ;+ ; Undraw a 1x16 image in monochrome ; ; a0 -> screen base ; a2 -> mask base ; d1 = screen width ; ;- mu1x16: .rept 16 move.w (a2)+,d0 and.w d0,(a0) add.w d1,a0 .endr rts ;+ ; Undraw a 2x16 image in monochrome ; ; a0 -> scr[een base ; a2 -> mask base ; d1 = screen width ; ;- mu2x16: .rept 16 move.l (a2)+,d0 and.l d0,(a0) add.w d1,a0 .endr rts ;- ; ; Update position (with gravity) ; ; Passed: a5 -> bug ; Returns: nothing ; Uses: d0-d4/a0-a4 ; upd_gravity: moveq #0,d2 ; MovedFlag := FALSE ;--- update Y position (with gravity) move.w BGypos(a5),d3 ; save old position (for comparison) move.l BGyvel(a5),d0 ; bump velocity with gravity add.l gravity,d0 .y: move.l d0,BGyvel(a5) add.l d0,BGypos(a5) ; bump position with new velocity move.w BGypos(a5),d0 ; get significant part of position bpl.s .1 ; if (pos < 0) bra.s .2 ; reverse velocity (bounce) .1: cmp.w maxy,d0 ; if (pos > maxy) blt.s .3 .2: move.l BGyvel(a5),d0 ; reverse velocity neg.l d0 bra .y ; recompute position .3: cmp.w BGypos(a5),d3 ; if (newpos != oldpos) beq.s .4 st d2 ; MovedFlag := TRUE .4: move.w BGxpos(a5),d3 ; save old position (for comparison) move.l BGxvel(a5),d0 ; d0 = velocity .7: add.l BGxpos(a5),d0 ; d0 = position + velocity move.l d0,BGxpos(a5) bmi.s .5 ; if (position < 0) then bounce swap d0 cmp.w maxx,d0 ; if (position <= maxx) then OK blt.s .6 .5: move.l BGxvel(a5),d0 ; d0 = -velocity neg.l d0 move.l d0,BGxvel(a5) ; velocity = -velocity bra.s .7 ; move again (other direction) .6: cmp.w BGxpos(a5),d3 ; if (newpos != oldpos) bne.s .8 ; then redraw tst.b d2 ; if (MovedFlag == TRUE) beq.s .r ; (no, so exit) .8: bsr undraw ; undraw old image (in old position) bsr draw ; draw new image in new position .r: rts ;- ; ; 68000 Opcodes ; abs = $0ab5 abcd:: abcd d1,d2 abcd -(a3),-(a4) nop add:: add d1,d2 add a2,d3 add (a3),d4 add (a4)+,d5 add -(a5),d6 add $1234(a6),d7 add $12(a1,a2),d2 add abs.w,d3 add abs,d4 add .1(pc),d5 add .1(pc,a2),d6 add #$1234,d7 .1: nop add d1,(a2) add d2,(a3)+ add d3,-(a4) add d4,$1234(a5) add d5,$12(a6,a7) add d6,abs.w add d7,abs nop adda:: add d1,a2 adda d1,a2 adda a2,a3 adda (a3),a4 adda (a4)+,a5 adda -(a5),a6 adda $1234(a6),a7 adda $12(a1,a2),a2 adda abs.w,a3 adda abs,a4 adda .1(pc),a5 adda .1(pc,a2),a6 adda #$1234,a7 .1: nop addi:: add #$1234,d1 addi #$1234,d1 addi #$1234,(a3) addi #$1234,(a4)+ addi #$1234,-(a5) addi #$1234,$1234(a6) addi #$1234,$12(a1,a2) addi #$1234,abs.w addi #$1234,abs .1: nop addq:: addq #1,d1 addq #2,a2 addq #3,(a3) addq #4,(a4)+ addq #5,-(a5) addq #6,$1234(a6) addq #7,$12(a1,a2) addq #8,abs.w addq #1,abs .1: nop addx:: addx d1,d2 addx d3,d4 addx -(a1),-(a2) addx -(a3),-(a4) and:: and d1,d2 and (a3),d4 and (a4)+,d5 and -(a5),d6 and $1234(a6),d7 and $12(a1,a2),d2 and abs.w,d3 and abs,d4 and .1(pc),d5 and .1(pc,a2),d6 and #$1234,d7 .1: nop and d1,(a2) and d2,(a3)+ and d3,-(a4) and d4,$1234(a5) and d5,$12(a6,a7) and d6,abs.w and d7,abs nop andi:: and #$1234,d1 andi #$1234,d1 andi #$1234,(a3) andi #$1234,(a4)+ andi #$1234,-(a5) andi #$1234,$1234(a6) andi #$1234,$12(a1,a2) andi #$1234,abs.w andi #$1234,abs .1: nop andi #$ff,ccr andi #$f,sr asl:: asl.b d1,d2 asl d2,d3 asl.w d3,d4 asl.l d4,d5 asl.b #2,d1 asl #3,d2 asl.w #4,d3 asl.l #5,d4 asl d5 asl (a3) asl (a4)+ asl -(a5) asl $1234(a6) asl $12(a1,a2) asl abs.w asl abs .1: nop asr:: asr.b d1,d2 asr d2,d3 asr.w d3,d4 asr.l d4,d5 asr.b #2,d1 asr #3,d2 asr.w #4,d3 asr.l #5,d4 asr d5 asr (a3) asr (a4)+ asr -(a5) asr $1234(a6) asr $12(a1,a2) asr abs.w asr abs .1: nop bra:: bra targ1 bcc targ1 bcs targ1 beq targ1 bge targ1 bgt targ1 bhi targ1 ble targ1 bls targ1 blt targ1 bmi targ1 bne targ1 bpl targ1 bvc targ1 bvs targ1 nop bra.s targ1 bcc.s targ1 bcs.s targ1 beq.s targ1 bge.s targ1 bgt.s targ1 bhi.s targ1 ble.s targ1 bls.s targ1 blt.s targ1 bmi.s targ1 bne.s targ1 bpl.s targ1 bvc.s targ1 bvs.s targ1 nop targ1:: nop nop bra.s targ1 bcc.s targ1 bcs.s targ1  beq.s targ1 bge.s targ1 bgt.s targ1 bhi.s targ1 ble.s targ1 bls.s targ1 blt.s targ1 bmi.s targ1 bne.s targ1 bpl.s targ1 bvc.s targ1 bvs.s targ1 nop bra targ1 bcc targ1 bcs targ1 beq targ1 bge targ1 bgt targ1 bhi targ1 ble targ1 bls targ1 blt targ1 bmi targ1 bne targ1 bpl targ1 bvc targ1 bvs targ1 nop bra.w targ1 bcc.w targ1 bcs.w targ1 beq.w targ1 bge.w targ1 bgt.w targ1 bhi.w targ1 ble.w targ1 bls.w targ1 blt.w targ1 bmi.w targ1 bne.w targ1 bpl.w targ1 bvc.w targ1 bvs.w targ1 bchg:: bchg d1,d2 bchg d2,(a3) bchg d3,(a4)+ bchg d4,-(a5) bchg d5,$1234(a6) bchg d6,$12(a1,a2) bchg d7,abs.w bchg d1,abs bchg #1,d2 bchg #2,(a3) bchg #3,(a4)+ bchg #4,-(a5) bchg #5,$1234(a6) bchg #6,$12(a1,a2) bchg #7,abs.w bchg #1,abs bclr:: bclr d1,d2 bclr d2,(a3) bclr d3,(a4)+ bclr d4,-(a5) bclr d5,$1234(a6) bclr d6,$12(a1,a2) bclr d7,abs.w bclr d1,abs bclr #1,d2 bclr #2,(a3) bclr #3,(a4)+ bclr #4,-(a5) bclr #5,$1234(a6) bclr #6,$12(a1,a2) bclr #7,abs.w bclr #1,abs bset:: bset d1,d2 bset d2,(a3) bset d3,(a4)+ bset d4,-(a5) bset d5,$1234(a6) bset d6,$12(a1,a2) bset d7,abs.w bset d1,abs bset #1,d2 bset #2,(a3) bset #3,(a4)+ bset #4,-(a5) bset #5,$1234(a6) bset #6,$12(a1,a2) bset #7,abs.w bset #1,abs btst:: btst d1,d2 btst d2,(a3) btst d3,(a4)+ btst d4,-(a5) btst d5,$1234(a6) btst d6,$12(a1,a2) btst d7,abs.w btst d1,abs btst d2,.1(pc) btst d3,.1(pc,a3) btst d4,#$12 btst #1,d2 btst #2,(a3) btst #3,(a4)+ btst #4,-(a5) btst #5,$1234(a6) btst #6,$12(a1,a2) btst #7,abs.w btst #1,abs btst #2,.1(pc) btst #3,.1(pc,a3) .1: nop chk:: chk d1,d2 chk (a3),d4 chk (a4)+,d5 chk -(a5),d6 chk $1234(a6),d7 chk $12(a1,a2),d2 chk abs.w,d3 chk abs,d4 chk .1(pc),d5 chk .1(pc,a2),d6 chk #$1234,d7 .1: nop clr:: clr d1 clr (a3) clr (a4)+ clr -(a5) clr $1234(a6) clr $12(a1,a2) clr abs.w clr abs clr a1 .1: nop cmp:: cmp d1,d2 cmp a2,d3 cmp (a3),d4 cmp (a4)+,d5 cmp -(a5),d6 cmp $1234(a6),d7 cmp $12(a1,a2),d2 cmp abs.w,d3 cmp abs,d4 cmp .1(pc),d5 cmp .1(pc,a2),d6 cmp #$1234,d7 cmp.w a2,d3 cmp.l a2,d3 .1: nop cmpa:: cmpa d1,a2 cmpa a2,a3 cmpa (a3),a4 cmpa (a4)+,a5 cmpa -(a5),a6 cmpa $1234(a6),a7 cmpa $12(a1,a2),a2 cmpa abs.w,a3 cmpa abs,a4 cmpa .1(pc),a5 cmpa .1(pc,a2),a6 cmpa #$1234,a7 .1: nop cmpi:: cmpi #$1234,d1 cmpi #$1234,(a3) cmpi #$1234,(a4)+ cmpi #$1234,-(a5) cmpi #$1234,$1234(a6) cmpi #$1234,$12(a1,a2) cmpi #$1234,abs.w cmpi #$1234,abs .1: nop cmpm:: cmpm.b (a1)+,(a2)+ cmpm (a3)+,(a4)+ cmpm.w (a5)+,(a6)+ cmpm.l (a7)+,(a0)+ nop dbcc:: dbcc d1,targ2 dbcs d2,targ2 dbeq d3,targ2 dbf d4,targ2 dbge d5,targ2 dbgt d6,targ2 dbhi d1,targ2 dble d2,targ2 dbls d3,targ2 dblt d4,targ2 dbmi d5,targ2 dbne d6,targ2 dbpl d1,targ2 dbt d2,targ2 dbvc d3,targ2 dbvs d4,targ2 dbra d5,targ2 nop targ2:: nop nop dbcc d1,targ2 dbcs d2,targ2 dbeq d3,targ2 dbf d4,targ2 dbge d5,targ2 dbgt d6,targ2 dbhi d1,targ2 dble d2,targ2 dbls d3,targ2 dblt d4,targ2 dbmi d5,targ2 dbne d6,targ2 dbpl d1,targ2 dbt d2,targ2 dbvc d3,targ2 dbvs d4,targ2 dbra d5,targ2 nop divs:: divs d1,d2 divs (a3),d4 divs (a4)+,d5 divs -(a5),d6 divs $1234(a6),d7 divs $12(a1,a2),d2 divs abs.w,d3 divs abs,d4 divs .1(pc),d5 divs .1(pc,a2),d6 divs #$1234,d7 .1: nop divu:: divu d1,d2 divu (a3),d4 divu (a4)+,d5 divu -(a5),d6 divu $1234(a6),d7 divu $12(a1,a2),d2 divu abs.w,d3 divu abs,d4 divu .1(pc),d5 divu .1(pc,a2),d6 divu #$1234,d7 .1: nop eor:: eor d1,(a2) eor d2,(a3)+ eor d3,-(a4) eor d4,$1234(a5) eor d5,$12(a6,a7) eor d6,abs.w eor d7,abs nop eori:: eor #$1234,d1 eori #$1234,d1 eori #$1234,(a3) eori #$1234,(a4)+ eori #$1234,-(a5) eori #$1234,$1234(a6) eori #$1234,$12(a1,a2) eori #$1234,abs.w eori #$1234,abs eori #$ff,ccr eori #$ffff,sr nop exg:: exg d1,d2 exg d2,a3 exg a3,d4 exg a4,a5 ext:: ext.w d1 ext.l d2 illegal:: illegal jmp:: jmp (a1) jmp $1234(a2) jmp $12(a3,a4) jmp abs.w jmp abs jmp $1234(pc) jmp $12(pc,a3) jmp targ3(pc) jmp targ3(pc,a4) nop targ3:: nop nop jsr:: jsr (a1) jsr $1234(a2) jsr $12(a3,a4) jsr abs.w jsr abs jsr $1234(pc) jsr $12(pc,a3) jsr targ4(pc) jsr targ4(pc,a4) nop targ4:: nop nop lea:: lea (a1),a2 lea $1234(a2),a3 lea $12(a3,a5),a4 lea abs.w,a5 lea abs,a6 lea targ5(pc),a1 lea targ5(pc,a6),a2 targ5:: nop link:: link a1,#$1234 link a2,#-1 link a3,#$ffff link a3,#0 lsl:: lsl.b d1,d2 lsl d2,d3 lsl.w d3,d4 lsl.l d4,d5 lsl.b #2,d1 lsl #3,d2 lsl.w #4,d3 lsl.l #5,d4 lsl d5 lsl (a3) lsl (a4)+ lsl -(a5) lsl $1234(a6) lsl $12(a1,a2) lsl abs.w lsl abs .1: nop lsr:: lsr.b d1,d2 lsr d2,d3 lsr.w d3,d4 lsr.l d4,d5 lsr.b #2,d1 lsr #3,d2 lsr.w #4,d3 lsr.l #5,d4 lsr d5 lsr (a3) lsr (a4)+ lsr -(a5) lsr $1234(a6) lsr $12(a1,a2) lsr abs.w lsr abs .1: nop move:: move d1,d1 move a2,d2 move (a3),d3 move (a4)+,d4 move -(a5),d5 move $1234(a6),d6 move $12(a1,a2),d1 move abs.w,d2 move abs,d3 move .1(pc),d4 move .1(pc,a2),d5 move #$1234,d6 .1: nop move d1,(a1) move a2,(a2) move (a3),(a3) move (a4)+,(a4) move -(a5),(a5) move $1234(a6),(a6) move $12(a1,a2),(a1) move abs.w,(a2) move abs,(a3) move .2(pc),(a4) move .2(pc,a2),(a5) move #$1234,(a6) .2: nop move d1,(a1)+ move a2,(a2)+ move (a3),(a3)+ move (a4)+,(a4)+ move -(a5),(a5)+ move $1234(a6),(a6)+ move $12(a1,a2),(a1)+ move abs.w,(a2)+ move abs,(a3)+ move .3(pc),(a4)+ move .3(pc,a2),(a5)+ move #$1234,(a6)+ .3: nop move d1,-(a1) move a2,-(a2) move (a3),-(a3) move (a4)+,-(a4) move -(a5),-(a5) move $1234(a6),-(a6) move $12(a1,a2),-(a1) move abs.w,-(a2) move abs,-(a3) move .4(pc),-(a4) move .4(pc,a2),-(a5) move #$1234,-(a6) .4: nop move d1,$1234(a1) move a2,$1234(a2) move (a3),$1234(a3) move (a4)+,$1234(a4) move -(a5),$1234(a5) move $1234(a6),$1234(a6) move $12(a1,a2),$1234(a1) move abs.w,$1234(a2) move abs,$1234(a3) move .5(pc),$1234(a4) move .5(pc,a2),$1234(a5) move #$1234,$1234(a6) .5: nop move d1,$12(a1,a5) move a2,$12(a2,a5) move (a3),$12(a3,a5) move (a4)+,$12(a4,a5) move -(a5),$12(a5,a5) move $1234(a6),$12(a6,a5) move $12(a1,a2),$12(a1,a5) move abs.w,$12(a2,a5) move abs,$12(a3,a5) move .6(pc),$12(a4,a5) move .6(pc,a2),$12(a5,a5) move #$1234,$12(a6,a5) .6: nop move d1,abs.w move a2,abs.w move (a3),abs.w move (a4)+,abs.w move -(a5),abs.w move $1234(a6),abs.w move $12(a1,a2),abs.w move abs.w,abs.w move abs,abs.w move .7(pc),abs.w move .7(pc,a2),abs.w move #$1234,abs.w .7: nop move d1,abs move a2,abs move (a3),abs move (a4)+,abs move -(a5),abs move $1234(a6),abs move $12(a1,a2),abs move abs.w,abs move abs,abs move .8(pc),abs move .8(pc,a2),abs move #$1234,abs .8: nop _ccr:: move d1,ccr move (a3),ccr move (a4)+,ccr move -(a5),ccr move $1234(a6),ccr move $12(a1,a2),ccr move abs.w,ccr move abs,ccr move .1(pc),ccr move .1(pc,a2),ccr move #$1234,ccr .1: nop _sr:: move sr,d1 move sr,(a2) move sr,(a3)+ move sr,-(a4) move sr,$1234(a5) move sr,$12(a6,a3) move sr,abs.w move sr,abs nop move d1,sr move (a3),sr move (a4)+,sr move -(a5),sr move $1234(a6),sr move $12(a1,a2),sr move abs.w,sr move abs,sr move .1(pc),sr move .1(pc,a2),sr move #$1234,sr .1: nop _usp:: move usp,a1 move usp,a2 move a3,usp move a4,usp movea:: move d1,a2 move a2,a3 move (a3),a4 move (a4)+,a5 move -(a5),a6 move $1234(a6),a1 move $12(a1,a2),a2 move abs.w,a3 move abs,a4 move .0(pc),a5 move .0(pc,a2),a6 move #$1234,a7 .0: nop movem:: movem d1-d6/a3-a7,(a1) movem d1-d6/a3-a7,-(a2) movem d1-d6/a3-a7,$1234(a3) movem d1-d6/a3-a7,$12(a4,a5) movem d1-d6/a3-a7,abs.w movem d1-d6/a3-a7,abs nop movem (a1),d1-d6/a3-a7 movem (a2)+,d1-d6/a3-a7 movem $1234(a3),d1-d6/a3-a7 movem $12(a4,a5),d1-d6/a3-a7 movem abs.w,d1-d6/a3-a7 movem abs,d1-d6/a3-a7 nop nop movem.w d1-d6/a3-a7,(a1) movem.w d1-d6/a3-a7,-(a2) movem.w d1-d6/a3-a7,$1234(a3) movem.w d1-d6/a3-a7,$12(a4,a5) movem.w d1-d6/a3-a7,abs.w movem.w d1-d6/a3-a7,abs nop movem.w (a1),d1-d6/a3-a7 movem.w (a2)+,d1-d6/a3-a7 movem.w $1234(a3),d1-d6/a3-a7 movem.w $12(a4,a5),d1-d6/a3-a7 movem.w abs.w,d1-d6/a3-a7 movem.w abs,d1-d6/a3-a7 nop nop movem.l d1-d6/a3-a7,(a1) movem.l d1-d6/a3-a7,-(a2) movem.l d1-d6/a3-a7,$1234(a3) movem.l d1-d6/a3-a7,$12(a4,a5) movem.l d1-d6/a3-a7,abs.w movem.l d1-d6/a3-a7,abs nop movem.l (a1),d1-d6/a3-a7 movem.l (a2)+,d1-d6/a3-a7 movem.l $1234(a3),d1-d6/a3-a7 movem.l $12(a4,a5),d1-d6/a3-a7 movem.l abs.w,d1-d6/a3-a7 movem.l abs,d1-d6/a3-a7 nop movep:: movep d1,$1234(a2) movep d2,(a3) movep $1234(a3),d4 movep (a4),d5 movep.w d1,$1234(a2) movep.w d2,(a3) movep.w $1234(a3),d4 movep.w (a4),d5 movep.l d1,$1234(a2) movep.l d2,(a3) movep.l $1234(a3),d4 movep.l (a4),d5 moveq:: moveq #0,d0 moveq #$ff,d0 moveq #$7f,d0 moveq #1,d0 muls:: muls d1,d2 muls (a3),d4 muls (a4)+,d5 muls -(a5),d6 muls $1234(a6),d7 muls $12(a1,a2),d2 muls abs.w,d3 muls abs,d4 muls .1(pc),d5 muls .1(pc,a2),d6 muls #$1234,d7 .1: nop mulu:: mulu d1,d2 mulu (a3),d4 mulu (a4)+,d5 mulu -(a5),d6 mulu $1234(a6),d7 mulu $12(a1,a2),d2 mulu abs.w,d3 mulu abs,d4 mulu .1(pc),d5 mulu .1(pc,a2),d6 mulu #$1234,d7 .1: nop nbcd:: nbcd d1 nbcd (a3) nbcd (a4)+ nbcd -(a5) nbcd $1234(a6) nbcd $12(a1,a2) nbcd abs.w nbcd abs nop neg:: neg d1 neg (a3) neg (a4)+ neg -(a5) neg $1234(a6) neg $12(a1,a2) neg abs.w neg abs nop negx:: negx d1 negx (a3) negx (a4)+ negx -(a5) negx $1234(a6) negx $12(a1,a2) negx abs.w negx abs nop nop:: nop nop not:: not d1 not (a3) not (a4)+ not -(a5) not $1234(a6) not $12(a1,a2) not abs.w not abs nop or:: or d1,d2 or (a3),d4 or (a4)+,d5 or -(a5),d6 or $1234(a6),d7 or $12(a1,a2),d2 or abs.w,d3 or abs,d4 or .1(pc),d5 or .1(pc,a2),d6 or #$1234,d7 .1: nop or d1,(a2) or d2,(a3)+ or d3,-(a4) or d4,$1234(a5) or d5,$12(a6,a7) or d6,abs.w or d7,abs nop ori:: ori #$1234,d1 ori #$1234,(a3) ori #$1234,(a4)+ ori #$1234,-(a5) ori #$1234,$1234(a6) ori #$1234,$12(a1,a2) ori #$1234,abs.w ori #$1234,abs nop or #$1234,d1 or #$1234,(a3) or #$1234,(a4)+ or #$1234,-(a5) or #$1234,$1234(a6) or #$1234,$12(a1,a2) or #$1234,abs.w or #$1234,abs nop or #$ff,ccr or #$ffff,sr ori #$ff,ccr ori #$ffff,sr nop pea:: pea (a3) pea $1234(a6) pea $12(a1,a2) pea abs.w pea abs pea .0(pc) pea .0(pc,a2) .0: nop reset:: reset nop rol:: rol.b d1,d2 rol d2,d3 rol.w d3,d4 rol.l d4,d5 rol.b #2,d1 rol #3,d2 rol.w #4,d3 rol.l #5,d4 rol d5 rol (a3) rol (a4)+ rol -(a5) rol $1234(a6) rol $12(a1,a2) rol abs.w rol abs .1: nop ror:: ror.b d1,d2 ror d2,d3 ror.w d3,d4 ror.l d4,d5 ror.b #2,d1 ror #3,d2 ror.w #4,d3 ror.l #5,d4 ror d5 ror (a3) ror (a4)+ ror -(a5) ror $1234(a6) ror $12(a1,a2) ror abs.w ror abs .1: nop roxl:: roxl.b d1,d2 roxl d2,d3 roxl.w d3,d4 roxl.l d4,d5 roxl.b #2,d1 roxl #3,d2 roxl.w #4,d3 roxl.l #5,d4 roxl d5 roxl (a3) roxl (a4)+ roxl -(a5) roxl $1234(a6) roxl $12(a1,a2) roxl abs.w roxl abs .1: nop roxr:: roxr.b d1,d2 roxr d2,d3 roxr.w d3,d4 roxr.l d4,d5 roxr.b #2,d1 roxr #3,d2 roxr.w #4,d3 roxr.l #5,d4 roxr d5 roxr (a3) roxr (a4)+ roxr -(a5) roxr $1234(a6) roxr $12(a1,a2) roxr abs.w roxr abs .1: nop rte:: rte rtr:: rtr rts:: rts nop sbcd:: sbcd d1,d2 sbcd d3,d4 sbcd -(a1),-(a2) sbcd -(a3),-(a4) scc:: scc d1 scs (a2) seq (a3)+ sf -(a4) sge $1234(a5) sgt $12(a6,a1) shi abs.w sle abs sls d1 slt (a2) smi (a3)+ sne -(a4) spl $1234(a5) st $12(a6,a2) svc abs.w svs abs nop stop:: stop #$1234 stop #$2700 stop #$0000 nop sub:: sub d1,d2 sub a2,d3 sub (a3),d4 sub (a4)+,d5 sub -(a5),d6 sub $1234(a6),d7 sub $12(a1,a2),d2 sub abs.w,d3 sub abs,d4 sub .1(pc),d5 sub .1(pc,a2),d6 sub #$1234,d7 .1: nop sub d1,(a2) sub d2,(a3)+ sub d3,-(a4) sub d4,$1234(a5) sub d5,$12(a6,a7) sub d6,abs.w sub d7,abs nop suba:: sub d1,a2 suba d1,a2 suba a2,a3 suba (a3),a4 suba (a4)+,a5 suba -(a5),a6 suba $1234(a6),a7 suba $12(a1,a2),a2 suba abs.w,a3 suba abs,a4 suba .1(pc),a5 suba .1(pc,a2),a6 suba #$1234,a7 .1: nop subi:: sub #$1234,d1 subi #$1234,d1 subi #$1234,(a3) subi #$1234,(a4)+ subi #$1234,-(a5) subi #$1234,$1234(a6) subi #$1234,$12(a1,a2) subi #$1234,abs.w subi #$1234,abs .1: nop subq:: subq #1,d1 subq #2,a2 subq #3,(a3) subq #4,(a4)+ subq #5,-(a5) subq #6,$1234(a6) subq #7,$12(a1,a2) subq #8,abs.w subq #1,abs .1: nop subx:: subx d1,d2 subx d3,d4 subx -(a1),-(a2) subx -(a3),-(a4) nop swap:: swap d1 swap d2 swap d3 swap d7 nop tas:: tas d1 tas (a3) tas (a4)+ tas -(a5) tas $1234(a6) tas $12(a1,a2) tas abs.w tas abs nop trap:: trap #1 trap #2 trap #15 trap #$f nop trapv:: trapv tst:: tst d1 tst (a3) tst (a4)+ tst -(a5) tst $1234(a6) tst $12(a1,a2) tst abs.w tst abs N nop unlk: unlk a1 unlk a2 unlk a6 unlk a7 ;- ; ; 6502 Opcodes ; ; .6502 .org $f0 tmp: ds.b 1 tmph: ds.b 1 tmp1: ds.b 1 tmp1h: ds.b 1 .org $8000 dc.w $1234 dc.b 12,34,56,78 dc.b 'This is a test of the...',0 dc.w $1234,$5678,$9abc,@777 adc #immed adc abs adc tmp adc (tmp,x) adc (tmp),y adc tmp,x adc abs,x adc abs,y and #immed and abs and tmp and (tmp,x) and (tmp),y and tmp,x and abs,x and abs,y asl abs asl tmp asl asl tmp,x asl abs,x bcc where bcs where beq where bne where bmi where bpl where bvc where bvs where where: bit abs bit tmp brk clc cld cli clv cmp #immed cmp abs cmp tmp cmp (tmp,x) cmp (tmp),y cmp tmp,x cmp abs,x cmp abs,y cpx #immed cpx abs cpx tmp cpy #immed cpy abs cpy tmp dec abs dec tmp dec tmp,x dec abs,x dex dey eor #immed eor abs eor tmp eor (tmp,x) eor (tmp),y eor tmp,x eor abs,x eor abs,y inc abs inc tmp inc tmp,x inc abs,x inx iny jmp abs jmp (abs) jsr abs lda #immed lda abs lda tmp lda (tmp,x) lda (tmp),y lda tmp,x lda abs,x lda abs,y ldx #immed ldx abs ldx tmp ldx abs,y ldx tmp,y ldy #immed ldy abs ldy tmp ldy abs,x ldy tmp,x lsr abs lsr tmp lsr lsr tmp,x lsr abs,x nop ora #immed ora abs ora tmp ora (tmp,x) ora (tmp),y ora tmp,x ora abs,x ora abs,y pha php pla plp rol abs rol tmp rol rol tmp,x rol abs,x ror abs ror tmp ror ror tmp,x ror abs,x rti rts sbc #immed sbc abs sbc tmp sbc (tmp,x) sbc (tmp),y sbc tmp,x sbc abs,x sbc abs,y sec sed sei sta abs sta tmp sta (tmp,x) sta (tmp),y sta tmp,x sta abs,x sta abs,y stx abs stx tmp stx tmp,y sty abs sty tmp sty tmp,x tax tay tsx txa txs tya abs = $5ba immed = $11 s CONV65(1) UNIX Programmer's Manual CONV65(1) NAME conv65 - convert 6502 object files SYNOPSIS conv65 [ -c ] [ -z[ADDR] ] [ -8 ] [ -rADDR ] [ -iADDR ] file[.o] DESCRIPTION The object file is converted to S-records or an Atari DOS-II format binary loadfile. If the input filename has no exten- sion, ".o" is automatically appended. The default conversion is to S-records (unless -8, -r or -i is specified). The output filename is the name of the input file, with a extension of ".sr". For DOS load files, the output filename is likewise the name of the input file, with a extension of ".obj". Options: -z[ADDR] Specify a starting address. If no hexadecimal address ('ADDR') is specifed then the starting address of the data will be zero, otherwise the data will be emitted with the specified starting address (e.g. -z4000 will generate S-records or an Atari loadfile that starts at $4000, regardless of the origin of the code in the object file). All following pages will likewise be moved down, relative to the first page. (This allows downloading to EPROM programmers that do not accept offsets). -c This specifies that "holes" of zero in the ROM image are to be explicitly filled with zero. For instance, if your program contains uncompressed s4creen images that contain pages of zeros, you may need this option to generate a correct ROM image. -8 Produce an Atari DOS-II format binary loadfile. -rADDR Produce an Atari DOS-II format binary loadfile and set the program's run address to 'ADDR', a hexadecimal address. -iADDR Produce an Atari DOS-II format binary loadfile and likewise set the program's init address. Printed 6/4/87 21 November 1986 1 CONV65(1) UNIX Programmer's Manual CONV65(1) SEE ALSO MADMAC Reference Manual Atari DOS-II Manual BUGS Since the object code format sucks, this utility requires some wierd switches in an attempt to fix the problems. It's the assembler that really needs to be fixed. DIAGNOSTICS bad object file (pagemap entry >= 2) : garbage object file bad address : illegal hex address specified for -r or -i Printed 6/4/87 21 November 1986 2 N`z  oJ g.y # (Ш#pB0"HrtM`$JrtM I`HzHW?NBgNAJg4< g< gRBJAkS/XAg< g< fJAkB(`N 9$"/gRԁ"m#NupNu#Nu X-123456789**NVv nn.hN>N =|`T n 2n p -f n 2n p(H`3#`.j n 2.H/0TavX3 `.h n 2.H/0TaNX3 `3.N`R3`H n 2n p(H>/<NX>N `H |r W h$N`L n 2.H./zN XBW/</zNPBW/zN X=@|f.z/<NX`>/9/zNPBW/zN 6X=@l >N b.z/<NX>?.?.aX yfLJy g>/<h/<?.a Jy g>/<j/<?.a >N b>N bBy By Rn0.nmN^NuNV./?.N \Hg .a"Bn`(0nJ(g0n (g .aRn nmJyg=|`BnBn`0n (f./?.N \Hg .'a nf=n0. `\0.n@H-@>//.?. aZ `60.@H-@>//.?. a& ` ` J@g|gRn nmN N^NuNVBn`lBn` 0n"<0H"nHAgRn0n"<J0f0n"<J0f.ea no]n0.@n=@R nJf0.|"n 0.@|"n @N^NuNVH .N H(@S :gP` \fR`SbJng*L`RJg .fB*L`Jf. / N X`R .f .JL0N^Nu#d WaJ@j?<=NATO ydN#d WarJ@j?<<`#d Wa\J@j?<A`#d0|l ?<>NATO ydNp?`p@ O/(/( ?( Pl ?NA Nuar NuC20k*$Y/<Am<Zn< fJ(f _fNu    con:aux:prn:mid:H6/|6;0&o(/ gp???<NM\OSfLNu"_0H@??9r?<NM\OL< f< `NNV. H>N PN^NuX?<LNAJ C"D"/&/f r`@pe:fpr`2t(ȼf 0BAHA`Ԃed`ef&( Nu C"/lD&/nm <"`\Df r`:pmn2pr`,tl 0BAHA`Ԃփd`efJojDDJojD#l&Nu////N P Nu////N P NuNVH*n(n &Mf JL8N^NuNVH*nBG`RGRJf0JLV N^NuNVH*n(n &MJfSf JL8N^NuNVH /?.?./ /. nN*@ мfB(n ` %H| l|0`Jngp7`pW@ мfB JL0N^NuNVH*n<.H n0H.JngJl D. n P-"n R`μ`./N XH. 9lHJf JL N^NuNVH *n:.H n., nf x` HSDJgJDf` nf*x ` HSDJgJDfJDf-`Jng\Jl2 n P-"n Rf(|v0HfS `R D.`//N PH//N P.Jf`$`//N |PH//N P,Jf JL0N^NuNVHIBBn .RdRn-\ fRn-\*\&L`"(K<%gH>/?.a"\`BnH|-fRn| <0fG=|`"JnlBn0. HA|=@<0m<9o=|<.fBn`0. HA|=@<0m<9oBn<lfRnA-HH`JJng -| `-| BW/.?<?< // N TJngT`BW/< Bg?< // N T`Jng -| `-| BW/.Bg?<// N TJngT`Jng -| `-| <XgBW`>/.Bg?<// N TJngT`R-\&L`J=[0.H@B.`6H>/?.a&\``|C|5b@0@ PN.N =@0.nl Jnm=n0.n=@Jnf^ . g. n -f$Sn nH>/?.a\R`.H>/?.a\0.SnJ@n` nH>/?.aV\R0.SnJ@f`.H>/?.a,\0.SnJ@nf nf nBJL8N^NuNV0.`<.H>N P`< n ..H?N zT`$ n P"n R``J@g|gʰ|g.HN^Nu0123456789ABCDEFabcdefd 8IRXZirxzNdd.srUsage: conv65 [-z] [-8 [-rADDR] [-iADDR]] file[.o] .obj~(Debugging ON)~ Unknown switch: '%c' .oCannot open: %s Cannot create: %s header read errorbad object file (pagemap entry >= 2)object read errorwrite errorwrite errorS1nnaError: %s bad address<&PPPPPPPPPPPPP4PpPPPPPPPPPPPP<&PPPPPPPPPPPPP4PpPP 6F". D    0    0*> h   R"j6    ^P$lb,F @   *`R2 25 .title 'Example Program' ;-H ; : ; Silly Example Program : ; : ;- : ; 30-Nov-1986 lmd Hacked it up from previous brontos. : ; : ;-H .include atari ; include Atari ST equates and macros ;- ; ; Display a message, ; display an interesting icon, ; wait for a keypress, ; and then exit. ; ; Puts #.message ; print message Super ; get into supervisor mode lea icon(pc),a0 ; a0 -> form lea .ret(pc),a6 ; a6 -> return address moveq #26,d6 ; horizontal offset (/2) bra monoicon .ret: User ; back to user mode Bconin #CON ; wait for a keystroke Pterm0 ; and terminate .message: dc.b $1b,'E','Press any key to exit...',13,10,0 .even ;- ; ; A cute icon ; (This is a monochrome mask, generated by NEO and ; massaged by hand somewhat). ; ; icon: dc.w $3f-1 dc.w ($12/2)-1 dc.w $F,$F,$F,$F,$F,$F,$F,$FFFC dc.w $0,$8000,$0,$0,$0,$0,$0,$0 dc.w $0004,$0,$8000,$0,$0,$0,$0,$0 dc.w $0,$0007,$8000,$8000,$0,$0,$0,$0 dc.w $0,$0,$0006,$8000,$8000,$0,$0,$0 dc.w $0,$0,$0,$0005,$8000,$8000,$0,$0 dc.w $0,$0,$0,$0,$0006,$8000,$8000,$0 dc.w $0,$0,$0,$0,$0,$0005,$8000,$8000 dc.w $0,$0,$0,$0,$0,$0,$0006,$8000 dc.w $8000,$0,$0,$0,$0,$0,$0,$0005 dc.w $8000,$8000,$0,$0,$0,$0,$0,$0 dc.w $0006,$8000,$8000,$0,$0,$0,$0,$0 dc.w $0,$0005,$8000,$8000,$0,$0,$0,$0 dc.w $0,$0,$0006,$8000,$8000,$0,$0,$0 dc.w $0,$0,$0,$0005,$8000,$8000,$0,$0 dc.w $0,$0,$0,$F000,$0006,$8000,$8000,$0 dc.w $0,$0,$0,$0001,$8800,$0005,$8000,$8000 dc.w $0,$0,$0,$0,$0002,$0400,$0006,$8000 dc.w $8000,$0,$0,$0,$0,$0004,$4400,$0005 dc.w $8000,$8000,$0,$0,$0,$0,$0008,$B800 dc.w $0006,$8000,$8000,$0,$0,$0,$0,$0011 dc.w $0,$0005,$8000,$8000,$0,$0,$0,$0 dc.w $0022,$0,$0006,$8000,$8000,$0,$0,$0 dc.w $0,$0044,$0,$0005,$8000,$8000,$0,$0 dc.w $0,$0,$0088,$0,$0006,$8000,$8000,$0 dc.w $0,$0,$0,$0110,$0,$0005,$8000,$8000 dc.w $0,$0,$0,$0,$0210,$0,$0006,$8000 dc.w $8000,$0,$0,$0,$0,$1C20,$000C,$7005 dc.w $8000,$8000,$0,$0,$000F,$F,$E020,$0002 dc.w $8006,$8000,$8000,$0,$0,$07F0,$0,$0040 dc.w $0009,$2005,$8000,$8000,$0,$0,$3800,$0 dc.w $0040,$0015,$5006,$8000,$8000,$0,$0,$4000 dc.w $0,$0080,$0022,$8805,$8000,$8000,$0,$0001 dc.w $8000,$0,$0100,$0024,$C806,$8000,$8000,$0 dc.w $0002,$0,$0,$0200,$0009,$2005,$8000,$8000 dc.w $0,$0004,$0,$0,$0400,$0011,$1006,$8000 dc.w $8000,$0,$0008,$0,$0,$0400,$0012,$9005 dc.w $8000,$8000,$0,$0030,$0,$0,$0200,$0001 dc.w $0006,$8000,$8000,$0,$01C0,$0,$0,$0E00 dc.w $0002,$8005,$8000,$8000,$0,$1E01,$FC1F,$00FA dc.w $3100,$0001,$0006,$8000,$8000,$000F,$E00F,$0220 dc.w $FF04,$4880,$0002,$8005,$8000,$8000,$07F0,$01F0 dc.w $0B20,$0004,$4580,$0001,$0006,$8000,$8000,$7800 dc.w $3E00,$1990,$0008,$8300,$0002,$8005,$8000,$800F dc.w $F,$E000,$1CF0,$000F,$8000,$0005,$4006,$8000 dc.w $BFFF,$F,$F,$F,$F,$F,$F,$FFF5 dc.w $8000,$8000,$0,$0,$0,$0,$0,$0 dc.w $0006,$8000,$8000,$0,$0,$0,$0,$0 dc.w $0,$0005,$8000,$8000,$0,$0,$0,$0 dc.w $0,$0,$0006,$8000,$8000,$0,$0,$0 dc.w $0,$0,$0,$0005,$8000,$8000,$0,$0 dc.w $0,$0,$0,$0,$0006,$8000,$8000,$0 dc.w $1E00,$0004,$01E3,$8F00,$0,$0005,$8000,$8000 dc.w $0,$1138,$E78E,$3914,$5000,$0,$0006,$8000 dc.w $8000,$003F,$9E25,$1444,$4514,$4E3F,$8000,$0005 dc.w $8000,$8000,$0,$1121,$1444,$4514,$4100,$0 dc.w $0006,$8000,$8000,$0,$1E20,$E442,$39E3,$9E00 dc.w $0,$0005,$8000,$8000,$0,$0,$0,$0 dc.w $0,$0,$0006,$8000,$8000,$0,$0,$0 dc.w $0,$0,$0,$0005,$8000,$8000,$0,$0 dc.w $0,$0,$0,$0,$0006,$8000,$8000,$0 dc.w $0,$0,$0,$0,$0,$0005,$8000,$8000 dc.w $0,$0,$0,$0,$0,$0,$0006,$8000 dc.w $8000,$0,$0,$0,$0,$0,$0,$0005 dc.w $8000,$8000,$0,$0,$0,$0,$0,$0 dc.w $0006,$8000,$8000,$0,$0,$0,$0,$0 dc.w $0,$0005,$8000,$F,$F,$F,$F,$F dc.w $F,$F,$FFFE,$8000,$3555,$5,$5,$5 dc.w $5,$5,$5,$5,$8000,$2AAA,$A,$A dc.w $A,$A,$A,$A,$A,$8000,$3FFF,$F dc.w $F,$F,$F,$F,$F,$F,$8000 ;- ; ; Monochrome-image icon draw ; [This is probably slow, but it doesn't HAVE to be fast] ; ; Passed: a0 -> icon form (see below) ; d6 = horizontal offset (in source word) ; a6 -> return address ; processor in supervisor mode ; ; Uses: d0-d5/a0-a2 ; ; An icon form has the simple structure: ; ; dc.w lineCount-1 ; "DBRA" number of scanlines ; dc.w widthCount-1 ; "DBRA" number of words/line ; dc.w ...data... ; image data (by scanline) ; monoicon:: move.w (a0)+,d4 ; d4 = height of form - 1 move.w (a0)+,d3 ; d3 = width of form - 1 move.b shiftmd,d7 ; get video resolution and.w #$0003,d7 ; (strip naughty bits) add.w d7,d7 ; d7 = rez index moveq #0,d0 ; compute base address move.b dbaseh,d0 ; dbaseh<<16 + dbasel<<8 lsl.w #8,d0 ; + middle_of_screen move.b dbasel,d0 lsl.l #8,d0 move.l d0,a2 add.w .middle(pc,d7.w),a2 ; a2 -> base of mem to draw at move.w d6,d0 ; d0 = hoffset * dest width mulu.w .wmult(pc,d7.w),d0 add.w d0,a2 ; adjust horizontal position .3: move.w d3,d2 ; d2 = width - 1 (loop count) move.l a2,a1 ; a1 -> start of line .2: move.w (a0)+,d f0 ; get form word move.w .nplanes(pc,d7.w),d1 ; d1 = #planes - 1 .1: move.w d0,(a1)+ ; dump a form word in dbra d1,.1 ; (do more planes) dbra d2,.2 ; (loop for entire line) add.w .width(pc,d7.w),a2 ; a2 -> start of next line dbra d4,.3 ; (loop for entire form) jmp (a6) ; "return" to caller .middle: dc.w 100*160,100*160,200*80,200*80 .nplanes: dc.w 3,1,0,0 .width: dc.w 160,160,80,80 .wmult: dc.w 8,4,2,2 J ;-H ; : ; Example #1 : ; : ;-H pea string(pc) ; Cconws(&string) move.w #9,-(sp) trap #1 addq #6,sp clr.w -(sp) ; Pterm0() trap #1 illegal ; "cannot return" string: dc.b "Hello, world!\r\n",0 { ;-H ; : ; Example #2 : ; : ;-H .include atari ; include "atari.s" ST definitions Puts #string Pterm0 string: dc.b "Hello again, world!\r\n",0 * images.s .globl _images .globl _masks _images: dc.l a_i2 dc.l a_i1 dc.l a_i0 dc.l 0 ; end of table _masks: dc.l a_m2 dc.l a_m1 dc.l a_m0 dc.l 0 ; end of table a_i0: dc.l i0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 a_m0: dc.l m0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 a_i1: dc.l i1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 a_m1: dc.l m1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 a_i2: dc.l i2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 a_m2: dc.l m2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 i0: dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f dc.w $f,$f,$f,$f m0: dc.w 0,0,0,0,0,0,0,0 dc.w 0,0,0,0,0,0,0,0 i1: .dc.w $07E0,$07E0,$07E0,$0,$1FF8,$1FF8,$1FF8,$0 .dc.w $0FF0,$0FF0,$0FF0,$0,$47E2,$47E2,$47E2,$0 .dc.w $63C6,$63C6,$63C6,$0,$F5AF,$F5AF,$F5AF,$0 .dc.w $DA51,$DA51,$DA51,$0,$9DB5,$9DB5,$9DB5,$0 .dc.w $DDB5,$DDB5,$DDB5,$0,$DA51,$DA51,$DA51,$0 .dc.w $F5AF,$F5AF,$F5AF,$0,$63C6,$63C6,$63C6,$0 .dc.w $47E2,$47E2,$47E2,$0,$0FF0,$0FF0,$0FF0,$0 .dc.w $1FF8,$1FF8,$1FF8,$0,$07E0,$07E0,$07E0,$0 m1: .dc.w $f-$07E0,$f-$1FF8,$f-$0FF0,$ff ff-$47E2 .dc.w $f-$63C6,$f-$F5AF,$f-$DA51,$f-$9DB5 .dc.w $f-$DDB5,$f-$DA51,$f-$F5AF,$f-$63C6 .dc.w $f-$47E2,$f-$0FF0,$f-$1FF8,$f-$07E0 i2: .dc.w $0,$0,$0,$0,$0180,$0,$0,$0 .dc.w $0180,$0,$0,$0240,$0180,$0,$0,$0 .dc.w $07E0,$0,$0,$0,$1FF8,$1818,$1B18,$0 .dc.w $2FF4,$2004,$2304,$0,$4FD2,$4002,$4602,$0 .dc.w $3FDC,$300C,$360C,$0,$4FD2,$4002,$4602,$0 .dc.w $4FB2,$4812,$4812,$0,$1768,$1008,$1008,$0 .dc.w $13C8,$1008,$1008,$0,$1008,$1008,$1008,$0 .dc.w $0,$0,$0,$0,$0,$0,$0,$0 m2: .dc.w $f-$0,$f-$0180,$f-$03C0,$f-$0180 .dc.w $f-$07E0,$f-$1FF8,$f-$2FF4,$f-$4FD2 .dc.w $f-$3FDC,$f-$4FD2,$f-$4FB2,$f-$1768 .dc.w $f-$13C8,$f-$1008,$f-$0,$f-$0  .title 'Install MADMAC From AUTO Folder' ;- ; ; 2-Nov-1986 lmd Hacked it up (we need example programs, right?) ; ;- ; ; Shrink as small as possible (by relocating to the commandline ; part of the basepage) and exec MAC.PRG from the root of the ; boot disk.This example program is for floppy disk users who ; don't like installing MADMAC manually every time they boot. ; ; This leaves a *small* memory fragment, less than $100 bytes. ; ; The coding style here is, er . . . bizarre. I suggest the reader ; treat it as an excercise in paranoia, and not as an example ; of good coding practice. As jwt sez, "this should only be ; attempted by experienced software engineers." Or madpersons. ; ; bra.w movedown ; branch to shrinker BEGIN: lea END(pc),sp ; then come back here and init stack move.l d0,-(sp) ; = amount to keep move.l a1,-(sp) ; -> basepage move.l d1,-(sp) ; push WORD 0x0 and function number trap #1 ; do Mshrink() add.w #12,sp ; (cleanup) clr.l -(sp) ; null enviroment string pea progtail(pc) ; -Q switch pea progpath(pc) ; -> program to exec move.l d7,-(sp) ; subfunc=0, function=Pexec() trap #1 clr.w -(sp) ; terminate, return code = OK trap #1 illegal ; "cannot happen" progpath: dc.b '\\MAC.PRG',0 ; program to exec, in the root dir progtail: dc.b '*-q',0 ; command tail (the '*' gets clobbered) dcb.b 64,0 ; 64 bytes of user stack END: ; end of kept part ;- ; ; Copy code from BEGIN to END into commandline area of basepage; ; this code (and everything beyond it) is thrown away by an ; Mshrink() in the kept portion. ; ; Returns: d0 = amount of memory to keep; ; d1 = Mshrink code + word of zero ; d7 = Pexec code + subfunction zero ; a1 -> process's basepage ; ; movedown: move.l 4(sp),a1 ; a1 -> basepage lea $80(a1),a2 ; a2 -> basepage's command tail area lea BEGIN(pc),a0 ; a0 -> start kept portion (right now) move.w #END-BEGIN+1,d0 ; d0 = size (bytes-1) of kept portion .1: move.b (a0)+,(a2)+ ; copy a byte dbra d0,.1 ; until we're done move.l #$80+END-BEGIN,d0 ; d0 = amount to keep on Mshrink move.l #$004a0,d1 ; d1 = Mshrink + word of zero move.l #$004b0,d7 ; d7 = Pexec + subfunction zero jmp $80(a1) ; jump back to kept portion `B?< NA\O/?< LNA\O f f/+Nu/<L?< NA\O?<?<LNAJMADMAC not installed; use "MADMAC -Q" to install it 4\`JG*%& oJg.y# (Ш#pB0"HrtM`$JrtM I`HzHW?NBgNAJg4< g< gRBJAkS/XAg< g< fJAkB(`N 9$"/gRԁ"m#NupNu#Nu NVBy+>N no. X?.SWaFT=@`BnaJnf BWN` >NN^NuNVH*|˄./<ˣNX./</<J/<N 3+.N|8.8?< N:T> NTK8.9H|`0SFJ@fBBGK8`vHHм @(gR`Z|dm.N`z0G!MRG`RJgHHм @(gHHм @(gBJfJGgN(-@.?aTJy5g, y5o./`.1?95/<N\N(-@/< /</.NP/NP./</.NP/?9.j м8мr / 9,Pмr //<2/8N.8N`:JL N^NuNVH B.bB+B+B+35$B+By.vBy+By5By,`By+By+rBy+|By+By5&3++By1By+By+3,NBWNNvNN"|N.NHN ZN_NZNBG`$ n 2G p -fp n 2G p(H`> n 2G pJ(g n 2H 0T#+`0RG0nm.cNRy5`0G #+` n 2H 0T#+` n 2H 0T#+3,`3+Ry5` n 2H.TNú3 Z y  Zl.zNRy5`x`jJ.bf #P.bBW/<̏NX<.̔?NyTN `, n 2H 0T#+`35&3+r`N3+`0G *PT` =fB-`Jf n 2G pJ(f.̛NRy5` n 2H.TN(@ f"BWBg n 2H/0TNL\(@B9|Jg.Nú)@`B`> n 2G p(H`nBy+`|3+ n 2G p(H`3+`"` .̭N`J@g|Ugܰ|ug``..NRy5``H |lrW hN` n 2G p(H`,3+`43+`*.NRy5``J@gа|Sg԰|sg``H3+|`>`< n 2H./<NXRy5``H |ʜrW hpN`J.bf0G #.b n 2H./NLXBW/</NPBW/NX<JFl./<NXRy5`.?NyTN RGnmN0D>a>az>arJ+f\J.bf #P.b..b/NLX>Jy+g/<"`/<'/NPA#+N3.NrJy5fzBW/9+N:X<l .+aJy+g.Jy+g <*` <5*@.+/ /<N>NfJy5g .+NPJy+g.Jy+g .SN3,`Nb>+NfJy+g >5$Nf095JL0N^NuNV./<oNX>NN^NuNV>N/tNCBN0DN^NuNVH >. *n(y+ f.̈́N(@ fB@`.` Jg ;f0SGJ@fJfB@``Jg ;fBpJL0N^NuNVByt#v/B#v#|ByzN^NuNVHBnN}|ff.Jy+g JngN y/Jg .N\`Jy+g>JngJy,`oNJytg>-` 9/H>N=|By,^~BB+B-y1#'D/ y1 egP y1 cg."N\`2 y1 (<|=g|gg |Sg|Rf y1-h=F 1`|:g|hfX y1-h y1 (=@ 1Jy5&g,Bn y1 cf y1 :f =|` y1 eg y1 c@X1Dg."N\`T y1*P-MX1.l/</<Ԩ/<͌/ N^>=| y1 Wf=|X1`6 y1 Lf=|X1` y1 Bf =|X1|mN|lF0`(a`a`a`Jytf.///<,bN" J@fZ0.|f.N\`@ y1 ,@X1Dg.N\`Jg`JytfJg .*NN_`JytfJg .*NNe`JytfJg .*NNe`Jytf .N\``|| b@0@V PNJytfdJghBF n .f<95>Bg/.N\-@JfD>Bg/.NL\-@ nBh ngfJFg.&N\` n1|@`0 n0(|g" nSg n./<NX` n(f .N nRf*.N!J@m0.-@=|`0.///<,bN" J@fD0.|f.N\`*0.|"nԁi n!nJy+g .NZa `JgBF n .f<95>Bg/.N\-@Jf>Bg/.NL\-@ nBh`$ n0(|g./<NX` n(f .N n!y'D09,\|"nԁi#+JFfRy5 nhfJFg.&N\` nh@Jy5&gJnf"|gJy1gJJGm|m@."/<ޒ/<Z/<0/.N^>|m>W0N `JGl@BW?</.N\-@g>/.NcLX`./<2NX`f|l?.0G"| pNT`D95g.BN\`*9'GgN: 9+t5dBN00|м-@ n0|g?. n?( n hNX`>N J@m y1 eg .N\0y.h.-P0y.l.-P nf$ y.hg y.lf.nN\`D n02.Ag8 n (g* n (g?. n?( n hNX` n0( м-@`JL N^NuNV y1 eg .N\N^NuNVH*y| f.N0*@`#|*/#/JytfP./U/]/<,bN" J@f20.|f.N\`JgB@`p3t;ytJL N^NuNVH*y/Jf.N\`$Jytg U3t`3t;ytJL N^NuNVH*y/Jf.N\`#/ U3t*|#|JL N^NuNVB@3+p3+n35pI3.l3.hpE#)j#3$#'j#1$B@3'X3'd3'R3'bB#1 #1 y1 efB@` y1 e2 y1 b$By.h y1 3+nX1` y1 e4 y1 b&3.h y1 3+nX1` y1 #f@X1.1/<'b/<'J/<1$N" J@gp` :3<.h` y1 (f8X1 y1 ev y1 bf y1 3+nX1 y1 )f0X1 y1 +fX13.h`3.h`30.h`"` y1 ffX13;.hB'J3'b y1 ,@X1Df 4 y1 e $ y1 b  y1 3'BX1 y1 `$X1By+j`*3+jX1`` `|Bg|Lgް|Wg` y1 *fX1 y1 a@X1Df y1 b x y1 X1`&`>y+j`4y+j`*y+j` ` D`|g԰|gа|g԰|g` y1 )@X1Df ``6 y1 [f` ` .1/<'b/<'J/<1$N" J@gp` y1 ,@X1Df y1 el y1 b^ y1 3+nX1 y1 ,f30.h` `& y1 )f3(.hX1``` 0`\ y1 fJX1 y1 ,f3;.h``& y1 )f3:.hX1`T`````D y1 -fl y1 (f\ y1 eL y1 b< y1 ) f,3 .h y1 (3+n1` y1 f3H.hX1`` y1 f3G.hX1`` y1 f3F.hX1`b`^.1/<'b/<'J/<1$N" J@gp` y1 WfX138.h``b y1 (gT39.h09'b||f 9'Jмd38.h y1 LfX139.h`X1 y1 eT y1 bF y1 3+nX1 y1 )f3(.hX1`P30.h``> y1 f0X1 y1 )f3:.hX1`3;.h`D`35Jng y1 ,gp`X1 y1 e2 y1 b$By.l y1 3+pX1` y1 e4 y1 b&3.l y1 3+pX1` y1 #f@X1.1 /<'d/<'N/<3$N" J@gp`3<.l` y1 (f8X1 y1 ev y1 bf y1 3+pX1 y1 )f0X1 y1 +fX13.l`3.l`30.l`"` y1 ffX13;.lB'N3'd y1 ,@X1Df y1 e y1 b y1 3'HX1 y1 `$X1By+l`*3+lX1``N`|Bg|Lgް|Wg` y1 *fX1 y1 a@X1Df y1 b y1 X1`&`>y+l`4y+l`*y+l` ``|g԰|gа|g԰|g` y1 )@X1Df`~`6 y1 [f`` .1 /<'d/<'N/<3$N" J@gp`\ y1 ,@X1Df( y1 el y1 b^ y1 3+pX1 y1 ,f30.l` `& y1 )f3(.lX1````\ y1 fJX1 y1 ,f3;.l``& y1 )f3:.lX1`R``X``R`B y1 -fl y1 (f\ y1 eL y1 b< y1 ) f,3 .l y1 (3+p1` y1 f3H.lX1`` y1 f3G.lX1`` y1 f3F.lX1```\.1 /<'d/<'N/<3$N" J@gp`T y1 WfX138.l``b y1 (gT39.l09'd||f 9'Nмd38.l y1 LfX139.l`X1 y1 eT y1 bF y1 3+pX1 y1 )f3(.lX1`N30.l``> y1 f0X1 y1 )f3:.lX1`3;.l`D` 35p`.N\` .N\N^NuNVHBG y1 e& y1 b y1 <X1`` y1 -f^X1 y1 e& y1 b y1 :X1`.N\`RFl.2N\`@F`BE`0F0@RF0SEJ@l y1 /f X1`* n0B@JLN^NuNVHBG` 0GBRG|mBG*|`JfRG`0HHҼ"AR fJL N^NuNVH*n# y1 ag y1 cf0 y1 h l y1 afH y aX y1 ("n ""y"X n0Jg nB` y1&hBG .f>95>Bg/ N\(@ f>Bg/ NL\(@l y cX y X0,|g n ` n B0,|"n20,||@f Jg n P1 y EXB@`4a`& y1.X1a6J@gp`$ y X y1 P lB@JLN^NuNVH y1 P"<0H> y1 -g|f8 y1,X1aJ@gp`漼-f|n y X`Ⱦ|f y1 X1` y aXN&/ y X`| y aXN/ y X`P y1 c@X1Dg.N\`0 y1-PX1BW?</.N\JfBn`=| y aX0."y"X`=|`=| y1 c@X1Dg.N\` y1-PX1Bn n .f=y5>Bg/.N\-@g n0(2.Ag=|`Bn y aX0."y"X` y1 cg y1 bg.N\` y1-hP1 y1 ,@X1Dg.N\` y1 cg y1 bg.N\` y1-hP1./.NXJ@gB@`p=@ y aX0."y"X``|p| b@0@ PN`a`B@JLN^NuNVH y1 X1` y aX y"y1 X1X` y1*PX1BG .f>95>Bg/ N\(@ f>Bg/ NL\(@ y cX y X`\ y aX y1.a/ y X1X`$aJ@gp` y1 )@X1Dg.[N\``aHJ@gp` y1 ]@X1Dg.yN\`` y AX y 'DX09,\|"y"X`j y AX y /X09,\|"y"X`&.N\``H |BrW hNB@JL0N^NuNVH(|*|B`. n X` n&PXk0+|f4+f nBP n BB@` Jg.N\` -K0+|gX(`XBT0+|:`X n(XT:`X n(XT n :X`xYU ,є0|f:`0-|g.N\`z`BYU ,>|JGf:`*0-|g 0-2Af.N\`8`U`0|g .N\ D(:`0|g .N\JgB@`p(:`0|g .N\ F(:`UY0|2-|Ag .N\: cB@`p(`NUY0|2-|Ag .N\: dB@`p(`UY0|2-|Ag .N\: bB@`p(`UY0|2-|Ag .N\: eB@`p(`UY0|2-|Ag .N\: fB@`p(`NUY0|2-|Ag .N\: gB@`p(`0|f0%|g .N\: n (`Y/,/NP(`YJf.N\`/,/NP(`YJf.N\`/,/NP(`\Y", (`NY", (`@Y ,`6Y ,`,Y ,`">N`H |rW h N`H |rW h8N n EfJgUJg n n0 n B@JL8N^NuNVH*nB`H|RJf JL N^NuNVHBG` BW?aTTRG|m>BgaBT>?<a6T>?<a*T>?<aT>?<aT>aHJLN^NuNVH0.*@%: BB+@+@ B+@+@JL N^NuNVH ngB@`p313,\0.*@%35#'D# .#'f(y. g"# +t#5 ,й5#1`B#5#+t(y'f g"# +x#+ ,й+#5`B#+#+xJL0N^NuNVH 09,\*@%:5+y'DJ.g y.!y5J'fg y'f!y+JL0N^NuNVH ..95fJf~ 9+t5cd.<09,\(@%.N0*@J.f B)M`+y. y. y.!y5+y'DB +@ #+tB+@#5A+H #1 )@ #.JL0N^NuNVH n cf n Ef~`Pn B`( Ю @ ag Ю @ cfRR Ю @ EfR.޼ 9+x+c09,\(@%.N0*@J'ff B)M`+y'f y'f y'f!y+B <+@ #+xB+@#+A+H #5 )@#'f y50T5 y5 X5 y50+T5 y50+T5. g2 "y52T5` y5"n XX5 SJf` y5"n X5߹+JL0N^NuNVHJy+rgN >a>a>a JLN^NuNVH 0.м%-@ n-hJg< n-hJg* nf n"n!i  n-h n*h` n>T n-PX n3+T n3+TB n (b n ("n")ЁbP n-h`. n (b n ("n")Ёb n-PJfJf >N n(h ."n")g^ n=PT.///.N* J@g0.Ѯ`0.Ѯ`D n-PX n=h0.|g n-h`B0.||@f-n0.|=@0.|fJf.N\`Jg0.|gX0.ڰnf .쑮`Jng.N\`Jy+|g$g .мd .N` y+f .쑮Bnn0|`0.|f.0N\`U .мd|Jf.FN\`rR .H`VR0.|f.eN\`HJng.}N\`2g .мd g .мd` d .H`0.|f,g><`BG.?Bg/.?.N `hJngBBg?./.?.N g .мlf`* g .мdJ` .谼d: ng .H .H` .H .H`0.|f .?<Bg/.?.N `$JngB?<?./.?.N .rH .rH .H .H`0.|f.N\`~ ef b\ .`F .R .мd, .H` >N`|b@0@ PN` .N\b n-PJfJL0N^NuNVH Nr0.м% @*h`-m(n` n>T n,0| @"<0H܀XX f0| @"<0H`6g n>T0Ѯ`Xbz*U f`B@JL0N^NuNV.N\N^NuNVB/U/./<,bN" J@lp`20.|f.N\`0.|g.N\`B@N^NuNV y,\g>95gR'D` y1BR1R'DR5J+g y+RN^NuNVH*| y1 cg .N\`J y1/( nNXJ@f4P1 y1 eg y1 ,g .N\`X1`JL N^NuNVH y1 bfX1 y1*P`Z y1 cflBF`b.Nn>JGo$0GSH (\g.@/NÒX./NÒXBW/NX>l0RF.?/<8N \J@f./<BNX` .?NyTJL0N^NuNV`@0.|f.TN\`NJf.qN\`: y1 ,f&X1B/U/]/<,bN" J@gNN^NuNVJy1g. N\` .N/tN^NuNVJy1g. N\` y,\gN0D>N/tN^NuNVJy1g. N\` y,\gN0D>N/tN^NuNVH>. y,\g6Jy5&f95f.N\`|g9'Gga.Ya,J@f95f y,\fL.NZ0//.NP-@ .ѹ'D y,\f .ѹ13,^`B?<B?/.a NJLN^NuNVH>.95g.N\` y,\g|g9'Gga|f y1 bf y1 ,g y1 eff y1.Nn( 9+t5c.N0 y1*h` y1R1R'DR5RJfP1`B/U/]/<,bN" J@f<.|:.| 9+t5d .N00`JEf4.,b/9'D?< N1z\ y1BR1R'DR5`VJFg.N\` .мe.N\`v .H"y1R1R'DR5`4JEfD.,b/9'D?< N1z\ y1BR1 y1BR1T'DT5`JFgBBg?/9'D?9,\N .мm.N\` y,\g8 .H"y1R1 .H"y1R1T'DT5`6 .H"y1R1 .H"y1R1T'DT5`,Jy1g. N\`2JEf`.,b/9'D?<N1z\ y1BR1 y1BR1 y1BR1 y1BR1X'DX5`JFg B?<?/9'D?9,\N .rH"y1R1 .rH"y1R1 .H"y1R1 .H"y1R1X'DX5`"` |gV|g|g|g y1 ,f X1`0NJL N^NuNVJy1g. N\`69'Gg,95f y1BR1R'DR5`R'DN^NuNV95g.N\`.YaJ@f y1 ,@X1Dg.N\`dB//Q/<,bN" J@m@ y,\g ng9'Gga.,b?./.?./.aD N^NuNVH>.95g.N\` y1 #f>X1.Ya(J@f y1 ,@X1Dg.N\``-|B//Q/<,bN" J@m y1 X1`|`(|`$|` <Y1``|Bg|Lg|Wg`.,b?./.?/.aF y1 ``*X1`.N\``|,g|eg``JLN^NuNVH..<.|:.|` 9+t5d .N00. `JEf2./9'D?< N1z\ y1BR1R'DR5`RJFg.AN\`n мe.N\`N H"y1R1R'DR5`JEfB./9'D?< N1z\ y1BR1 y1BR1T'DT5`JFgBBg?/9'D?9,\N <Їe.N\` y,\g4 H"y1R1 H"y1R1T'DT5`2 H"y1R1 H"y1R1T'DT5`"Jy1g. N\`JEf^./9'D?<N1z\ y1BR1 y1BR1 y1BR1 y1BR1X'DX5`JFg B?<?/9'D?9,\N rH"y1R1 rH"y1R1 H"y1R1 H"y1R1X'DX5`"` |gr|g|g|g .SJf$JLN^NuNVH Jy1g. N\` y1 cg.YN\` y1(hP1 .f.&N\`BWBg/ N\*@ fBWBg/ NL\*@`0-|g.hN\`D;|` y1 ,@X1Dg.N\`.]aTJ@f +nNJL0N^NuNVJy+gRy,`N^NuNVJy+gSy,`N^NuNVN0D>N/tN^NuNVH y1 #f*X1.YaJ@f y1 ,fX1`-| y1 cf y1(h .f>95`BG>Bg/ N\*@ f>Bg/ NL\*@Bm`0-|g./<NX`-f.N;|+nP1 y1 ` TX1`|Bg|Lg|WgT` y1 e@ y1 b2.]N!J@m~BF`.gX|@RFDm`B y1 `"TTX1`(`>.N\`0`H |rW hN y1 ,fX1`JL0N^NuNV.KaN^NuNVHBW?</.N\*@ g| B@JL N^NuNV.N\N^NuNV.N\N^NuNV0.H|"y1R10.|"y1R1T'DT5N^NuNVH>.<|g0.  @r0@g,g0y+pb0@`0y+nb0@g`09.ly+p@0H|"y1R10|"y1R1T'DT5g > Nf> Nn`^09.hy+n@0H|"y1R10|"y1R1T'DT5> Nfg > NnJLN^NuNVH>.<. gSG0 @r0@0y+p"<b00y+n@0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. 0 @"<002y+pb2Ay.hy+n@0H|"y1R10|"y1R1T'DT5>NfJLN^NuNVH>.<. g0 @r0@g0y+pb0@|y+n0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. 0H|"y1R10|"y1R1T'DT5>NfJLN^NuNVH>.<. 0H|"y1R10|"y1R1T'DT5>NfJLN^NuNVH>.<. 0y+n"<b002"Ar2Ay+p@0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. 0 @"<r00y+p@09'b|gf 'Jc.N\` 9'Jr 㨎@0H|"y1R10|"y1R1T'DT5`L.1$/9'DBgN1z\0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. Jy.lf0|g.N\``0|g.N\`09.ly+p@ y<.hfB0H|"y1R10|"y1R1T'DT5>Nf`H0y+nb0@0H|"y1R10|"y1R1T'DT5>NnJLN^NuNVH>.<. y+n0H|"y1R10|"y1R1T'DT509'd|g09'd|y,\g.N\`*9'N'D <Ѕc.N\`t H"y1R1 H"y1R1T'DT5`@.3$/9'D?< N1z\ y1BR1 y1BR1T'DT5JLN^NuNVH>.<. Jy.hf Jy.lfz@`< y.hf y.lfzH`$ y.hf:9+p3+n+p3+n:<0y+n"<b00y+pE@0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. y+n0H|"y1R10|"y1R1T'DT5>NnJLN^NuNVH>.<. |fF y<.hfNf y(.lm>NnJLN^NuNVH>.<. yF.hfy+p`y+n0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. 09'b|f".1$/9'DR?< N1z\B'J`" 9'Jмe.N\`^0y+p"<b00"9'J¼@0H|"y1R10|"y1R1T'DT5JLN^NuNVH>.<. |f|@Jy.hf0y+n"<b00y+p@0H|"y1R10|"y1R1T'DT5 y.lf* y1BR1 y1BR1T'DT5`>Nn`0y+p"<b00y+n@0H|"y1R10|"y1R1T'DT5 y.hf* y1BR1 y1BR1T'DT5`>NfJLN^NuNVH>.<. 09'b|g09'b|y,\g.N\`*9'J 9'DT|fJgX мdH @0H|"y1R10|"y1R1T'DT5``` <Ѕc.N\`<0H|"y1R10|"y1R1T'DT5 H"y1R1 H"y1R1T'DT5`м|fd мe.N\` @0H|"y1R10|"y1R1T'DT5` <Ѕe.N\`F0H|"y1R10|"y1R1T'DT5 H"y1R1 H"y1R1T'DT5``|f||fR.1$/9'D?<N1z\0H|"y1R10|"y1R1T'DT5`x`v0H|"y1R10|"y1R1T'DT5.1$/9'D?<`N1z\ y1BR1 y1BR1T'DT5JLN^NuNVH>.<. 0 @"<r00y.ly+p@09'b|gn 'JbJ'Jf.N\` 9'Jr 㨎@0H|"y1R10|"y1R1T'DT5`L.1$/9'DBgN1z\0H|"y1R10|"y1R1T'DT5>NnJLN^NuNVH>.<. 09'b|gv09'b|g.N\`f 'Je.N\`L 9'J@0H|"y1R10|"y1R1T'DT5` .N\JLN^NuNVH>.. g. N\`t n f|@ y1 #f NfJLN^NuNVH>.<. 0y+n"<b002"A2Ay+n@0H|"y1R10|"y1R1T'DT5JLN^NuNVB35B%N^NuNV y1 c@X1Dg.hN\` y1-PX1BW?</.N\Jg.wN\`.l/</<Ԩ/<͌/.N^J@m.N\`tBW?</.NL\-@# nB n1y5Ry5 y1 egB.aN:fNB./<alaXN^NuNVH *n y>?</ N\Jg.N\`* y>?</ NL\(@)yRB@JL0N^NuNVJy+gN>.NJn gj.NnZ@-@.N0-@ nB./.XNLXJf y!n` y #p``B@N^NuNVHJgRy5N}|ff. /<NX.N~ y1 cfF y1 :g y1 hf y1 c f y1*h` y1*h g .fR. / a:X>Jg?/</ nN\>JGg`HJgSy5JL N^NuNVH *n Bn`H(n<Am <Zn< < f Jf0.`&f``RJg  f  fRRnJfpJL0N^NuNVH>Nx&&@(k9n Bn-y1~#1`JGgRn` n X` y1 \f y1 egX1 y1 `@JGg XnX1` y1*X1JGg XnX1` y1*X1``|Ag|ag|cg` y1 ,g y1 efbJGgXn`*e y1 ,fX1 y1 efJGgLJng0..N*@0.R@H.N-@ n %X#%``SG`9n)n n)h)y.r R#.rB@` .+NJL8N^NuNVH `NyJ+g y+ PfJ+f .@N y+*h# .rJmg y%.NY%(y% y%#%.NNyJL0N^NuNVH .YN9J@gp`NBB3.O/<fa$XJg >Nx&*@(m(B)nJL0N^NuNVHJy+gN>#N0. `lSyfB@`l`Ry.NnZ@..N*@B./ XNLXJf#` y #09`` J@g|g`JL N^NuNVH,9'J>9'b|:9'b|09.h``JGgvJEgBBg?/9'D?9,\N <Іe.N\` H"y1R1 H"y1R1T'DT5`@.1$/9'D?< N1z\ y1BR1 y1BR1T'DT5`$JGg09'b|y,\f'D`09'b|g .N\ <Іe.N\` H"y1R1 H"y1R1T'DT5`@.1$/9'D?<N1z\ y1BR1 y1BR1T'DT5`T>9'Bp oy+j09'b|gvJEg.N\`& мe.N\` @0H|"y1R10|"y1R1T'DT5`P.1$/9'DR?< N1z\0H|"y1R10|"y1R1T'DT5`n>9'Bp oy+j09'b|g09'b|y,\f'D`09'b|g .N\ мe.N\` @0H|"y1R10|"y1R1T'DT5`N.1$/9'D?<N1z\0H|"y1R10|"y1R1T'DT5`j0.`fJGghJEg.N\`L мe.N\`, H"y1R1 H"y1R1T'DT5`B.1$/9'DR?< N1z\ y1BR1 y1BR1T'DT5`JGgvJEgBBg?/9'D?9,\N <Іe.N\`l H"y1R1 H"y1R1T'DT5`@.1$/9'D?< N1z\ y1BR1 y1BR1T'DT5`JGgJEg B?<?/9'D?9,\N rH"y1R1 rH"y1R1 H"y1R1 H"y1R1X'DX5`\.1$/9'D?<N1z\ y1BR1 y1BR1 y1BR1 y1BR1X'DX5`.>N`"|g|g@|g|g0``JGgvJEgBBg?/9'D?9,\N <Іe.N\` H"y1R1 H"y1R1T'DT5`@.1$/9'D?< N1z\ y1BR1 y1BR1T'DT5`JGgJEg B?<?/9'D?9,\N rH"y1R1 rH"y1R1 H"y1R1 H"y1R1X'DX5`\.1$/9'D?<N1z\ y1BR1 y1BR1 y1BR1 y1BR1X'DX5`0.N\`$>N`H |ZrW hXNB@JLN^NuNVH,9'N>9'd|:9'd|09.l``JGgvJEgBBg?/9'D?9,\N <Іe.N\` H"y1R1 H"y1R1T'DT5`@.3$/9'D?< N1z\ y1BR1 y1BR1T'DT5`$JGg09'd|y,\f'D`09'd|g .N\ <Іe.N\` H"y1R1 H"y1R1T'DT5`@.3$/9'D?<N1z\ y1BR1 y1BR1T'DT5`T>9'Hp oy+l09'd|gvJEg.N\`& мe.N\` @0H|"y1R10|"y1R1T'DT5`P.3$/9'DR?< N1z\0H|"y1R10|"y1R1T'DT5`n>9'Hp oy+l09'd|g09'd|y,\f'D`09'd|g .N\ мe.N\` @0H|"y1R10|"y1R1T'DT5`N.3$/9'D?<N1z\0H|"y1R10|"y1R1T'DT5`j0.`fJGghJEg.N\`L мe.N\`, H"y1R1 H"y1R1T'DT5`B.3$/9'DR?< N1z\ y1BR1 y1BR1T'DT5`JGgvJEgBBg?/9'D?9,\N <Іe.N\`l H"y1R1 H"y1R1T'DT5`@.3$/9'D?< N1z\ y1BR1 y1BR1T'DT5`JGgJEg B?<?/9'D?9,\N rH"y1R1 rH"y1R1 H"y1R1 H"y1R1X'DX5`\.3$/9'D?<N1z\ y1BR1 y1BR1 y1BR1 y1BR1X'DX5`.>N`"|g|g@|g|g0``JGgvJEgBBg?/9'D?9,\N <Іe.N\` H"y1R1 H"y1R1T'DT5`@.3$/9'D?< N1z\ y1BR1 y1BR1T'DT5`JGgJEg B?<?/9'D?9,\N rH"y1R1 rH"y1R1 H"y1R1 H"y1R1X'DX5`\.3$/9'D?<N1z\ y1BR1 y1BR1 y1BR1 y1BR1X'DX5`0.8N\`$>N`H |rW hXNB@JLN^NuNVH-|By5#+3+3+By+By.j#'TBBBB+B+~B+ /BG`$0G5(0G+B02G.|RG|mBG`&|l0`0]@2GHHҼ5("ARG0GJf~A`0G.| RG|ZoB,0B,B,AB,!W,EW,%L,:L,JLN^NuNVHJf.N0*@`*y y#0.`vJf. N0(@`(y y#+L`TJf.N0&@`&y y#+K`$. N+@``J@g|g|g+y/:+y1 +y'T+y+#+ JL8N^NuNVHJy+g. /<NXBWa(@*l;nB@;@ ;@ ;y++y+;y+Ry+3++. Nt#+By+.N0&@B'y+J+f#+~` y+ #+B@JL8N^NuNVH*y+ g`N -/f# 1#'T0`Jy+g.+/<NX(m(#>Nf#+3+3+`Z&m&#`H m-P` n-P.N-nJf.N``J@gd|g|g#++y#JL8N^NuNVH*y+~`*U g 0.SnJ@f f #+`#+JL N^NuNVH=| y+*hBG<- 6m (K`6  g  f&RG  fFl" , fRGBm m `RGRFmJnfJm g Bm BB`0- Hm&0m SHB(Bm 0- HЍм`Jm g:8m 0- |H&@BG`RGm m0- |;@ .0- H2- HЁЍ/?-N\=@lB`0.m Jm fB``JL8N^NuNVH y+*h(m fB`"+T>/ / Xa

JGl`|JFmJGl &c&`0&BnJg&Jng-M`gH&`g|H`^ =f &kR`&!`m&b&(M`<\fvH`X. N\`<`X< `R<`L< `F< `@< `:<"`4<'`.<\`(. /NS``H |Pr W h(NJg .ft.g. LN\`B`HHм @g>B`HH @"<5(0H؀HHм5( @Jl&a&`&$`H`0&mR`&kR`z&jR`n&<`d`|g` :f &hR`&:`4 =f &gR`&=`H`$&lR`&iR`&>``|=g|>g` 0m 1o &%`B`H؀ؼ 0m 1o&a&` 0m 7o &@`B`H؀ؼ 0m 7o&a&`V ^g &^`FRHHм @f. `N\` (MR`RHHм @fBG`VH|Am |Zn| 0GZ0@0F̾Pg|`&Jgf0F<`0F>JGlJFmJGl. |N\`0&`>N`r`H |r W h,NgFB`$/< /NP(H؀ؼHHм @f&a&`. N\`$Jfj#'T1Jng nB&eB@JL8N^NuNVVH y+-hj nj h=hrSn&n 0.HЮ -@*n :f"`RJgHHм @gJgR` \gd`BnRH`ʷd`R=|` nj>/< /VNP`b nj0( `"(| `2(| `*(| `"(| ``|g|g|g|g` ..r/< /VNPIVR` d Jf`. N\``H |\rW hNHHм @gH|=@Jnl=| `It {gHHм @f`*R`Jg }f }g. N\`n`RB>r?</tN\-@nf.t/< NX`0` nn (=@B nj0(nc0n%-PJng.Jg n efBnd0.|0H`Jg` n e" n P(PX`Z`R n X`, n(PX`6 n(PXdP"` dBJfd4"`` n./< 9/VNPXIV`(| >`(| A`(| E`(| G`(| J`(| M`(| P`(| S`(| V`z(| Y`p(| \`f(| _`^(| b`V(| i`N(| p`F(| {`>(| `6(| `.dT n (H``|:|?b@0@ PN g`d Jf n efbJf2BB@`B. NJL8N^NuNVH y1 cg. N\` y1-hP1 y+ Pg. N\`p y+-h n h*h`D -:f:(nG`Jg RRgJgHHм @g n!M`*U f. N\JL8N^NuNVHBG`0GBRG|m35B5B+B.xB+JL N^NuNVH.N0*@.Nt+@0. H@ ;nBmB>/.aX>0G*0G J5f#5` y+!MB#+ JL N^NuNVH*n>. <.BE&M8`|@REDf H@@`H@Jf0|0@(P`2, @@f$lf lHf./ NXJ@g(T f JL8N^NuNVH*nBF>. `|@RFDf H@@`H@RJf0|JL N^NuNV n(f8 nhJ.xf #.x` y+!n nB#+N^NuNVH*y5`$J- fJmf0-||fm@*m fJL N^NuNVH *nBG fB(y5`6,f*lJ.xf#.x` y+!LB#+(l f(y.x`J, f0,||g0,|P|Pg,g"9GRG g?</ / n N *@`VJ, fPJy,NgH0,|g>Jy5&g l Lg,0,||g9GRG gBg/ / n N *@(l fV0JL0N^NuNVH09 Z[@=@.N0-@BG`0GBRG|mBG`~0G(P`f-T lH<J, fL0F*P`./,NXJ@m&M*U f f0F(0F `(&(n fRG|m~BG`*0G&P g f*K`*`*UJf f(KRG|mNB. /<5NLX`BG` 0G!LBF` g (TRFnmRG|mBG`RB.RJgNBF`(0F*h g0F!U=m| | .g|c`$0.||@f|x`.g|g0.|м @P .xf. /NLX`&./< /NP.a.H>.H?.g?<e`?< //-/< "/N./RNÒXRF|m.RN4RGnmNB fnJL8N^NuNVH*n` am zn RJfJL N^NuNVB#5#,TB#5#+By.fN^NuNVJ5g y.n0 y5!y5 N^NuNVH 9+5da>.n0.y.fg|Jg|@Jy+g.f . :N\Jg n./< bNX\5 y.n0T.n y.n X.n0|g y.n0T.n3.fT5g y.n X.nX5JLN^NuNVH.N0*@B+|A+HJ5g& y.n0 T.n y5!y5 y5 J,Tf#,T#5 |.n"MXr0Q#+B5JL N^NuNVH *nJng. / NXBn-y,T` NQ"nXr0Q n>T fB n-PX0|g n=PTg n-PX nf .Ѯ .Ѝ-@Jngg n|TJg8Jng. g~`~ n0(H@0H"nR0"n`|Jng n2Ҽ 4"AQ`Jy+g0|g(nH|r-@H|r㨁H|ሁH| 9%Ѯ|f 9&Ѯ(n .rH .rH .H .H`l n-PJfJJngJy+g=|-M(MB` n(H||frJng0 .rH .rH .H .HBn`, .-@`  b .HX-nX`TT . ehJnfB`Bn`BRn nm -@ .` . JL0N^NuNVB,PJngBN#5` .5NBN^NuNVH..gR߹,P.N*@f . N JL N^NuNVH*nB`RJ5xf.Ra&@(K`JfB JL8N^NuNVH /</.ZNP.R(y f(| ##By*T`X0-b40-f(` m0- ;@# \`f.a*@ fB`(M*U fJL0N^NuNVH ..޼/</NP.N*@fB`(M 9@.\a 9JL0N^NuNVH *n](y`ebe (Tcd0-Ѝf T0(m T*`*0,Ќf 0-l(`(#JL0N^NuNVH *n(n ..` SJf JL0N^NuNV4aJy,`o .N4. /.?9+/9+/< /8N.8Nn./8?95$N\>ENVRy5pN^NuNVla8. /./8NPJy,`o.8N4. /8?9+/9+/< /pN.pNn./p?95$N\>ENVRy5pN^NuNV4aJy,`o .N4. /.?9+/9+/< /8N.8Nn./8?95$N\>WNVB@N^NuNV4aJy,`o .N4. /.?9+/9+/< /8N.8Nn./8?95$N\>NN^NuNV4a. ?.?9+/9+/< /8NJy,`o.8N4.8Nn./8?95$N\>NN^NuNV|>+NzJ+g.+/NLXJ.f0..b/NLX>/< :/NPB+BW/N:X35$l.N 3+N^NuNVH>N@09+`BBNLX:>/9&/9%// N ,./ ?.N\``J@gL|gJL8N^NuNVH *n n (hBG`RG|lJf`B|@RGDm n 8(0| @ @<| g|@ g |(|`0|g Jng| `|0HH n *(Jy+g|JDgڹ%gڹ& rH rH H JL0N^NuNVHBWBaX-@0.-@ . Ю-@.d.. .㈾d..095.N0#5.0N0*@0 .Ѝ#+A#1 y1R1 y1R1T'DT5 y1R1 y1BR1T'DT5 y1 R1 y1BR1T'DT5 y10R1 y1BR1T'DT5 . rH"y1R1 . rH"y1R1 . H"y1R1 . H"y1R1X'DX5 y1BR1 y1BR1 y1BR1 y1BR1X'DX5 y1BR1 y1BR1 y1BR1 y1BR1X'DX5 .rH"y1R1 .rH"y1R1 .H"y1R1 .H"y1R1X'DX5 y1BR1 y1BR1 y1BR1 y1BR1X'DX5 .rH"y1R1 .rH"y1R1 .H"y1R1 .H"y1R1X'DX5 y1BR1 y1BR1 y1BR1 y1BR1X'DX5 .rH"y1R1 .rH"y1R1 .H"y1R1 .H"y1R1X'DX5 .rH"y1R1 .rH"y1R1 .H"y1R1 .H"y1R1X'DX5(M|`20м% @&h`./+/ N0P&S fRF|o>/ arX-@.0/ ?.N\.R/ NLX./ ?.N\BW/ a&Xav./9+?.N\JL8N^NuNVH*nBBE-y5By5-y,T` N"nXr0Q n<T fRy5 n(X0|g n:T0|м J @g n(PX<TZg<@`<  g<gع%Jn g0|gg&DH|r-@H|r㨁H|ሁH| 9%Ѯg 9&Ѯ&D .rH .rH .H .H`Z&DH|-@H| 9%Ѯg 9&Ѯ&D .H .H`L gH n X rH rH H H g0,|0,H|` n-PJf .JL8N^NuNVH.?<?95/95NP&y+*y5>95` (]H||fSGJGfJL8N^NuNVH n*P n (P-@|r`-A|taA-A|AA-A|A.,@|r`,A|taA,A|AA,A|A,cp`` dp``B@JL0N^NuNVH *nBn n (h _fJy+g=|RBG`RG|lJf|l Jng_RG`B|@RGDm n :( g|`20| @ P<Jng|0|f|| 0|0H| n ((0|gع%gع& rH rH H H JL0N^NuNVByByBy3= Z3. \/<NLX. ]/<5NLXN./<NXN&./<NLXN^NuNVH #'D1 3,\3+> ?<(/<ar\ &(|(*|/ `"  l  f`^H|@HRJfBJL0N^NuNV./< ^/<NP> /</<aPN^NuNVH 91 'Dg0.1 /< e/<NP>/</<axP09y+g0>/< k/<NP>/</<a:PN0D09y,\f09м% @f 91 'DgJy,^f09м% @*h yg$` -1 b -Э1 b*U f f >N(y1 =|Bn 9'D1 -@` n%m^=|.a.a8> ?<(/<ar\.1 /< o/<NP>/</<a P yg -Э1 b *U gD(mJnf.1 ?9N8T=@JngSn. u/<NLXR`H>W/< x/<NP>/<0.Hм/ajPTnR1 .SJf no.a.a`.a.a JL0N^NuNVHJy,`o09 ZS@ynaJyfRy. }a. /<J/</<?9/9+/</< ~/<N.a.5/< /<NP.a. az3.ajRyJLN^NuNVH~`. n2H0H|am<fnH|2GRG|(mJLN^NuNV 'N^NuNVH*nJ+gaD.Nn./ ?9+N\./< ?9+N\JL N^NuNV|.+/NLXJ.f0..b/NLX>/< /NPB+BW/N:X3+l.N N^NuNVJy,`o. aByN^NuNV y1 bg. N\`> y1./<NLXP1 yo. /<5NLXaN^NuNVH~ y1 -fBGX1 y1 bg. N\`@ y1./<5NLXP1JGgJyf yoa 3JLN^NuNVH (n*n >.JGl><`0SGJ@gJfJL0N^NuNVH*n>. .`0SGJ@fBJL N^NuNVH .NnH(@S :gP` \fR`SbJng*L`RJg .fB*L`Jf. / NÒX`R .f .JL0N^NuNVHB?< N:T.,8.?< N:T JLN^NuH Lpr<Zn <Am< @4qB62 CCf g03 jL pNu o00 L Nu/<?<&NN\O/<@?< NA\O/<J?< NA\O/<P?< NA\O y <Ш ШШBg/?<1NA/<?<&NN\O/<^?< NA\O?<?<LNAJMADMAC version installed. Terminate error: cannot install. < y!! NuBNup$o"y"i,Jg&r1RA<=g 2gJf`J2fC NuNVH*| BG`&BF`0 2HЁм#( @RF| mRG|8mBG`H|0 2HЁм#( @0 2HЁм @ fL0 м#( @0 м @0 м#( @| 0 м @m T fpRRG|8mdJL N^NuNVN0D>N/tJ+tf$.N0. y&/(NXN^NuNVHB5Bn y1 `F~`dX1B/]/Y/<,bN" J@mj~`6X1B/]/Y/<,bN" J@m< y1 )fZX1 y1 ,fBX1 y1*h y1 cfJ-fH| |yf~P1~`~`n y1 ,f\X1 y1*h y1 cfBJ-f:H| |xf*P1 y1 )@X1Df ~```4X1B/]/Y/<,bN" J@m: y1 (fX1 y1*h y1 cfJ-f y1 )f y1 e fzH| |xf~`|yf~``Z 1=|` y1 ef~``2`d y1*h y1 cf~J-fv y1 ,fd 1H| |xf~` |yf~``0. 2HЁ @"<#(0H`X y12. 4H҂Ҽ "AR1R'DR5`: y12. 4H҂Ҽ "AR1R'DR50.|f.,b/9'D?<N1z\B`" .мe.N\B .H"y1R1R'DR5` y12. 4H҂Ҽ "AR1R'DR50.|gP 9'DR .мe.N\B .H"y1R1R'DR5`2.,b/9'D?<N1z\ y1BR1R'DR5` y12. 4H҂Ҽ "AR1R'DR50.|f.,b/9'D?<N1z\B .H"y1R1 .H"y1R1T'DT5`LBF` y1R1R'DR5RF|m.N\`H |r W h4N 9'Dc ..N y1 eg .N\JL N^NuNVJy1f.FN\`X.YN9J@mJ .e.N\`0B5 .#'D#1 y. (Ю#1NN^NuNVH *y& gJ gBB`6 GB( (@,<`Jg G|z` SJfRmJgn./?.N\(mB`D FJ(g8*R`Rl EJ(f . Ќ/?.N\,RmJL0N^Nu o"oHrtvxz|~&G g g,A$HHHHHHHHHSfܳg`LNuNVH n oP3%#%09%@3%09%3%0. %Ю-@ n m ./.aX09%HЮ-@`-n&n(K`/ / y%NPJ@o(K% e޹g"*n09%HЮ-@`ǻe-n`j/.09%H/. y%NPJ@n09%HѮ .g26y%`(K*L`*L% dS d09%HѮ .-@e|JL8N^NuNVH . -@09%H//.NnP/0y%/NP*@-M09%H".n|/ &n/ y%NPJ@o ` (@ . 29%H-@// y%NPJ@o$f ` (@/./ y%NPJ@l(ng<9%SFf*n(n %`%̻d/./ y%NPJ@o`B/ /. y%NPJ@n%`&09%HЍ-@f&L-K`&L%`$bf`.`&n -@-@%<9%SFf*n``(n:y% -@". -An(09%H".n ./.a@X-M-n` 09%H".n . / aX-L 09%H".oJL8N^NuNVH>*N:. JL N^NuNVH>,N:. JL N^NuNVH.. r <| o| -|`-|. ? ???/</.NJLN^NuNVH.. r м>  @"<l/0 ?/</.NJLN^Nu#% WaJ@j?<=NATO y%N#% WarJ@j?<<`#% Wa\J@j?<A`#%0|l ?<>NATO y%Np?`p@ O/(/( ?( Pl ?NA Nuar NuC20k*$Y/<Am<Zn< fJ(f _fNu con:aux:prn:mid:H6/|6;0&o(/ gp???<NM\OSfLNu"_0H@??9?<NM\OL< f< `NNV. H>NTN^NuX?<LNAJ2/0/ 4 B4/g0/gBH@B@ЈNuJolDRIJolDSI2/B0/ 4 B4/g0/gBH@B@Ј2 gDNu C"D"/&/f r`@pe:fpr`2t(ȼf 0BAHA`Ԃed`ef&( Nu C"/lD&/nm <"`\Df r`:pmn2pr`,tl 0BAHA`Ԃփd`efJojDDJojD#1&Nu////NP Nu////NnP NuNVH *n(n ` gSS`JfHHAJL0N^NuNVH*n(n &Mf JL8N^NuNVH*nBG`RGRJf0JL N^NuNVH*n(n &MJfSf JL8N^NuNVH*n`R  g  g  g| +g -f +fp`p<BG` H@|R 0m 9o0JL N^NuNVH /?.?./ /. nN*@ мfB(n ` %H| l|0`Jngp7`pW@ мfB JL0N^NuNVH*n<.H n0H.JngJl D. n P-"n R`μ`./NnXH. 91HJf JL N^NuNVH *n:.H n., nf x` HSDJgJDf` nf*x ` HSDJgJDfJDf-`Jng\Jl2 n P-"n Rf(|0HfS `R D.`//NPH//NnP.Jf`$`//NPH//NP,Jf JL0N^NuNVHIBBn .RdRn-\ fRn-\*\&L`"(K<%gH>/?.a"\`BnH|-fRn| <0fG=|`"JnlBn0. HA|=@<0m<9o=|<.fBn`0. HA|=@<0m<9oBn<lfRnA-HH`JJng -|`-|ĦBW/.?<?< // N&TJngT`BW/<ĦBg?< // N&T`Jng -|`-|ĦBW/.Bg?<// N&TJngT`Jng -|`-|Ħ<XgBW`>/.Bg?<// N&TJngT`R-\&L`J=[0.H@B.`6H>/?.a&\``|C|5b@0@ PN.Nn=@0.nl Jnm=n0.n=@Jnf^ . g. n -f$Sn nH>/?.a\R`.H>/?.a\0.SnJ@n` nH>/?.aV\R0.SnJ@f`.H>/?.a,\0.SnJ@nf nf nBJL8N^NuNV0.`<.H>NT`< n ..H?N~T`$ n P"n R``J@g|gʰ|g.HN^Nu#%/<NXO y%N#%NN/9%Nu#%NM/9%Nu#%NA/9%Nu1.05 noname.oX-123456789** AMamvvv6DEFILOPQSUVXYdefilopqsuvxy4`rJT^`rJT^`- %sMADMAC Atari Macro Assembler Copyright 1987 Atari Corp. Version %s %s lmd %sMay 1988* Too many arguments %d assembly error%s s%ldK used, %ldK left, %d lines, %ld.%ld seconds Missing argument to -o-y: bad page length con:(con:)-d: empty symbol -fm: unknown modifier-f: unknown object format specified -p: syntax error Unknown switch: %s .sCannot open: %s .prg.oexecutableobject[Writing %s file: %s] [Wrapping-up listing file] Cannot create: '%s' MACPATH+/?NJ^VYkjz1 7>mb , o,GNODaTRqpz     $('"%./"15.32('(6>3@?2?<E?D@MMLTGFTV[VXSVQaeZe_XbZk^l_o]ccsmvk{mjtq}xw{{\st(&Zr qYwGLHM !"#%$&)u*+,x'-./(06123v4y7589:;<=@A>BCRNDOEF?PISQJKUT[VW\X^_]`ablcdemfnghijzk{op~|}       !"#$%&'()*+st(&      !#$&'* .0  +   1"+ " 3/56%/748,%()((,-)429):;=?-@)A--22<C<<<<DEG<<<H<F<F<><I>B<JBKFLMNOKPQROSTUQVWXYZYX[\][^_`\abcde\f]]ghbc_iaccjklmnopeqruviwxyqz{|}~      !"#$%&'()*+`X           "9*=4">ABCE I\^eb_gw|~kxy|}}~"  $')+-%12.&3*-5)(,(/07826:  D&MY[Z]ozs0  &0 ./T'f, .U/VX',--@!!8  **- */)+46(#>2B66H8;LMNFLMPPJDcd  " $%&!('-*#)+.,/0        !"#$%&'*,(++)(+.&')""--/0,,/Dextra (unexpected) text found after addressing mode @@@@@@@@ @  && missing commasyntax errorcannot GLOBL local symbollabel ignoredhit EOF without finding matching .endifmis-nested .endrmultiple equate to '%s'multiply-defined label '%s'unknown op '%s'cannot initialize non-storage (BSS) sectioncannot use '.b' with an address registersyntax errormismatched .elsemismatched .endif @ @addressing mode syntaxunimplemented addressing moderegister list syntaxregister list order   missing symbolBac([{)]}pqvwyx!~n*/%+-mlji<>k=&^|&*&2''''&%%J%v$(*[abc)\())"(((L)%&*/^lm|-.-~-.--..$!+-<=>Aacijkn~+*+,-,R***@,+,+f+-Rmissing symbol or stringmissing close parenthesis ')'missing close parenthesis ']'bad expressiondivide by zeromod (%) by zero86N66L7588ZPC-relative expr across sectionsunoptimized short branchexternal short branchillegal bra.s with zero offsetexternal byte referencenon-absolute byte referenceExternal quick referenceexpression out of rangeCBI>===>HDPI4?>:K99C999999<999<@9999:y9e9II9999bB99eK8K(K(K(K,K,K:unimplemented directivesymbol list syntax.smissing filenameextra stuff after filename -- enclose it in quotesMACPATH\cannot open: "%s"forward or undefined .assertassert failurecannot .globl local symbol.ds permitted only in BSSillegal initialization of sectionnon-absolute byte valueillegal initialization of sectionmissing comma.init not permitted in BSS or ABSnon-absolute byte valuemissing symbol.comm symbol already definedmultiply-defined label '%s'.cargs syntax(@\u K M` M`L0L0ML0PZ M` M` L0 L0 L0 <O\ |O OP6 Nv  L0 OP6 Nv  L0  dW  eW  gW  lW  nW  bW  oW  cW  mW  kW  fW  jW  hW  iW @&Q, @'Q, @(Q, @Q, *Q, +Q, ,Q, Q,  `W /Q, 0Q, 1Q, Q,  aW 4Q, 5Q, 6Q, Q, AL0 B9L0 _R;L0<L0=M >L0 Nv TR, UR, WR, QR, \R, ^R, RR, _R, SR, ]R, [R, VR, ZR, PR, XR, YR, L0 L0RL0 SL0  <TO\  |O SP  HWNv HNv JK NL0 NL0 AL0NPT (^O_P6 `L0 Nv(bOcP6 dL0 NvfTl@gTl FhL0 @iL0 DjL0 NhkUl N`Ul@Tl H\$oV$V pU L0 L0  HL0 DL0 @L0 NqK FL0yL0zL0{L0 <|O\ |O  H@L0 NpK8OP6 L0 Nv8OP6 L0 Nv0OP6 L0 Nv0OP6 L0 Nv ,NsK NwK NuK M` M`  TL0  UL0  WL0  QL0  \L0  ^L0  RL0  _L0  SL0  ]L0  [L0  VL0  ZL0  PL0  XL0  YL0 NrOL0L0ML0QZM` M`  H@Nv  JL0 N@\  NvK JL0 NXNvK @@0 0 @@@@@ @ @@   @@@@ @ @ @@  expression out of rangeillegal absolute expressionbad (section) expressionillegal relative addressbad size specifiedundefined expressionforward or undefined expressionunimplemented mnemonicinappropriate addressing modebad size suffixmissing commainvalid addressing modemissing commainvalid addressing modemissing symbolmultiple macro definitionmacro definition cannot override directive or mnemonicendm multiple formal argument definitionencountered end-of-file looking for '%s'cannot continuemacro stack overflowtoo many ENDMsendr rept  (089:;<@ABCDEFGHIffffffhvlmgi\j`nnnnnnffffn (089:;<@ABCDEFGHIoooooopuuoqxr|vvvvvvoooovillegal byte-sized relative referenceunsupported 68020 addressing modeillegal byte-sized relative referenceunsupported 68020 addressing modeHR^f;q 387=<QNTTUVNXLO\\_aXdce\  %()*&' "+,#$-./012345678!  !!   "#$%& '()*+,-./ 012 345678BRLW=SB LRW=Syxvwpql  @@H@@ @ @   @    e"'\befnrt"V\b>2P8JDh!"$%':<=>@^d~\2                     !#?\~vhF2x(<FPZdn0123456789abcdefABCDEF[Including: %s] [Leaving: %s] (*top*)[bwsl] must follow `.' in symbolmisuse of `.', not allowed in symbolsunterminated stringbad backslash code in stringunterminated stringinvalid symbol following ^^unknown symbol following ^^illegal characterd0d1d2d3d4d5d6d7a0a1a2a3a4a5a6a7pcsspuspsrccr%d.b.w.lM%ldmissing argument namemissing '}'undefined argument: '%s'$%lx==set:::>=<=<>>><<.b.w.l^^date^^time^^defined ^^referenced ^^streq ^^macdef line too long as a result of macro expansionmissing labelgoto not in macrogoto label not foundatd!b Symbol Tableexternal%08lx %16s %s %c%c%cillegal word relocatable (in .PRG mode)illegal external reference (in .PRG mode) to '%s'memory exhausted "%s", line %d: %s%s"%s", line %d: %s%s"%s", line %d: warning: %s%s"%s", line %d: Fatal error: %s%s"%s", line %d: Internal error number %d%s.err  ==%08lx%08lx%5d%08lxxx%02x%-40s%-20s Page %-4d %s %s Madmac %s (%s)Atari ST%s .prn missing stringmissing stringdirective illegal in .6502 sectionim eaq u}y)- %!1 5=9  0Pp, $X    IM EAQ U]Y Ll      N FJ V^  Hh(. &* 6>n fj v~@`  8x      TTTTTT@@bad 6502 addressing modeillegal 6502 addressing mode6502 code pointer > 64K.org permitted only in .6502 sectionpmam%d:%02d:%02d %sJanFebMarAprMayJunJulAugSepOctNovDec%d-%s-%d   AB P:ddddddddddǮdddHdDŽddddddddddddP:ddddddddddǮdddHdDŽdd 6F" 4   4&     ^   > 0  0 "         L     $    4"       4:$ "(    6   \            "  (                "  (           *(    H  <         *       $          (V<"*:::::4J B                2x~L6  .($$&D\ 0@0R    " ,"               "        *    2  " F           J    ".   $0     4   ,   2 ( (    ,                        ((      "    *         8             ,        $      6                      * " & &    "  (                         <      (                         <      ( .      $         :J0 B   $">$ @,|* &",H\$"<& 6fp ,8   D" 8Z.~ L\\.6~BJ     ( jT^ @ F "ZD   $                          rP            > $6.Fvd fD 8B                 `      ~P.B"b>62    ( ( 6 .$ *>,(              nH $$*:  & ( (&8 & > lb,^ @   *`8 @x. l4 $(@0 ^` 4 F< x5{ @ATARI ?MADMAC 068000 Macro Assembler 5Reference Manual  9version 1.00 * NOTE: Every effort has been made to ensure the accuracy and robustness of this manual and the associated software. However, because Atari Corporation is constantly improving and updating its computer software, it is unable to guarantee the accuracy of printed or duplicated material after the date of publication and disclaims liability for changes, errors or omissions. ATARI, the Atari logo, MEGA, and ST are trademarks or registered trademarks of Atari Corporation. Mark Williams is a trademark of Mark Williams Company. Motorola is a trademark of Motorola Inc. Copyright 1986, 1987, Atari Corporation All rights reserved. Reproduction of this document or the associated software is not allowed without the specific written consent of Atari Corporation. Printed in USA. Atari Document number C300341-001 Rev. A. * MADMAC Version 1.05 release notes, August, 1988. This version of MadMac replaces version 1.00 and fixes some small bugs: Symbols beginning with a capital L were not included in the object file output. They should have been (and now are) excluded only in AS68 compatibility mode to avoid cluttering the output with compiler-generated symbols. Forward branches declared "short" (such as bra.s dbra.s bsr.s) but whose targets were too far away did not cause assembly-time error; incorrect machine code was silently generated. They now cause assembly-time errors. Symbols appeared in the object file symbol table in the order they were referenced in the source, not in the order they were declared. Now the order more clearly matches the order of declaration (but not perfectly). The disp(Ax,Xn.s) addressing mode produced correct machine code, but incorrect output in the listing file. Now the output is correct. * Contents Intr oduction.(2 Getting Started.%2 The Command Line.$3 Using MADMAC.(7 Example Command Lines.7 Interactive Mode.$7 Things You Should Be Aware Of.8 Forward Branches.$8 Notes for AS68 users. 9 Notes for Mark Williams C Users.9 Using MADMAC as a Back-End to the Alcyon C Compiler.10 Text File Format.$10 Source Format.'11 Statements.*11 Equates.-11 Symbols and Scope.#11 Keywords.,12 Constants.+13 Strings.-13 Register Lists.&13 Expressions.)15 Order of Evaluation.!15 Types./15 Unary Operators.%16 Binary Operators.$16 Special Forms.'16 Example Expressions.!17 Directives.*18 68000 Mnemonics.%22 Macros..24 Macro Declaration.#24 Parameter Substitution.24 Macro Invocation.$25 Example Macros.&26 Repeat Blocks.'27 6502 Support.(28 6502 Addressing Modes.28 6502 Directives.%28 6502 Object Code Format.29 Error Messages.&30 *1 Introduction This document describes MADMAC, a fast macro assembler for the 68000. MADMAC currently runs on the Atari ST and under 4.2 BSD VAX UNIX. It was written at Atari Corporation by programmers who needed a high performance assembler for their work. MADMAC is intended to be used by programmers who write mostly in assembly language. It was not originally a back-end to a C compiler, therefore it has creature comforts that are usually neglected in such back-end assemblers. It supports include files, macros, symbols with limited scope, some limited control structures, and other features. MADMAC is also blindingly fast, another feature often sadly and obviously missing in today's assemblers.1 MADMAC is not entirely compatible with the AS68 assembler provided with the original Atari ST Developer's Kit, but most changes are minor and a few minutes with an editor should allow you to assemble your current source files. If you are an AS68 user, before you leap into the unknown please read the section on Notes for AS68 Users. This manual was typeset with Microsoft WRITE and it was printed on the Atari SLM-804 laser printer with a MEGA ST. Except for 200 lines of assembly language, the assembler is written entirely in C. _ 1It processes 30,000 lines a minute on a lightly loaded VAX 11/780; maybe 40,000 on a 520-ST with an SH-204 hard disk. Yet it could be sped up even more with some effort and without resorting to assembly language; C doesn't have to be slow! *2 Getting Started >> Write protect your distribution disk and make a backup of it now. Put the original disk in a safe place. o The distribution disk contains a file called README that you should read. This file contains important news about the contents of the distribution disk and summarizes the most recent changes to the tools. o Hard disk users can simply copy the executable files to thePir work or binary directories. People with floppy disks can copy the executables to ramdisks, install the assembler with the -q option, or even work right off of the floppies. o You will need an editor that can produce ``normal'' format text files. Micro Emacs will work well, as will most other commercial program editors, but not most word processors (such as First Word or Microsoft Write). o You will probably want to examine or get a listing of the file `` ATARI.S''. It contains lots of definitions for the Atari ST, including BIOS variables, most BIOS, XBIOS and GEMDOS traps, and line-A equates. We (or you) could split the file up into pieces (a file for line-A equates, a file for hardware and BIOS variables and so on), but MADMAC is so fast that it doesn't matter much. o Read the rest of the manual, especially the first two chapters on The Command Line and Using MADMAC. The distribution disk contains example programs that you can look at, assemble and modify. The Command Line and Using MADMAC. The distribution disk contains example programs that you can look at, assemble and modify. *3 The Command Line The assembler is called `` mac.prg.'' The command line takes the form: mac [switches] [files...] A command line consists of any number of switches followed by the names of files to assemble. A switch is specified with a dash (-) followed immediately by a key character. Key characters are not case-sensitive, so `` -d'' is the same as `` -D''. Some switches accept (or require) arguments to immediately follow the key character, with no spaces in between. Switch order is important. Command lines are processed from left to right in one pass, and switches usually take effect when they are encountered. In general it is best to specify all switches before the names of any input files. If the command line is entirely empty then MADMAC prints a copyright message and enters an ``interactive'' mode, prompting for successive command lines with a star (*). An empty command line will exit (See the examples in the chapter on Using MADMAC). After each assembly in interactive mode, the assembler will print a summary of the amount of memory used, the amount of memory left, the number of lines processed, and the number of seconds the assembly took. Input files are assumed to have the extension `` .s''; if a filename has no extension (i.e. no dot) then `` .s'' will be appended to it. More than one source filename may be specified: the files are assembled into one object file, as if they were concatenated. MADMAC normally produces object code in `` file.o'' if ``file.s'' is the first input filename. If the first input file is a special character device, the output name is noname.o. The -o switch (see below) can be used change the output file name. Switch Description  -dname[=value] Define symbol, with optional value. -e[file[.err]] Direct error messages to the specified file. -fm Produce Mark Williams format object file. -fmu Like `` -fm'', but move underscores to end of symbol names. -ipath Set include-file directory search path. -l[file[.prn]] Construct and direct assembly listing to the specified file. -ofile[.o] Direct object code output to the specified file. -p Produce an executable ( .prg) output file. -ps Produce an executable ( .prg) output file with symbols. -q Make MADMAC resident in memory (Atari ST only). -s Warn about unoptimized long branches. -u Assume that all undefined symbols are external. -v Verbose mode (print running dialogue). -yn Set listing page size to n lines. -6 ``Back end'' mode for Alcyon C68. file[.s] Assemble the specified file. *4 The switches are described below. A summary of all the switches is given in the table. The -d switch permits symbols to be defined on the command line. The name of the symbol to be defined immediately follows the switch (no spaces). The symbol name may optionally be followed by an equals sign (=) and a decimal number. If no value is specified the symbol's value is zero. The symbol attributes are ``defined, not referenced, and absolute''. This switch is most useful for enabling conditionally-assembled debugging code on the command line; for example: -dDEBUG -dLoopCount=999 -dDebugLevel=55 -e The -e switch causes MADMAC to send error messages to a file, instead of the console. If a filename immediately follows the switch character, error messages are written to the specified file. If no filename is specified, a file is created with the default extension ``.err'' and with the root name taken from the first input file name (e.g. error messages are written to `` file.err '' if `` file '' or ``file.s'' is the first input file name). If no errors are encountered, then no error listing file is created. Beware! If an assembly produces no errors, any error file from a previous assembly is not removed. -fm -fmu The -fm and -fmu switches cause MADMAC to generate Mark Williams style object files instead of Alcyon object files. These files may be linked with the Mark Williams linker. The bf -fmu switch causes underscores on the first character of a global symbol name to be moved to the end of the name, as per the Mark Williams C compiler naming convention. That is, ``_main '' will become ``main_ '' and ``__main '' will become ``_main_ ''. -i The -i switch allows automatic directory searching for include files. A list of semi-colon seperated directory search paths may be mentioned immediately following the switch (with no spaces anywhere). For example: -im:;c:include;c:include\sys will cause the assembler to search the current directory of device M, and the directories include and include\sys on drive C. If -i is not specified, and the enviroment variable `` MACPATH '' exists, its value is used in the same manner. For example, users of the Mark Williams shell could put the following line in their profile script to achieve the same result as the -i example above: setenv MACPATH="m:;c:include;c:include\sys" -l The -l switch causes MADMAC to generate an assembly listing file. If a filename immediately follows the switch character, the listing is written to the specified file. If no filename is specified, then a listing file is created with the default extension `` .prn'' and with the root name taken from the first input file name (e.g. the listing is written to `` file.prn'' if `` file'' or `` file.s'' is the first input file name). -o The -o switch causes MADMAC to write object code on the specified file. No default extension is applied to the filename. For historical reasons the filename can also be seperated from the switch with a space (e.g. `` -o file''). *5 -p -ps The -p and -ps switches cause MADMAC to produce an Atari ST executable file with the default extension of `` .prg''. If there are any external references at the end of the assembly, an error message is emitted and no executable file is generated. The -p switch does not write symbols to the executable file. The -ps switch includes symbols (Alcyon format) in the executable file. -q The -q switch is aimed primarily at users of floppy-disk-only systems. It causes MADMAC to install itself in memory, like a RAMdisk. Then the program m.prg (which is very short --- less than a sector) can be used instead of mac.prg, which can take ten or twelve seconds to load. -s The -s switch causes MADMAC to generate a list of unoptimized forward branches as warning messages. This is used to point out branches that could have been short (e.g. ``bra'' could be ``bra.s''). -u The -u switch takes effect at the end of the assembly. It forces all referenced and undefined symbols to be global, exactly as if they had been made global with a .extern or .globl directive. This can be used if you have a lot of external symbols, and you don't feel like declaring them all external. -v The -v switch turns on a ``verbose'' mode in which MADMAC prints out (for example) the names of the files it is currently processing. Verbose mode is automatically entered when MADMAC prompts for input wikth a star. -y The -y switch, followed immediately by a decimal number (with no intervening space), sets the number of lines in a page. MADMAC will produce N lines before emitting a form-feed. If N is missing or less than 10 an error message is generated. -6 The -6 switch takes effect when it is mentioned. It allows MADMAC to be used as a back end to the Alcyon C compiler.The -6 switch is not a compatibility mode for AS68 --- it has been carefully tailored to accept the output of the Alcyon C compiler.2 Note: the assembler will produce code that is typically ten percent larger and ten percent slower than the output of the Alcyon assembler, therefore use of this switch for production code is discouraged. _ 2The -6 switch is not a compatibility mode for AS68 --- it has been carefully tailored to accept the output of the Alcyon C compiler. *6 Using MADMAC Let's assemble and link some example programs. These programs are included on the distribution disk in the "EXAMPLES" directory --- you should copy them to your work area before continuing. In the following examples we adopt the conventions that the shell prompt is a percent sign (%) and that your input (the stuff you type) is presented in bold face. If you have been reading carefully, you know that MADMAC can generate an executable file without linking. This is useful for making small, stand alone programs that don't require externals or library routines. For example, the following two commands: % mac example.s % aln -s example.o could be replaced by the single command: % mac -ps example.s since you don't need the linker for stand-alone object files. Successive source files named in the command line are concatenated, as in this example, which assembles three files into a single executable, as if they were one big file: % mac -p bugs shift images Of course you can get the same effect by using the .include directive, but sometimes it is convenient to do the concatenation from the command line. Here we have an unbelievably complex command line: % mac -lzorf -y95 -o tmp -ehack -im: -Ddebug=123 -ps example This produces a listing on the file called ``zorf.prn'' with 95 lines per page, writes the executable code (with symbols) to a file called `` tmp.prg,'' writes an error listing to the file ``hack.err,'' specifies an include-file path that includes the current directory on the drive `` M:,'' defines the symbol `` debug'' to have the value 123, and assembles the file `` example.s.'' (Take a deep breath --- you got all that?) One last thing. If there are any assembly errors, MADMAC will terminate with an exit code of 1. If the assembly succeeds (no errors, although there may be warnings) the exit code will be 0. This is primarily for use with ``make'' utilities. Interactive Mode If you invoke MADMAC with an empty command line it will print a copyright message and prompt you for more commands with a star (*). This is useful if you are used to working directly from the desktop, or if you want to assemble several files in succession without having to reload the assembler from disk for each assembly. In interactive mode, the assembler is also in verbose mode (just as if you had specified -v on each command line): *7 % mac - MADMAC Atari Macro Assembler Copyright 1987 Atari Corporation Beta version 0.12 Jun 1987 lmd - * -ps example [Including: example.s] [Including: atari.s] [Leaving: atari.s] [Leaving: example.s] [Writing executable file: example.prg] 36K used, 3658K left, 850 lines, 2.0 seconds * You can see that the assembler gave a ``blow-by-blow'' account of the files it processed, as well as a summary of the assembly's memory usage, the number of lines processed (including macro and repeat-block expansion), and how long the assembly took. The assembler prompts for another command with the star. At this point you can either type a new command line for the assembler to process, or you can exit by typing control-C or an empty line. Things You Should Be Aware Of MADMAC is a one pass assembler. This means that it gets all of its work done by reading each source file exactly once and then ``back-patching'' to fix up forward references. This one-pass nature is usually transparent to the programmer, with the following important exceptions: In listings, the object code for forward references is not shown. Instead, lower-case `` xx''s are displayed for each undefined byte, as in the following example: 60xx .1: bra.s .2 ; forward branch x dc.l .2 ; forward reference 60FE .2: bra.s .2 ; backward reference o Forward branches (including BSRs) are never optimized to their short forms. To get a short forward branch it is necessary to explicitly use the `` .s'' suffix in the source code. o Error messages may appear at the end of the assembly, refering to earlier source lines that contained undefined symbols. o All object code generated must fit in memory. Running out of memory is a fatal error that you must deal with by splitting up your source files, re- sizing or eliminating memory-using programs such as ramdisks and desk accessories, or buying more RAM. Forward Branches MADMAC does not optimize forward branches for you, but it will tell you about them if you use the -s (short branch) option: % mac -s example.s "example.s", line 20: warning: unoptimized short branch With the -e option you can redirect the error output to a file, and determine by hand (or editor macros) which forward branches are safe to explicitly declare short. *8 Notes for AS68 Users MADMAC is not entirely compatible with the Alcyon assembler, AS68. This section outlines the major differences. In practice, we have found that very few changes are necessary to make AS68 source code assemble. o A semicolon (;) must be used to introduce a comment, except that a star ( *) may be used in the first column. AS68 treated anything following the operand field, preceeded by whitespace, as a comment. (MADMAC treats a star that is not in column 1 as a multiplication operator). o Labels require colons (even labels that begin in column 1). o Conditional assembly directives are called if, else and endif. AS68 called these ifne, ifeq (etc.), and endc. o The tilde (~) character is an operator, and back-quote ( `) is an illegal character. AS68 permitted the tilde and back-quote characters in symbols. o There are no equivalents to AS68's org or section directives. AS68's page directive has become eject. The AS68 .xdef and .xref directives are not implemented, but .globl makes these unnecessary anyway. The directives .comline, mask2, idnt and opt, which were unimplemented and ignored in AS68, are not legal in MADMAC. o The location counter cannot be manipulated with a statement of the form: * = expression o The ds directive is not permitted in the text or data segments (except in -6 mode); an error message is issued. Use dcb instead to reserve large blocks of initialized storage. o Back-slashes in strings are ``electric'' characters that are used to escape C-like character codes. Watch out for GEMDOS path names in ASCII constants --- you will have to convert them to double-backslashes. Notes for Mark Williams C Users MADMAC will generate object code that the Mark Williams C linker, ld, will accept. This has been tested only with version 2.0 of the Mark Williams package. Some notable differences between MADMAC and the Mark Williams assembler, as, are: o MWC permits 16-character symbol names in the object file, and MADMAC supports this; o MWC object files can contain more code and data sections than the MADMAC (Alcyon) object code format. MADMAC maps its code sections as follows: MWC Space MADMAC Space - - shri (shared instruction) text prvi (private instruction) unsupported bssi (uninitialized instruction) unsupported shrd (shared data) data prvd (private data) unsupported bssd (uninitialized data) bss debug information unsupported symbols y symbols absolute abs, equates, etc. *9 It is not possible for MADMAC to generate code in the Mark Williams private instruction, private data or uninitialized instruction spaces. o None of the Mark Williams assembler directives (e.g. `` .long'' and `` .odd'') are supported. None of the MWC non-standard addressing modes are supported. o The Mark Williams debugger, db, does not support the Alcyon-format symbols produced with the -ps switch; it complains about the format of the executable file and aborts. o MADMAC does not support the method by which the Mark Williams shell passes long command lines to programs. Command lines are truncated to 127 characters. Using MADMAC as a Back-End to the Alcyon C Compiler MADMAC can be used in place of the AS68 assembler as a back-end for the Alcyon version 4.14 C compiler. The `` -6'' switch turns on a mode that warps and perverts MADMAC's ordinary syntax into accepting what the Alcyon compiler dishes out. This can be used in a batch file (for instance) with a line that looks like: mac -6 -o % 1.o m:% 1 (Assuming that device `` M:'' is where the source was put by compiler phase c168). You should be aware that AS68 generally produces better and faster code than MADMAC, although it is slower to assemble. Text File Format For those using editors other than the ``Emacs'' style ones (Micro-Emacs, Mince, etc.) this section documents the source file format that MADMAC expects. o Files must contain characters with ASCII values less than 128; it is not permissable to have characters with their high bits set unless those characters are contained in strings (i.e. between single or double quotes) or in comments. o Lines of text are terminated with carriage-return/line-feed, linefeed alone, or carriage-return alone. oThe file is assumed to end with the last terminated line. If there is text beyond the last line terminator (e.g. control-Z) it is ignored. *10 Source Format Statements A statement may contain up to four fields which are identified by order of appearance and terminating characters. The general form of an assembler statement is: label: operator operand(s) ; comment The label and comment fields are optional. An operand field may not appear without an operator field. Operands are seperated with commas. Blank lines are legal. If the first character on a line is an asterisk (*) or semicolon (;) then the entire line is a comment. A semicolon anywhere on the line (except in a string) begins a comment field which extends to the end of the line. The label, if it appears, must be terminated with a single or double colon. If it is terminated with a double colon it is automatically declared global. It is illegal to declare a confined symbol global (see: Symbols and Scope). Equates A statement may also take one of these special forms: symbol equ expression symbol = expression symbol == expression symbol set expression symbol reg register list The first two forms are identical; they equate the symbol to the value of an expression, which must be defined (no forward references). The third form, double-equals (==), is just like an equate except that it also makes the symbol global. (As with labels, it is illegal to make a confined equate global.) The fourth form allows a symbol to be set to a value any number of times, like a variable. The last form equates the symbol to a 16-bit register mask specified by a register list. It is possible to equate confined symbols (see: Symbols and Scope). For example: cr equ 13 ; carriage-return lf = 10 ; line-feed DEBUG == 1 ; global debug flag count set 0 ; variable count set count + 1 ; increment variable .regs reg d3-d7/a3-a6 ; register list .cr = 13 ; confined equate Symbols and Scope Symbols may start with an uppercase or lowercase letter ( A-Z a-z ), an underscore (_), a question mark (?) or a period (.). Each remaining character may be an upper or lowercase letter, am digit (0-9), an underscore, a dollar sign ($), or a question mark. (Periods can only begin a symbol, they cannot appear as a symbol continuation character). Symbols are terminated with a character that is not a symbol continuation character (e.g. a period or comma, whitespace, etc.). Case is significant for user- defined symbols, but not for 68000 mnemonics, assembler directives and register names. Symbols are limited to 100 characters. When symbols are written to the object file they are silently truncated to eight (or sixteen) characters (depending on the object file format) with no check for (or warnings about) collisions. For example, all of the following symbols are legal and unique: *11 reallyLongSymbolName .reallyLongConfinedSymbolName a10 ret move dc frog aa6 a9 ? .a1 .ret .move .dc .frog .a9 .9 .? .0 .00 .000 .1 .11 .111 . ._ _frog ?zippo? sys$system atari Atari ATARI aTaRi while all of the following symbols are illegal: 12days dc.10 dc.z 'quote .right.here @work hi.there $money$ ~tilde Symbols beginning with a period (.) are confined; their scope is between two normal (unconfined) labels. Confined symbols may be labels or equates. It is illegal to make a confined symbol global (with the ``.globl'' directive, a double colon, or a double equals). Only unconfined labels delimit a confined symbol's scope; equates (of any kind) do not count. For example, all symbols are unique and have unique values in the following: zero:: subq.w #1,d1 bmi.s .ret .loop: clr.w (a0)+ dbra d0,.loop .ret: rts FF:: subq.w #1,d1 bmi.s .99 .loop: move.w #-1,(a0)+ dbra d0,.loop .99: rts Confined symbols are useful since the programmer has to be much less inventive about finding small, unique names that also have meaning. It is legal to define symbols that have the same names as processor mnemonics (such as `` move'' or `` rts'') or assembler directives (such as `` .even''). Indeed, one should be careful to avoid typographical errors, such as this classic (in 6502 mode): .6502 .org = $8000 which equates a confined symbol to a hexadecimal value, rather than setting the location counter, which the .org directive does (without the equals sign). Keywords The following names, in all combinations of uppercase and lowercase, are keywords and may not be used as symbols (e.g. labels, equates, or the names of macros): equ set reg sr ccr pc sp ssp usp d0 d1 d2 d3 d4 d5 d6 d7 a0 a1 a2 a3 a4 a5 a6 a7 r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 *12 Constants Numbers may be decimal, hexadecimal, octal, binary or concatenated ASCII. The default radix is decimal, and it may not be changed. Decimal numbers are specified with a string of digits (0-9). Hexadecimal numbers are specified with a leading dollar sign ($) followed by a string of digits and uppercase or lowercase letters (A-F a-f). Octal numbers are specified with a leading at-sign (@) followed by a string of octal digits (0-7). Binary numbers are specified with a leading percent sign (%) followed by a string of binary digits (0-1). Concatenated ASCII constants are specified by enclosing from one to four characters in single or double quotes. For example: 1234 decimal $1234 hexadecimal @777 octal %10111 binary "z" ASCII 'frog' ASCII Negative numbers are specified with a unary minus (-). For example: -5678 -@334 -$4e71 -%11011 -'z' -"WIND" Strings Strings are contained between double (") or single (') quote marks. Strings may contain non-printable characters by specifying ``backslash'' escapes, similar to the ones used in the C programming language. MADMAC will generate a warning if a backslash is followed by a character not appearing below: \\ $5c backslash \n $0a line-feed (newline) \b $08 backspace \t $09 tab \r $0d carriage-return \f $0c form-feed \e $1b escape \' $27 singleK-quote \" $22 double-quote It is possible for strings (but not symbols) to contain characters with their high bits set (i.e. character codes 128...255). You should be aware that backslash characters are popular in GEMDOS path names, and that you may have to escape backslash characters in your existing source code. For example, to get the file "c:\auto\ahdi.s" you would specify the string "c:\\auto\\ahdi.s". Register Lists Register lists are special forms used with the movem mnemonic and the .reg directive. They are 16-bit values, with bits 0 through 15 corresponding to registers D0 through A7. A register list consists of a series of register names or register ranges seperated by slashes. A register range consists of two register names, Rm and Rn, m> 1, line3/4 Line 1 deposits two longwords that point to line 2. Line 2 deposits two longwords that point to line 1. Line 3 deposits two longwords that have the absolute value eight. The fourth line will result in an assembly error, since the expressions (respectively) attempt to add two relocatable values, shift a relocatable value right by one, and divide a relocatable value by four. The pseudo-symbol ``*'' (star) has the value that the current section's location counter had at the beginning of the current source line. For example, these two statements deposit three pointers to the label ``bar'': foo: dc.l *+4 bar: dc.l *, * Similarly, the pseudo-symbol ``$'' has the value that the current section's location counterp has, and it is kept up to date as the assembler deposits information ``across'' a line of source code. For example, these two statements deposit four pointers to the label ``zip'': zip: dc.l $+8, $+4 zop: dc.l $, $-4 *15 Unary Operators Operator Description - - - Unary minus (2's complement). ! Logical (boolean) NOT. ~ Tilde: bitwise not (1's complement). ^^ defined symbol True if symbol has a value. ^^ referenced symbol True if symbol has been referenced. ^^ streq string1, string2True if the strings are equal. ^^ macdef macroName True if the macro is defined. o The boolean operators generate the value $1$ if the expression is true, and $0$ if it is not. o A symbol is referenced if it is involved in an expression. A symbol may have any combination of attributes: undefined and unreferenced, defined and unreferenced (i.e. declared but never used), undefined and referenced (in the case of a forward or external reference), or defined and referenced. Binary Operators Operator Description - - + - * The usual arithmetic operators. % Modulo. & | ^ Bit-wise AND, OR and Exclusive-OR. << >> Bit-wise shift left and shift right. < <= >= > Boolean magnitude comparisons. = Boolean equality. <> != Boolean inequality. o All binary operators have the same precedence: expressions are evaluated strictly left to right. o Division or modulo by zero yields an assembly error. o The ``<>'' and ``!='' operators are synonyms. o Note that the modulo operator (%) is also used to introduce binary constants (see: Constants). A percent sign should be followed by at least one space if it is meant to be a modulo operator, and is followed by a `0' or `1'. Special Forms Special Form Description ^^ date The current system date (Gemdos format). ^^ time The current system time (Gemdos format). o The `` ^^ date'' special form expands to the current system date, in Gemdos format. The format is a 16-bit word with bits 0...4 indicating the day of the month (1...31), bits 5...8 indicating the month (1...12), and bits 9...15 indicating the year since 1980, in the range 0...119. *16 o The `` ^^ time'' special form expands to the current system time, in Gemdos format. The format is a 16-bit word with bits 0...4 indicating the current second divided by 2, bits 5...10 indicating the current minute 0...59, and bits 11...15 indicating the current hour 0...23. Example Expressions line address contents source code - - - - 1 0 4480 lab1: neg.l d0 2 02 42790 lab2: clr.w lab1 3 =064 equ1 = 100 4 =096 equ2 = equ1 + 50 5 08 064 dc.l lab1 + equ1 6 0C 7FE6 dc.l (equ1 + ~equ2) >> 1 7 010 0001 dc.w ^^ defined equ1 8 012 0 dc.w ^^ referenced lab2 9 014 02 dc.l lab2 10 018 0001 dc.w ^^ referenced lab2 11 01A 0001 dc.w lab1 = (lab2 - 6) Lines 1 through four here are used to set up the rest of the example. Line 5 deposits a relocatable pointer to the location 100 bytes beyond the label " lab1". Line 6 is a nonsensical expression that uses the ~ and right-shift operators. Line 7 deposits a word of 1 because the symbol `` equ1'' is defined (in line 3). Line 8 deposits a word of 0 because the symbol `` lab2,'' defined in line 2, has not been referenced. But the expression in line 9 references the symbol `` lab2,'' so line 10 (which is a copy of line 8) deposits a word of 1. Finally, line 11 deposits a word of 1 because the boolean equality operator evaluates to true. The operators `` ^^ defined'' and `` ^^ referenced'' are particularly useful in conditional assembly. For instance, it is possible to automatically incl^ude debugging code if the debugging code is referenced, as in: lea string,a0 ; A0 -> message jsr debug ; print a message rts ; and return string: dc.b "Help me, Spock!",0 ; (the message) : .iif ^ ^ defined debug, .include "debug.s" The jsr statement references the symbol debug. Near the end of the source file, the `` .iif'' statement includes the file `` debug.s'' if the symbol debug was referenced. In production code, presumably all references to the debug symbol will be removed, and the debug source file will not be included. (We could have as easily made the symbol debug external, instead of including another source file). *17 Directives Assembler directives may be any mix of upper- or lowercase. The leading periods are optional, though they are shown here and their use is encouraged. Directives may be preceeded by a label; the label is defined before the directive is executed. Some directives accept size suffixes ( .b, .s, .w or .l); the default is word ( .w) if no size is specified. The .s suffix is identical to .b. Directives relating to the 6502 are described in the chapter on 6502 Support. .even If the location counter for the current section is odd, make it even by adding one to it. In text and data sections a zero byte is deposited if necessary. .assert expression [,expression...] Assert that the conditions are true (non-zero). If any of the comma- seperated expressions evaluates to zero an assembler warning is issued. For example: .assert *-start = $76 .assert stacksize >= $400 .bss .data .text Switch to the BSS, data or text segments. Instructions and data may not be assembled into the BSS segment, but symbols may be defined and storage may be reserved with the .ds directive. Each assembly starts out in the text segment. .abs [location] Start an absolute section, beginning with the specified location (or zero, if no location is specified). An absolute section is much like BSS, except that locations declared with .ds are based absolute. This directive is useful for declaring structures or hardware locations. For example, the following equates: VPLANES = 0 VWRAP = 2 CONTRL = 4 INTIN = 8 PTSIN = 12 could be as easily defined as: .abs VPLANES: ds.w 1 VWRAP: ds.w 1 CONTRL: ds.l 1 INTIN: ds.l 1 PTSIN: ds.l 1 *18 .comm symbol, expression Specifies a label and the size of a common region. The label is made global, thus confined symbols cannot be made common. The linker groups all common regions of the same name; the largest size determines the real size of the common region when the file is linked. .dc [ .size] expression [ ,expression...] Deposit initialized storage in the current section. If the specified size is word or long, the assembler will execute a .even before depositing data. If the size is .b, then strings that are not part of arithmetic expressions are deposited byte-by-byte. If no size is specified, the default is .w. This directive cannot be used in the BSS section. .dcb [ .size] expression1, expression2 Generate an initialized block of expression1 bytes, words or longwords of the value expression2. If the specified size is word or long, the assembler will execute .even before generating data. If no size is specified, the default is .w. This directive cannot be used in the BSS section. .ds [ .size] expression Reserve space in the current segment for the appropriate number of bytes, words or longwords. If no size is specified, the default size is .w. If the size is word or long, the assembler will execute .even before reserving space. This directive can only be used in the BSS or ABS sections (in text or data, use .dcb to reserve large chunks of initialized storage.) .init [.size] [#expression,]expression[.size][ , ...] Generalized initialization directive. The size specified on the directive becomes the default size for the rest of the line. (The ``default'' default ^ size is .w.) A comma-seperated list of expressions follows the directive; an expression may be followed by a size to override the default size. An expression may be preceeded by a sharp sign, an expression and a comma, which specifies a repeat count to be applied to the next expression. For example: .init.l -1, 0.w, # 16,'z'.b, # 3,0, 11.b will deposit a longword of -1, a word of zero, sixteen bytes of lower-case ' z', three longwords of zero, and a byte of 11. No auto-alignment is performed within the line, but a .even is done once (before the first value is deposited) if the default size is word or long. .cargs [#expression,]symbol[.size][, symbol[.size]...] Compute stack offsets to C (and other language) arguments. Each symbol is assigned an absolute value (like equ) which starts at expression and increases by the size of each symbol, for each symbol. If the expression is not supplied, the default starting value is 4. For example: .cargs # 8, .fileName.l, .openMode, .bufPointer.l could be used to declare offsets from A6 to a pointer to a filename, a word containing an open mode, and a pointer to a buffer. (Note that the symbols used here are confined). Another example, a C-style ``string- length'' function, could be written as: *19 _strlen:: .cargs .string ; declare arg move.l .string(sp),a0 ; a0 -> string moveq #-1,d0 ; initial size = -1 .1: addq.l #1,d0 ; bump size tst.b (a0)+ ; at end of string? bne .1 ; (no -- try again) rts ; return string length .end End the assembly. In an include file, end the include file and resume assembling the superior file. This statement is not required, nor are warning messages generated if it is missing at the end of a file. This directive may be used inside conditional assembly, macros or .rept blocks. .if expression .else .endif Start a block of conditional assembly. If the expression is true (non- zero) then assemble the statements between the .if and the matching .endif or .else. If the expression is false, ignore the statements unless a matching .else is encountered. Conditional assembly may be nested to any depth. It is possible to exit a conditional assembly block early from within an include file (with end) or a macro (with endm). .iif expression, statement Immediate version of .if. If the expression is true (non-zero) then the statement, which may be an instruction, a directive or a macro, is executed. If the expression is false, the statement is ignored. No .endif is required. For example: .iif age < 21, canDrink = 0 .iif weight > 500, dangerFlag = 1 .iif !(^^ defined DEBUG), .include dbsrc .macro name [ formal, formal, ...] .endm .exitm Define a macro called name with the specified formal arguments. The macro definition is terminated with a .endm statement. A macro may be exited early with the .exitm directive. See the chapter on Macros for more information. .undefmac macroName [ , macroName...] Remove the macro-definition for the specified macro names. If reference is made to a macro that is not defined, no error message is printed and the name is ignored. .rept expression .endr The statements between the .rept and .endr directives will be repeated expression times. If the expression is zero or negative, no statements will be assembled. No label may appear on a line containing either of these directives. .globl symbol [ , symbol...] .extern symbol [ , symbol...] Each symbol is made global. None of the symbols may be confined symbols (those starting with aperiod). If the symbol is defined in the assembly, *20 the symbol is exported in the object file. If the symbol is undefined at the end of the assembly, and it was referenced (i.e. used in an expression), then the symbol value is imported as an external reference that must be resolved by the linker. The .extern directive is merely a synonym for .globl. .include "file " Include a file. If the filename is not enclosed in quotes, then a default extension of `` .s'' is applied to it. If the filename is quoted, then the name is not changed in any way. Note: If the filename is not a valid symbol, then the assembler will generate an error message. You should enclose filenames such as `` atari.s'' in quotes, because such names are not symbols. If the include file cannot be found in the current directory, then the directory search path, as specified by -i on the commandline, or by the MACPATH enviroment string, is traversed. .eject Issue a page eject in the listing file. .title " string " .subttl [ - ] " string " Set the title or subtitle on the listing page. The title should be specified on the the first line of the source program in order to take effect on the first page. The second and subsequent uses of .title will cause page ejects. The second and subsequent uses of .subttl will cause page ejects unless the subtitle string is preceeded by a dash (-). .list .nlist Enable or disable source code listing. These directives increment and decrement an internal counter, so they may be appropriately nested. They have no effect if the -l switch is not specified on the commandline. .goto label This directive provides unstructured flow of control within a macro definition. It will transfer control to the line of the macro containing the specified goto label. A goto label is a symbol preceeded by a colon that appears in the first column of a source line within a macro definition: : label where the label itself can be any valid symbol name, followed immediately by whitespace and a valid source line (or end of line). The colon must appear in the first column. The goto-label is removed from the source line prior to macro expansion -- to all intents and purposes the label is invisible except to the .goto directive. Macro expansion does not take place within the label. For example, here is a silly way to count from 1 to 10 without using .rept: .macro Count count set 1 :loop dc.w count count set count + 1 iif count <= 10, goto loop .endm *21 68000 Mnemonics Mnemonics All of the standard Motorola 68000 mnemonics and addressing modes are supported; you should refer to The Motorola M68000 Programmer's Reference Manual for a description of the instruction set and the allowable addressing modes for each instruction. With one major exception (forward branches) the assembler performs all the reasonable optimizations of instructions to their short or address register forms. Register names may be in upper or lower case. The alternate forms R0 through R15 may be used to specify D0 through A7. All register names are keywords, and may not be used as labels or symbols. None of the 68010 or 68020 register names are keywords (but they may become keywords in the future). Addressing Modes Assembler Syntax Description - - Dn Data register direct An Address register direct (An) Address register indirect (An)+ Address register indirect postincrement -(An) Address register indirect predecrement disp(An) Address register indirect with displacement bdisp(An, Xi[.size]) Address register indirect indexed abs.w Absolute short abs Absolute (long or short) abs.l Forced absolute long disp(PC) Program counter with displacement bdisp(PC, Xi) Program counter indexed #imm Immediate Branches Since MADMAC is a one pass assembler, forward branches cannot be automatically optimized to their short form. Instead, unsized forward branches are assumed to be long. Backward branches are always optimized to the short form if possible. A table that lists ``extra'' branch mnemonics (common synonyms for the Motorola defined mnemonics) appears below. *22 Branch Synonyms Alternate name Becomes: -- - bhs bcc blo bcs bze, bz beq bnz bne dblo dbcs dbze dbeq dbra dbf dbhs dbhi dbnz dbne Linker Constraints It is not possible to make an external reference that will fix up a byte. For example: .extern frog move.l frog(pc,d0),d1 is illegal (and generates an assembly error) when frog is external, because the displacement occupies a byte field in the 68000 offset word, which the object file cannot represent. Optimizations and Translations The assembler provides ``creature comforts'' when it processes 68000 mnemonics: o CLR. x A n will really generate SUB. x A n,A n. o ADD, SUB and CMP with an address register will really generate ADDA, SUBA and CMPA. o The ADD, AND, CMP, EOR, OR and SUB mnemonics with immediate first operands will generate the ``I'' forms of their instructions ( ADDI, etc.) if the second operand is not register direct. o All shift instructions with no count value assume a count of one. o MOVE.L is optimized to MOVEQ if the immediate operand is defined and in the range -128...127. However, ADD and SUB are never translated to their quick forms; ADDQ and SUBQ must be explicit. *23 Macros A macro definition is a series of statements of the form: .macro name [ formal-arg, ...] : statements making up the macro body : .endm The name of the macro may be any valid symbol that is not also a 68000 instruction or an assembler directive. (The name may begin with a period -- - macros cannot be made confined the way labels or equated symbols can be). The formal argument list is optional; it is specified with a comma-seperated list of valid symbol names. Note that there is no comma between the name of the macro and the name of the first formal argument A macro body begins on the line after the .macro directive. All instructions and directives, except other macro definitions, are legal inside the body. The macro ends with the .endm statement. If a label appears on the line with this directive, the label is ignored and a warning is generated. Parameter Substitution Within the body, formal parameters may be expanded with the special forms: \name \{name} The second form (enclosed in braces) can be used in situations where the characters following the formal parameter name are valid symbol continuation characters. This is usually used to force concatentation, as in: \{frog}star \{godzilla}vs\{reagan} The formal parameter name is terminated with a character that is not valid in a symbol (e.g. whitespace or puncuation); optionally, the name may be enclosed in curly-braces. The names must be symbols appearing on the formal argument list, or a single decimal digit (\1 corresponds to the first argument, \2 to the second, \9 to the ninth, and \0 to the tenth). It is possible for a macro to have more than ten formal arguments, but arguments 11 and on must be referenced by name, not by number. Other special forms are: Special Form Description - - \\ a single `` \'' \~ a unique label of the form `` M n'' \# the number of arguments actually specified \! the ``dot-size'' specified on the macro invocation \? nameconditional expansion \? {name} conditional expansion The last two forms are identical: if the argument is specified and is non- empty, the form expands to a `` 1'', otherwise (if the argument is missing or empty) the form expands to a `` 0''. The form ``\!'' expands to the ``dot-size'' that was specified when the macro was invoked. This can be used to write macros that behave differently *24 depending on the size suffix they are given, as in this macro which provides a synonym for the `` dc'' directive: .macro deposit value dc\! \value .endm deposit.b 1 ; byte of 1 deposit.w 2 ; word of 2 deposit.l 3 ; longword of 3 deposit 4 ; word of 4 (no explicit size) Macro Invocation A previously-defined macro is called when its name appears in the operation field of a statement. Arguments may be specified following the macro name; each argument is seperated by a comma. Arguments may be empty. Arguments are stored for substitution in the macro body in the following manner: o Numbers are converted to hexadecimal. o All spaces outside strings are removed. o Keywords (such as register names, dot sizes and "^^" operators) are converted to lowercase. o Strings are enclosed in double-quote marks ("). For example, a hypothetical call to the macro `` mymacro'', of the form: mymacro A0, , 'Zorch' / 32, ^^ DEFINED foo, , , tick tock will result in the translations: Argument Expansion Comment - - - \1 a0 `` A0'' converted to lower-case \2 empty \3 "Zorch"/$20 `` Zorch'' in double-quotes, 32 in hexadecimal \4 ^^ defined foo`` ^^ DEFINED'' converted to lower-case \5 empty \6 empty \7 ticktock spaces removed (note concatenation) *25 The .exitm directive will cause an immediate exit from a macro body. Thus the macro definition: .macro foo source .iif !\?source, .exitm ; exit if source is empty move \source,d0 ; otherwise, deposit source .endm will not generate the move instruction if the argument `` source'' is missing from the macro invocation. The .end, .endif and .exitm directives all pop-out of their include levels appropriately. That is, if a macro performs a .include to include a source file, an executed .exitm directive within the include-file will pop out of both the include-file and the macro. Macros may be recursive or mutually recursive to any level, subject only to the availability of memory. When writing recursive macros, take care in the coding of the termination condition(s). A macro that repeatedly calls itself will cause the assembler to exhaust its memory and abort the assembly. Example Macros The Gemdos macro is used to make file system calls. It has two parameters, a function number and the number of bytes to clean off the stack after the call. The macro pushes the function number onto the stack and does the trap to the file system. After the trap returns, conditional assembly is used to choose an addq or an add.w to remove the arguments that were pushed. .macro Gemdos trpno, clean move.w #\trpno,-(sp) ; push trap number trap #1 ; do GEMDOS trap .if \clean <= 8 ; addq #\clean,sp ; clean-up up to 8 bytes .else ; add.w #\clean,sp ; clean-up more than 8 bytes .endif ; .endm The Fopen macro is supplied two arguments; the address of a filename, and the open mode. Note that plain move instructions are used, and that the caller of the macro must supply an appropriate addressing mode (e.g. immediate) for each argument. .macro Fopen file, mode move.w \mode,-(sp) ; push open mode move.l \file,-(sp) ; push address of file name Gemdos $3d,8 ; do the GEMDOS call .endm The String macro is used to allocate storage for a string, and to place the string's address somewhere. The first argument should be a string or other expression acceptable in a dc.b directive. The second argument is optional; it specifies where the address of the string should be placed. If the second argument is omitted, the string's address is pushed onto the stack. The string data itself is kept in the data segment. *26 .macro String str,loc .if \?loc ; if loc is defined move.l #.\~,\loc ; put the string's address there .else ; otherwise pea .\~ ; push the string's address .endif ; .data ; put the string data .\~: dc.b \ str,0 ; in the data segment .text = ; and switch back to the text segment .endm The construction `` .\~'' will expand to a label of the form `` .M n'' (where n is a unique number for every macro invocation), which is used to tag the location of the string. The label should be confined because the macro may be used along with other confined symbols. Unique symbol generation plays an important part in the art of writing fine macros. For instance, if we needed three unique symbols, we might write `` .a\~'', `` .b\~'' and `` .c\~''. Repeat Blocks Repeat-blocks provide a simple iteration capability. A repeat block allows a range of statements to be repeated a specified number of times. For instance, to generate a table consisting of the numbers 255 through 0 (counting backwards) you could write: .count set 255 ; initialize counter .rept 256 ; repeat 256 times: dc.b .count ; deposit counter .count set .count - 1 ; and decrement it .endr ; (end of repeat block) Repeat blocks can also be used to duplicate identical pieces of code (which are common in bitmap-graphics routines). For example: .rept 16 ; clear 16 words clr.w (a0)+ ; starting at A0 .endr ; *27 6502 Support MADMAC will generate code for the Motorola 6502 microprocessor. This chapter describes extra addressing modes and directives used to support the 6502. As the 6502 object code is not linkable (currently there is no linker) external references may not be made. (Nevertheless, MADMAC may reasonably be used for large assemblies because of its blinding speed.) All standard 6502 addressing modes are supported, with the exception of the accumulator addressing form, which must be omitted (e.g. `` ror a'' becomes `` ror''). Five extra modes, synonyms for existing ones, are included for compatibility with the Atari Coinop assembler. empty implied or accumulator (e.g. tsx or ror) expr absolute or zeropage #expr immediate (expr,x) indirect X (expr),y indirect Y (expr) indirect expr,x indexed X expr,y indexed Y @expr(x) indirect X @expr(y) indirect Y @expr indirect x,expr indexed X y,expr indexed Y While MADMAC lacks ``high'' and ``low'' operators, high bytes of words may be extracted with the shift ( >>) or divide ( /) operators, and low bytes may be extracted with the bitwise AND (&) operator. .6502 This directive enters the 6502 section. The location counter is undefined, and must be set with `` .org'' before any code can be generated. The `` dc.w'' directive will produce 6502-format words (low byte first). The 68000's reserved keywords ( d0- d7/ a0- a7/ ssp/ usp and so on) remain reserved (and thus unusable) while in the 6502 section. The directives globl, dc.l, dcb.l, text, data, bss, abs, even and comm are illegal in the 6502 section. It is permitted, though probably not useful, to generate both 6502 and 68000 code in the same object file. .68000 This directive leaves the 6502 segment and returns to the 68000's text segment. 68000 instructions may be assembled as normal. .org location This directive is only legal in the 6502 section. It sets the value of the location counter (or pc) to location, an expression that must be defined, absolute, and less than $10. *28 WARNING It is possible to assemble ``beyond'' the microprocessor's 64K address space, but attempting to do so will probably screw up the assembler. DO NOT attempt to generate code like this: .org $fffe nop nop nop the third NOP in this example, at location $10, may cause the assembler to crash or exhibit spectacular schizophrenia. In any case, MADMAC will give no warning before flaking out. Object Code Format This is a little bit of a kludge. An object file consists of a page map, followed by one or more page images, followed by a normal Alcyon 68000 object file. If the page map is all zero, it is not written. The page map  contains a byte for each of the 256 256-byte pages in the 6502's 64K address space. The byte is zero ($00) if the page contained only zero bytes, or one ($01) if the page contained any non-zero bytes. If a page is flagged with a one, then it is written (in order) following the page map. The following code: .6502 .org $8000 .dc.b 1 .org $8100 .dc.b 1 .org $8300 .dc.b 1 .end will generate a page map that looks (to a programmer) something like: <$80 bytes of zero> 01 01 00 01 <$7c more bytes of zero, for $100 total> < image of page $80> < image of page $81> < image of page $83> Following the last page image is an Alcyon-format object file, starting with the magic number $601a. It may contain 68000 code (although that is probably useless), but the symbol table is valid and available for debugging purposes. 6502 symbols will be absolute (not in text, data or bss). *29 Error Messages When Things Go Wrong Most of MADMAC's error messages are self-explanatory. They fall into four classes: warnings about situations that you (or the assembler) may not be happy about, errors that cause the assembler to not generate object files, fatal errors that cause the assembler to abort immediately, and internal errors that should never happen.3 You can write editor macros (or sed or awk scripts) to parse the error messages MADMAC generates. When a message is printed, it is of the form: " filename", line line-number: message The first element, a filename enclosed in double quotes, indicates the file that generated the error. The filename is followed by a comma, the word `` line'', and a line number, and finally a colon and the text of the message. The filename `` (*top*)'' indicates that the assembler could not determine which file had the problem. The following sections list warnings, errors and fatal errors in alphabetical order, along with a short description of what may have caused the problem. Warnings bad backslash code in string You tried to follow a backslash in a string with a character that the assembler didn't recognize. Remember that MADMAC uses a C-style escape system in strings. label ignored You specified a label before a macro, rept or endm directive. The assembler is warning you that the label will not be defined in the assembly. unoptimized short branch This warning is only generated if the -s switch is specified on the command line. The message refers to a forward, unsized long branch that you could have made short ( .s). Fatal Errors cannot continue As a result of previous errors, the assembler cannot continue processing. The assembly is aborted. line too long as a result of macro expansion When a source line within a macro was expanded, the resultant line was too long for MADMAC (longer than 200 characters or so). _ 3If you come across an internal error, we would appreciate it if you would contact Atari Technical Support and let us know about the problem. *30 memory exhausted The assembler ran out of memory. You should (1) split up your source files and assemble them seperately, or (2) if you have any ramdisks or RAM- resident programs (like desk accessories) decrease their size so that the assembler has more RAM to work with. As a rule of thumb, pure 68000 code will use up to twice the number of bytes contained in the source files, whereas 6502 code will use 64K of ram right away, plus the size of the source files. The assembler itself uses about 80K bytes. Get out your calculator... too many ENDMs The assembler ran across an endm directive when it wasn't expecting to see one. The assembly is aborted. Check the nesting of your macro definitions --- you probably have an extra endm. Errors .cargs syntax Syntax error in .cargs directive. .comm symbol already defined You tried to .comm a symbol that was already defined. .ds permitted only in BSS You tried to use .ds in the text or data section. .init not permitted in BSS or ABS You tried to use .init in the BSS or ABS section. .org permitted only in .6502 section You tried to use .org in a 68000 section. Cannot create: filename The assembler could not create the indicated filename. External quick reference You tried to make the immediate operand of a moveq, subq or addq instruction external. PC-relative expr across sections You tried to make a PC-relative reference to a location contained in another section. [bwsl] must follow `.' in symbol You tried to follow a dot in a symbol name with something other than one of the four characters `B', `W', `S' or `L'. addressing mode syntax You made a syntax error in an addressing mode. assert failure One of your .assert directives failed! bad (section) expression You tried to mix and match sections in an expression. bad 6502 addressing mode The 6502 mnemonic will not work with the addressing mode you specified. bad expression There's a syntax error in the expression you typed. *31 bad size specified You tried to use an inappropriate size suffix for the instruction. Check your 68000 manual for allowable sizes. bad size suffix You can't use .b (byte) mode with the movem instruction. cannot .globl local symbol You tried to make a confined symbol global or common. cannot initialize non-storage (BSS) section You tried to generate instructions (or data, with dc) in the BSS or ABS section. cannot use '.b' with an address register You tried to use a byte-size suffix with an address register. The 68000 does not perform byte-sized address register operations. directive illegal in .6502 section You tried to use a 68000-oriented directive in the 6502 section. divide by zero The expression you typed involves a division by zero. expression out of range The expression you typed is out of range for its application. external byte reference You tried to make a byte-sized reference to an external symbol, which the object file format will not allow. external short branch You tried to make a short branch to an external symbol, which the linker cannot handle. extra (unexpected) text found after addressing mode MADMAC thought it was done processing a line, but it ran up against ``extra'' stuff. Be sure that any comment on the line begins with a semicolon, and check for dangling commas, etc. forward or undefined .assert The expression you typed after a .assert directive had an undefined value. Remember that MADMAC is one-pass. hit EOF without finding matching .endif The assembler fell off the end of last input file without finding a .endif to match an .if. You probably forgot a .endif somewhere. illegal 6502 addressing mode The 6502 instruction you typed doesn't work with the addressing mode you specified. illegal absolute expression You can't use an absolute-valued expression here. illegal bra.s with zero offset You can't do a short branch to the very next instruction (read your 68000 manual). illegal byte-sized relative reference *32 The object file format does not permit bytes contain relocatable values; you tried to use a byte-sized relocatable expression in an immediate addressing mode. illegal character Your source file contains a character that MADMAC doesn't allow. (most control characters fall into this category). illegal initialization of section You tried to use .dc or .dcb in the BSS or ABS sections. illegal relative address The relative address you specified is illegal because it belongs to a different section. illegal word relocatable (in .PRG mode) You can't have anything other than long relocatable values when you're generating a .PRG file. inappropriate addressing mode The mnemonic you typed doesn't work with the addressing modes you specified. Check your 68000 manual for allowable combinations. invalid addressing mode The combination of addressing modes you picked for the movem instruction are not implemented by the 68000. Check your 68000 reference manual for details. invalid symbol following ^^ What followed the ^^ wasn't a valid symbol at all. mis-nested .endr The assembler found a .endr directive when it wasn't preparued to find one. Check your repeat-block nesting. mismatched .else The assembler found a .else directive when it wasn't prepared to find one. Check your conditional assembly nesting. mismatched .endif The assembler found a .endif directive when it wasn't prepared to find one. Check your conditional assembly nesting. missing ' =' missing ' \CloseBrace' missing argument name missing close parenthesis ' )' missing close parenthesis ' ]' missing comma missing filename missing string missing symbol missing symbol or string The assembler expected to see a symbol/filename/string (etc...), but found something else instead. In most cases the problem should be obvious. misuse of `.', not allowed in symbols You tried to use a dot ( .) in the middle of a symbol name. mod (%) by zero The expression you typed involves a modulo by zero. *33 multiple formal argument definition The list of formal parameter names you supplied for a macro definition includes two identical names. multiple macro definition You tried to define a macro which already had a definition. non-absolute byte reference You tried to make a byte reference to a relocatable value, which the object file format does not allow. non-absolute byte value You tried to dc.b or dcb.b a relocatable value. Byte relocatable values are not permitted by the object file format. register list order You tried to specify a register list like D7-D0, which is illegal. Remember that the first register number must be less than or equal to the second register number. register list syntax You made an error in specifying a register list for a .reg directive or a .movem instruction. symbol list syntax You probably forgot a comma between the names of two symbols in a symbol list, or you left a comma dangling on the end of the line. syntax error This is a ``catch-all'' error. undefined expression The expression has an undefined value because of a forward reference, or an undefined or external symbol. unimplemented addressing mode You tried to use 68020 ``square-bracket'' notation for a 68020 addressing mode. MADMAC does not support 68020 addressing modes. unimplemented directive You have found a directive that didn't appear in the documentation. It doesn't work. unimplemented mnemonic You've found an assembler (or documentation) bug. unknown symbol following ^^ You followed a ^^ with something other than one of the names defined, referenced or streq. unsupported 68020 addressing mode The assembler saw a 68020-type addressing mode. MADMAC does not assemble code for the 68020 or 68010. unterminated string You specified a string starting with a single or double quote, but forgot to type the closing quote. write error The assembler had a problem writing an object file. This is usually caused by a full disk, or a bad sector on the media. *34 B MadMAC 1.05 Beta Release 18-Aug-1988 (If you have a copy of MadMAC with a version number "0.11t" or earlier, it is definitely advantagous to use 0.13, since there have been a significant number of bug fixes.) Files in the distribution are: README Distribution documentation MAC.PRG Macro assembler CONV65.PRG 6502 object file converter CONV65.MAN Man page for CONV65.PRG M.PRG "Quick" MAC.PRG invoker ATARI.S Equates and macros for Atari ST programming CODE.S 68000 op codes the assembler implements CODE65.S 6502 opcodes the assembler implements INSTMAC.S Sample MAC installer (silly example) EXAMPLE.S \ EXAMPLE1.S ->- Silly example programs EXAMPLE2.S / BUGS.S \ SHIFT.S ->- another silly example program IMAGES.S / MAC and ALN perform their functions in memory, so you may have to remove large desk accessories and ramdisks for them to operate on large programs. J;--- Exports: .globl mksh ;--- Imports: .globl _images .globl _masks ;+ ; Construct shifted images and masks ; ; Passed: a1 -> free memory ; ;- mksh:: lea _images,a5 .1: tst.l (a5) beq.s .2 move.l (a5)+,a0 bsr mkshimg bra.s .1 .2: lea _masks,a5 .3: tst.l (a5) beq.s .4 move.l (a5)+,a0 bsr mkshmsk bra.s .3 .4: rts ;+ ; Complete shifted entries in an image table. ; ; Passed: a0 -> image table with one aligned image in it ; a1 -> free memory ; ; Returns: table filled in with 15 more (shifted) entries ; a0 -> next table (probably) ; a1 -> next location in free memory ; ; Uses: d0-d4/a0-a4 ; ;- mkshimg: move.l (a0)+,a3 ; a3 -> original image moveq #1,d2 ; d2 = shift amount {1, 2, .. 15} .3: move.l a1,(a0)+ ; fill in table address moveq #16-1,d4 ; d4 = scanline count move.l a3,a2 ; a2 -> original image .4: moveq #0,d1 ; d1 = plane count {0, 2, 4, 6} .1: move.w (a2,d1.w),d0 lsr.w d2,d0 move.w d0,(a1,d1.w) addq.w #2,d1 cmp.w #8,d1 bne.s .1 moveq #16,d3 ; d3 = left-shift count sub.w d2,d3 ; = 16 - shiftCount moveq #0,d1 ; d1 = plane count {0, 2, 4, 6} .2: move.w (a2,d1.w),d0 lsl.w d3,d0 move.w d0,8(a1,d1.w) addq.w #2,d1 cmp.w #8,d1 bne.s .2 add.w #16,a1 ; bump dest to next free spot addq.w #8,a2 ; bump to next 4-plane entry in src dbra d4,.4 ; do another scanline addq.w #1,d2 ; bump shift count cmp.w #16,d2 ; if (shiftCount != 16) bne.w .3 ; loop for more shifted tables rts ;+ ; Complete shifted images in a mask table. ; ; Passed: a0 -> mask table with one aligned mask in it ; a1 -> free memory ; ; Returns: table filled in with 15 more (shifted) entries ; a0 -> next table (probably) ; a1 -> next location in free memory ; ; Uses: d0-d5/a0-a4 ; ;- mkshmsk: move.l (a0)+,a3 ; a2 -> original image moveq #2,d1 ; d1 = lmask[], rmask[] index moveq #1,d2 ; d2 = shift amount {1, 2, .. 15} .3: move.l a1,(a0)+ ; fill in table address moveq #16-1,d4 ; d4 = scanline count move.l a3,a2 ; a2 -> original image .4: move.w (a2),d0 lsr.w d2,d0 or.w lmask(pc,d1.w),d0 move.w d0,(a1) moveq #16,d3 ; d3 = left-shift count sub.w d2,d3 ; = 16 - shiftCount move.w (a2),d0 lsl.w d3,d0 or.w rmask(pc,d1.w),d0 move.w d0,2(a1) addq.w #2,a2 ; bump src to next mask entry addq.w #4,a1 ; bump dest to next free spot dbra d4,.4 ; loop for more scanlines addq.w #2,d1 ; bump mask table index addq.w #1,d2 ; bump shift count cmp.w #16,d2 ; if (shiftCount != 16) bne.w .3 ; loop for more shifted tables rts lmask: dc.w $0 ; >> 0 dc.w $8000,$c000,$e000,$f000 ; >> 1 (etc.) dc.w $f800,$fc00,$fe00,$ff00 dc.w $ff80,$ffc0,$ffe0,$fff0 dc.w $fff8,$fffc,$fffe ; >>15 rmask: dc.w $f ; << 0 dc.w $7fff,$3fff,$1fff,$0fff ; << 1 (etc.) dc.w $07ff,$03ff,$01ff,$00ff dc.w $007f,$003f,$001f,$000f dc.w $0007,$0003,$0001 ; << 15 %