O$p O` H@! #@%`')+-/1 3@5`79;=?A C@E`GMOQ S@U`WY[]_a c@e`ikmq s@u`wy} @`/ @ ` ` @ ` @ `  / ` ׀  @`@`!o   !Aa!!#%a')+-/1!3A579;?A!CEaO` H@! #@%`')+-/1 3@5`79;=?A C@E`GMOQ S@U`WY[]_a c@e`ikmq s@u`wy} @`/ @ ` ` @ ` @ `  / ` ׀  @`@`!o   !Aa!!#%a')+-/1!3A579;?A!CEaCOLRMOVRSTQ r MAGNETS STQ s MIDISEQRSTQ ,s IPRNTDRVRSTQ s ROUTINESSTQ t GEMTEXT STQ -t README TXT \t Dr " .  r ..  r COEUTIL S r KARATE S s EWMOUSEBAK s NEWMOUSEC s QNEWMOUSEPRG s NEWMOUSEBAT t G* COEUTIL.S - MC68000 cohort for NEWMOUSE * by Joe Chiazzese * Copyright 1986 ANTIC Publishing .globl _save_screen _save_screen: move.w 6(sp),d1 ;copy height to d1 subq.w #1,d1 ;height - 1 = height if count starts at zero move.l 12(sp),a0 ;buffer address to a0 ss1: move.w 4(sp),d0 ;copy width to d0 move.l 8(sp),a1 ;absolute screen address to a1 ss0: move.l (a1)+,(a0)+ ;move all four planes move.l (a1)+,(a0)+ dbf d0,ss0 ;repeat width times add.l #160,8(sp) ;move to next line dbf d1,ss1 ;repeat height times rts ;done .globl _restore_screen _restore_screen: move.w 6(sp),d1 ;copy height to d1 subq.w #1,d1 ;height - 1 = height if count starts at zero move.l 12(sp),a0 ;buffer address to a0 rs1: move.w 4(sp),d0 ;copy width to d0 move.l 8(sp),a1 ;absolute screen address to a1 rs0: move.l (a0)+,(a1)+ ;move all four planes move.l (a0)+,(a1)+ ;(2 longs = 4 words(planes)) dbf d0,rs0 ;repeat width times add.l #160,8(sp) ;move pointer to next line dbf d1,rs1 ;repeat height times rts ;done .globl _shift_image _shift_image: move.w 6(sp),d1 ;height in d1 move.w 16(sp),d2 ;offset to d2 subq.w #1,d1 ;height - 1 = height if count starts at zero subq.w #1,4(sp) ;width - 1 = width if count starts at zero move.l 8(sp),a0 ;object pointer to a0 move.l 12(sp),a1 ;image pointer to a1 si1: move.w 4(sp),d0 ;width in d0 clr.l (a1) ;for each line, the first word of the clr.l 4(a1) ;image must be cleared si0: clr.l d4 ;make sure that the top halves of these clr.l d5 ;registers are zeroed out clr.l d6 clr.l d7 move.w (a0)+,d4 ;load in one word (four planes) move.w (a0)+,d5 ;to be rotated move.w (a0)+,d6 move.w (a0)+,d7 ror.l d2,d4 ;rotate all planes by the offset(d2) ror.l d2,d5 ror.l d2,d6 ror.l d2,d7 or.w d4,(a1)+ ;add low order bits to the high order bits or.w d5,(a1)+ ;stored by move instructions farther or.w d6,(a1)+ ;down in this routine or.w d7,(a1)+ swap d4 ;move high order bits into lower halves swap d5 ;of the registers swap d6 swap d7 move.w d4,(a1) ;save the high orders bits to be ORed move.w d5,2(a1) ;in the loop (do not increment a1 because move.w d6,4(a1) ;the ORs in the loop must function on move.w d7,6(a1) ;the same addresses as these moves. dbf d0,si0 ;repeat width times addq.l #8,a1 ;new line, move to next word( * 4 planes = 8) dbf d1,si1 ;repeat height times rts ;done .globl _make_mask _make_mask: move.w 6(sp),d1 ;height in d1 subq.w #1,d1 ;height - 1 = height if count starts at zero move.l 8(sp),a0 ;image pointer to a0 move.l 12(sp),a1 ;mask /pointer to a1 mm1: move.w 4(sp),d0 ;width in d0 mm0: move.w (a0)+,d2 ;load first plane of bit image in d2 or.w (a0)+,d2 ;OR it with the 3 other planes or.w (a0)+,d2 or.w (a0)+,d2 move.w d2,d3 ;store inverse mask in d3 (temporary) swap d2 ;move inverse mask to top half of register move.w d3,d2 ;and also in bottom half eor.l #-1,d2 ;mask no longer inverse move.l d2,(a1)+ ;store mask in buffer dbf d0,mm0 ;repeat 'width' times dbf d1,mm1 ;repeat 'height' times rts ;done .globl _draw_image _draw_image: move.w 6(sp),d1 ;height to d1 subq.w #1,d1 ;height - 1 = height if count starts at zero move.l 12(sp),a1 ;image pointer to a1 move.l 20(sp),a2 ;mask pointer to a2 move.l 16(sp),a3 ;screen buffer pointer to a3 di1: move.w 4(sp),d0 ;width to d0 move.l 8(sp),a0 ;absolute screen address to a0 di0: move.l (a2)+,d3 ;load mask data into d3 move.l (a1)+,d6 ;load screen image into d6 and d7 move.l (a1)+,d7 ;2 words each covers all 4 planes move.l (a3)+,d4 ;do the same for the background move.l (a3)+,d5 ;in d4 and d5 (from buffer, not screen) and.l d3,d4 ;mask background and.l d3,d5 or.l d6,d4 ;copy image onto background or.l d7,d5 ;giving final image on top of background move.l d4,(a0)+ ;copy final image into screen memory move.l d5,(a0)+ dbf d0,di0 ;repeat for 'width' times add.l #160,8(sp) ;move to next screen line dbf d1,di1 ;repeat 'height' times rts ;done .* KARATEKA.S - bit image for NEWMOUSE from C.O.L.R. Object Editor * Copyright 1986 ANTIC Publishing .globl _bitimage _bitimage: * 2 by 42 words DC.L $01FC0000,$0,$0,$0 DC.L $03FE0000,$0,$0,$0 DC.L $03C0003E,$0,$0,$0 DC.L $038A0074,$0A,$0,$0 DC.L $0380007E,$0,$0,$0 DC.L $030000FE,$0,$0,$0 DC.L $010000FE,$0,$0,$0 DC.L $0FC,$0,$0,$0 DC.L $0F8,$0,$0,$0 DC.L $6038,$00005FC7,$20,$0000E000 DC.L $808,$0000FFF7,$0,$0000F000 DC.L $80E,$00007FF1,$0,$0000F800 DC.L $0040001E,$0000FFA1,$0C,$0000FC00 DC.L $0980001E,$0000F661,$01E,$0000FFE0 DC.L $06000018,$0000F9E7,$801E,$00007FE0 DC.L $0010,$0000FFEF,$40,$0000BFE0 DC.L $0020,$0000FFDF,$0,$00009FE0 DC.L $00C0,$00007F3F,$10,$0000F000 DC.L $0F0,$08FF,$3810,$0000FFF0 DC.L $020,$03FF,$70,$0000FFF8 DC.L $00810000,$0FF,$FC0,$0000FFF8 DC.L $007F0000,$07F,$EC0,$0000FFF8 DC.L $007E0000,$07F,$4080,$0000FF78 DC.L $0,$07F,$C0,$0000E0F8 DC.L $0,$07F,$C0080000,$0000E0F0 DC.L $0040,$03F,$0180,$0000E070 DC.L $0040,$07F,$20F0,$0000C000 DC.L $0,$03F,$2078,$0000C000 DC.L $0020,$01F,$20,$0000E000 DC.L $0020,$03F,$20,$0000E000 DC.L $0,$01F,$20,$0000E000 DC.L $0,$01F,$20,$0000E000 DC.L $0010,$0F,$20,$0000C000 DC.L a $0010,$01F,$20,$0000C000 DC.L $0,$0F,$0,$0000E000 DC.L $0,$0F,$0,$0000E000 DC.L $00080000,$07,$0,$0000E000 DC.L $00080000,$0F,$0,$0000E000 DC.L $0,$07,$0,$0000E000 DC.L $07,$0,$00008000,$0 DC.L $07,$0,$0000C000,$0 DC.L $01,$0,$0000F000,$0   oH"o$o Jof1|1|1|1|1|1|1|1|1|,1|.1|01|21|41|61|81|:1|<1|>1|@1|B1|D1|FaJ@j L @B@NuL @0<NuL @0<Nu1oFJog og`1|Z`1|@ZBhDBhJ!|d|$PaBhBBhHJhFg2(B|g1|N`1|N`1|NaklRhB2(BhZf| tGaBaJ@fV(P AP<8fa.\hD hDj*`r!|%O|tGaNBNu!| tGa8BNu1|ha1|LakRhDShhfRhH]hDShNfB@Nu"<NU./ / //NVBW?<NMN^$"$_"_ _N]Jk Sj0Bg?<NMN^$"$_"_ _N]RSBfB@NuNU./ / //NV>?<NMN^J@g*NV>?<NMN^af0<$"$_"_ _N]NuB@` hDk*/ /* Copyright 1986, ANTIC Publishing */ /*@/ #include "osbind.h" #define BLANKPIX 3 #define MAXX 320 #define MAXY 200 #define OBJW 2 #define OBJH 42 #define COEOBJECT bitimage #define IMAGESIZE ((OBJW + 1) * 8 * OBJH) int contrl[12], intin[128], intout[128], ptsin[128], ptsout[128]; int v_handle, offset; int def_pallete[16]; int demopal[] = { 0x000, 0x555, 0x743, 0x070, 0x007, 0x077, 0x770, 0x707, 0x777, 0x333, 0x732, 0x040, 0x337, 0x055, 0x550, 0x505 }; long imagebuf[16], maskbuf[16], screenbuf[IMAGESIZE], abspos, oldpos, imagestorage, scrbase; extern long COEOBJECT[]; open_workstation(handle) int *handle; { int dummy; appl_init(); v_handle = graf_handle(&dummy,&dummy,&dummy,&dummy); for ( dummy = 0; dummy < 10; ++dummy) intin[dummy] = 1; intin[10] = 2; v_opnvwk(intin,handle,intout); } close_workstation(handle) int handle; { v_clsvwk(handle); appl_exit(); } initialize() { int x,pxy[4]; if (Getrez()) /* if anything but low rez, back to desktop */ { form_alert(1,"[3][This program works ONLY|in low rez.][ OK ]"); return(0); } scrbase = xbios(3); if (!(imagestorage = Malloc((long)IMAGESIZE * 24))) return(0); for (x = 0; x < 16; ++x) def_pallete[x] = Setcolor(x,-1); /* save default pallete */ Setpallete(demopal); vsf_interior(v_handle,2); /* set fill index to dotted */ vsf_style(v_handle,9); /* set fill style to wall pattern */ vsf_color(v_handle,15); /* fill with color 15 */ pxy[0] = pxy[1] = 0; /* top left corner */ pxy[2] = 319; pxy[3] = 199; /* bottom right corner */ vr_recfzl(v_handle,pxy); /* fill'er up */ for (x = 0; x < 16; ++x) { imagebuf[x] = imagestorage + IMAGESIZE * x; maskbuf[x] = imagestorage + IMAGESIZE * 16 + IMAGESIZE * x / 2; shift_image(OBJW,OBJH,COEOBJECT,imagebuf[x],x); make_mask(OBJW,OBJH,imagebuf[x],maskbuf[x]); } save_screen(OBJW,OBJH,scrbase,screenbuf); oldpos = scrbase; return(1); } finish_up() { Mfree(imagestorage); Setpallete(def_pallete); } follow_mouse() { int mousex,mousey,dummy,oldx,oldy; while(!Bconstat(2)) { do { oldx = mousex; oldy = mousey; vq_mouse(v_handle,&dummy,&mousex,&mousey); } while (oldx == mousex && oldy == mousey && !Bconstat(2)); if (mousex > (MAXX - ((OBJW * 16) - BLANKPIX))) mousex = MAXX - ((OBJW * 16) - BLANKPIX); if (mousey > (MAXY - OBJH)) mousey = MAXY - OBJH; abspos = scrbase + (mousey * 160) + ((mousex / 16) * 8); /* (y * 160) = absolute offset in lines */ /* (x / 16) = which word the pixel lies in */ /* x is multiplied by eight to get the nth word */ /* from the FIRST plane (remember there are 4 planes */ /* 2 bytes per word dividing first removes the remainder */ offset = mousex % 16; xbios(37); /* wait for vsync */ if (abspos != oldpos) { restore_screen(OBJW,OBJH,oldpos,screenbuf); save_screen(OBJW,OBJH,abspos,screenbuf); oldpos = abspos; } draw_image(OBJW,OBJH,abspos,imagebuf[offset],screenbuf, maskbuf[offset]); } Bconin(2); } main() { open_workstation(&v_handle); v_hide_c(v_handle,0); if (initialize()) { follow_mouse(); finish_up(); } v_show_c(v_handle,0); close_workstation(v_handle); } ` D&*O.|*m - ЭЭм// ??<JNA Nn/<NA"/0<NBNuNVN l.U/U/U/UN  3'Bn`0n 0Rn n m3 ."/./< N PN^NuNV>NN N^NuNV>NJ@g. ?<N TB@`>N##.^?<HNT#$(fB@`Bn`*0n&/??9'N DT> ?9'N ~T>?9'N TB@=@=@=|?=|.?9'N TBn`0.й$(2n&"0.HHй$(м?2n#">0n"|&/0/<?<*?<N 0n"|#.0n"|&/0?<*?<NlPRn nmF. /9#?<*?<NP##&pN^NuNV.$(?<INT.&?<NTN^NuNV`H=n=n.Y/U/]?9'N 0.nf0.nf>?<NTJg n#o=|# no=|0.2.HAHЁй##&0.HH@3&>%N 9&&gB. /9&?<*?<NP. /9&?<*?<NP#&&0y&"|#./< 0y&"|&/0/9&?<*?<N>?<NTJg>?<NTN^NuNV.'aBW?9'NTaFJ@ga`a0BW?9'N T>'aN^Nu2/SA o 0/"o QQNu2/SA o 0/"o""QQNu2/4/SASo o"o 0/BBBBBB8:<>俉YYYYHDHEHFHG23E3F3GQPQNu2/SA o"o 0/4XXX6HB4 "QQNu2/SA"o $o&o0/ o&,.(*ȃʃ QQNu> t ~   `8_ @ a@ ?8p~@x@?p@ ? x   ?    p  #NN/9Nu#NM/9Nu#NA/9NuNV3e&By&By&3&N N^NuNV3{&By&By&3&N N^NuNV## .мZ#3d&By&3 & n 3&N n 0&# #"#%,#$,N^NuNV3|&By&By&3&N n 0" n0%, n0%.N^NuNV# 3r&3&By&3&N #$,N^NuNV3  3&By&3&3&N 09"N^NuNV3  3&By&3&3&N 09"N^NuNV3  3&By&3&3&N 09"N^NuNV3  3z&By&3&3&N N^Nu#&"<psNBNuNV3&J0.|Hм D-@=|` nH2n&J2RRn nm.&N>B@09&rN^NuNV#&J##&,##&R##&r##&##'###&> aF3&r&pN^NuNV>a*pN^NuNV3&R# &>4N N^NuNV>MN  n0&t n 0&v n0&x n0&zB@09&rN^Nu    -UCpwpw32@7UP[3][This program works ONLY|in low rez.][ OK ].      &   ,(@         $  -.  s ..  s MAG21 BAT s  MAG21 C s &MAG21 PRG s <1bcp68 mag21.c mag21.i c068 mag21.i mag21.1 mag21.2 mag21.3 -f rm mag21.i c168 mag21.1 mag21.2 mag21.s rm mag21.1 rm mag21.2 as68 -l -u mag21.s rm mag21.s link68 mag21.68k=apstart,mag21,osbind,libf,vdibind,aesbind rm mag21.o relmod mag21 rm mag21.68k wait /* MAG21.C - Dave's magplot program, cut 21. */ /* w/ color animation code. */ /* Copyright 1986 ANTIC Publishing */ /* Standard include files: */ /* GEM VDI related variable defines */ int contrl[12], intin[256], ptsin[256], intout[256], ptsout[256]; int handle; /* from v_opnvwk */ int i; /* for init loop & general array index */ int dummy; /* for graf_handle call */ int key_state; /* Lfor keyboard call */ int set_color; /* for color setting call */ int xcircle,ycircle,rcircle; /* for v_circle */ int style; /* for fill interior style call */ int color_flag; /* true if color, false if mono */ int numcolors; /* # of colors (2,4,16):mono,med,low res */ int xscreen,yscreen; /* from v_opnvwk */ int old_color,temp_color; /* for ext. bios _setColor call */ /* magplot vars */ int debug; /* nz = all sortsa debugging messages */ int gridstyle; /* nz = grid plotting technique */ int degreeinc,clipit; /* global vars */ int currcolor; /* current color */ int vbl_count; /* for color rotate */ double k2; /* force constant calc var */ double linelength; /* vector length */ double xmax,ymax; /* GEM: how big screen is */ double ymenu; /* menu size, for offset etc. */ int allneg; /* point entry routine: nz if all pts negative */ int currpt; /* array index of point being worked on */ int degree; /* polar coord of starting place on point */ int xcoord[10],ycoord[10],charge[10]; /* stored points */ int numpoints; /* # of points */ int xgridpt,ygridpt; /* for grid-style display */ double theta,radius,x1,y1; /* starting point calcs */ int newline; /* flag for "new line starting"; 0 = yes */ int doanotherseg; /* flag for exiting while segment loop */ int mouse_poll; /* polling flag for input */ int xposmin,xposmax,xnegmin,xnegmax; /* polling for input */ double xcurrent,ycurrent; /* saved old loc for calcs */ double xvectorsum,yvectorsum; /* internal to summer */ double number; /* scaling divider */ double xsqr,ysqr; /* internal to summer */ double xdistance,ydistance; /* internal to summer */ double force,forcetemp; /* internal to summer */ double ivtemp; /* debugging stuff */ double ivlength,ivline; /* after summer */ double xdelta,ydelta; /* for clipping radius check */ int height,width; /* from graf_handle */ int xtext,ytext; /* for v_gtext output */ int ctext; /* temp */ int xmouse,ymouse,smouse; /* for vq_mouse */ int black,white; /* vars to make colors "float" for vdi/palette*/ char outstring[80]; /* string output for numbers.. */ extern double sin(),cos(),sqrt(); /* trig functions */ main() { appl_init(); /* Gem voodoo */ gemopen(); /* open a workstation for VDI's kicks, init it */ /* We need a black background and colored foreground. GEM uses hardcoded */ /* color register #'s for a given color, which trips us up. */ /* We tweak color registers */ /* so black=0, white=1, other colors=2,3,4.. */ /* This handles text, etc, so we don't trip over the gem-hardware */ /* palette mapping problem later. */ do { key_state = 0; temp_color=xbios(7,0,0x100); /* set "black" (reg 0) to black color */ temp_color=xbios(7,3,0x777); /* set 3: "white".. this matters */ temp_color=xbios(7,15,0x777); /* set 15: "white".. matters to */ black=0; /* vdi constants for colors.. reassigned to my scheme. */ white=1; cls(); /* clear screen to white */ initglobals(); /* Setup variables */ inputpoints(); /* Input points to work on */ setupcolors(); /* setup colors to plot with */ plotit(); /* Plot the screen */ /* Done. Loop, waiting for any shift-alt-ctrl key, so we don't fall out */ /* of the program and erase the plot. If in color mode, rotate colors. */ vbl_count=0; /* init vbl_count for # of vblanks / change */ while (key_state == 0) { vq_key_s(handle, &key_state) ; /* get state into keystate */ /* color rotation stuff */ if (color_flag && gridstyle == 0) /* color modes & non grid*/ rotate(); } /* loop until key_state is nonzero */ } while (key_state != 4); /* until CTL key */ /* With apologies to the author, the do {} while (key_state != 4) loop was included by the ANTIC Editorial Staff because they felt it increased the program's fun quotient. */ v_clsvwk(handle); /* shut down GEM */ appl_exit(); /* Exit, stage left */ } /* end main() */ /* * setupcolors() * */ /* Configures the colors we want to plot with if color mode. */ /* These can be configured however you like. Format, in hex: */ /* 0xnrgb. n=null. r=red value 0-7, g=green, b=blue */ /* Register 0 always stays black as the background. */ setupcolors() { /* setup plotting colors */ if (numcolors==4) /* medium res 4-color mode */ /* just use rgb if 3 colors */ { temp_color=xbios(7,1,0x700); /* set "red" */ temp_color=xbios(7,2,0x070); /* set "green" */ temp_color=xbios(7,3,0x007); /* set "blue" */ } if (numcolors==16) /* Add some variations if 16 colors */ { temp_color=xbios(7,1,0x007); /* set "red" */ temp_color=xbios(7,2,0x004); /* set "dim red" */ temp_color=xbios(7,3,0x070); /* set "green" */ temp_color=xbios(7,4,0x040); /* set "dim green" */ temp_color=xbios(7,5,0x700); /* set "blue" */ temp_color=xbios(7,6,0x400); /* set "dim blue" */ temp_color=xbios(7,7,0x707); /* set "red/blue" */ temp_color=xbios(7,8,0x404); /* set "dim red/blue" */ temp_color=xbios(7,9,0x770); /* set "red/green" */ temp_color=xbios(7,10,0x440); /* set "dim red/green" */ temp_color=xbios(7,11,0x777); /* set "white" */ temp_color=xbios(7,12,0x444); /* set "dim white" */ temp_color=xbios(7,13,0x044); /* set "dim green/blue" */ temp_color=xbios(7,14,0x040); /* set "dim green" */ temp_color=xbios(7,15,0x440); /* set "dim red/green" */ } } /* * rotate * */ /* Rotates colors if in color mode to animate the lines flowing from */ /* + to - points. We do this by rotating colors in color registers, */ /* which gives onscreen animation, every few vblanks. */ /* Note: at present, Megamax does not support extended bios call names. */ /* Hence, I include a commented-out version of the call, with the proper */ /* name, then make the "generic" xbios call to do the color change. */ /* xbios (7,color register #, color value) is equiv. to set_Color; */ /* if color value is negative, only returns value, doesn't alter. */ rotate() { /* vsync(); */ /* wait until vblank to slow it */ xbios(37); /* vsync */ /* count # of vblanks. Once per vblank ismuch too fast; tweak this to */ /* your individual taste. */ vbl_count=vbl_count+1; if (vbl_count == 8) /* every 8 vblanks */ {  if (numcolors == 4) /* medium res: rotate 4 */ { /* rotation: First, sample #3 w/o changing it, then write into 1, */ /* getting old 1's value back, put that in 2, then do 3. */ temp_color=xbios(7,3,-1); /* get 3 */ temp_color=xbios(7,1,temp_color); /* 3->1 */ temp_color=xbios(7,2,temp_color); /* 1->2 */ temp_color=xbios(7,3,temp_color); /* 2->3 */ } if (numcolors == 16) { /* A more complex rotation. GEM colors do NOT match the palette */ /* numbers, so I can either do a table lookup, or do it directly. */ /* Either way, we have to rotate in GEM order since we drew the lines */ /* in GEM order. */ /* I did it directly. */ /* GEM COLOR # HARDWARE COLOR NUNBER (PALETTE) */ /* 0 0 */ /* 1 15 */ /* 2 1 */ /* 3 2 */ /* 4 4 */ /* 5 6 */ /* 6 3 */ /* 7 5 */ /* 8 7 */ /* 9 8 */ /* 10 9 */ /* 11 10 */ /* 12 12 */ /* 8 13 14 */ /* 14 11 */ /* 15 13 */ temp_color=xbios(7,13,-1); /* sample 13; no change */ temp_color=xbios(7,15,temp_color); /* 13->15 */ temp_color=xbios(7,1,temp_color);/* 15->1 */ temp_color=xbios(7,2,temp_color);/* 1->2 */ temp_color=xbios(7,4,temp_color);/* 2->4 */ temp_color=xbios(7,6,temp_color);/* 4->6 */ temp_color=xbios(7,3,temp_color);/* 6->3 */ temp_color=xbios(7,5,temp_color);/* 3->5 */ temp_color=xbios(7,7,temp_color);/* 5->7 */ temp_color=xbios(7,8,temp_color);/* 7->8 */ temp_color=xbios(7,9,temp_color);/* 8->9 */ temp_color=xbios(7,10,temp_color);/* 9->10 */ temp_color=xbios(7,12,temp_color);/* 10->12 */ temp_color=xbios(7,14,temp_color);/* 12->14 */ temp_color=xbios(7,11,temp_color);/* 14->11 */ temp_color=xbios(7,13,temp_color); /* 11->13 */ } vbl_count=0; /* reset vbl counter */ } /* end if vbl_count == rotate it.. */ } /* End rotate() */ /* * input points * */ /* Inputs points using mouse. Stores points into xcoord[],ycoord[], with a */ /* charge of charge[]. Uses VDI only, so no AES (resource, etc) is required */ inputpoints() { clearpn(); /* clear off menu bar */ numpoints=0; /* total # of points */ i=0; /* pointer for coord arrays */ key_state= 0; /* flag to exit input loop */ while (key_state == 0) { /* id=1 */ if (numcolors != 16) /* anything but low res */ { v_gtext(handle,1*width,(height)-2,"Exit: (SHIFT=pt-pt; ALT=grid)."); v_gtext(handle,50*width,(height)-2," Select a Point or Exit."); } else /* velly few characters across.. */ v_gtext(handle,1*width,(height)-2,"Select pt or (SHIFT=pt-pt; ALT=grid).");  /* update shift key state for possible exit */ vq_key_s(handle,&key_state); /* Update mouse button state */ vq_mouse(handle,&smouse,&xmouse,&ymouse); smouse=(smouse&1); /* mask to mouse button bit */ if (smouse==1) /* mouse down event */ /* id=2 */ { /* Erase the "select a point" stuff */ clearpn(); /* Store circle's co-ords there */ xcircle=xmouse; ycircle=ymouse; /* okay coord system: scrn-scrn */ rcircle=radius; /* Put up the pos/neg menu */ plotpn(); /* Now get a plus/minus in from him. */ mouse_poll=1; /* Wait for him to get into <20 y,*/ /* and in pos or neg field ranges with */ /* mouse down. */ while(mouse_poll==1) /* id=3 */ { vq_mouse(handle,&smouse,&xmouse,&ymouse); /* look for mouse down and Y <20 */ if (ymouse<20 && smouse == 1) /* go looking */ { /*id=4*/ if (xmouse>xposmin && xmouse < xposmax) { /*id=5*/ ctext=1; /* charge = 1 */ mouse_poll=0; /* terminate loop */ } /*endid=5*/ if (xmouse>xnegmin && xmouse < xnegmax) { /*id=5a*/ ctext = -1; /* charge = -1 */ mouse_poll=0; /* terminate loop */ } /*endid=5a*/ } /* end if smouse && y < 20 loop */ /*endid=4*/ } /* end mouse_poll ==1 loop (polling mouse x,y for +/- */ /*endid=3*/ /* e.g., while waiting for plus/minus decision */ clearpn(); /* clear pos/neg area */ /* Set circle styling; draw circle */ set_color=vsf_color(handle,white); /* fill color */ set_color=vsf_interior(handle,0); /* fill Z interior: 0 = hollow */ v_circle(handle,xcircle,ycircle,rcircle); /* circle */ /* store into array */ xcoord[i]=xcircle; /* y coord is upside down */ ycoord[i]=(ymax-ycircle)+20; /* scrn-> array */ charge[i]=ctext; i=i+1; /* bump array pointer */ numpoints=numpoints+1; /* totl # points to plot */ /* plot a +/- in circle there. Offset differently if color.*/ if (!color_flag) /* mono */ { xtext=(xcircle-4); /* offset to mid-circle */ ytext=(ycircle+6); /* Him too. */ } else { xtext=(xcircle-4); /* offset to mid-circle */ ytext=(ycircle+2); /* Him too. */ } /* ctext is charge set above */ if(ctext>0) { /*id=3a*/ v_gtext(handle,xtext,ytext,"+"); } /*endid=3a*/ else { /*id=3a*/ v_gtext(handle,xtext,ytext,"-"); } /*endid=3a*/ /* Wait for mouse to come up, since otherwise, it will just plot a circle */ /* on the pos/neg box we just picked.. */ waitmup(); } /* terminate while mouse_poll==1 mouse down paragraph id=2 */  } /* terminate while key_state==0: he pressed SHIFT id=1 */ /* Erase the "select a point" stuff */ clearpn(); numpoints=numpoints-1; /* because we were one over.. */ /* if no points picked, ANY key_state exits program */ if (numpoints < 0) key_state = 4; /* Now determine if grid mode or pt-pt mode. ALT=grid mode. */ if (key_state==8) /* ALT pressed */ gridstyle=1; /* grid mode */ else gridstyle=0; /* point-point mode */ /* Wait for mouse to come up, to prevent instant program stop on line start. */ waitmup(); slow(); /* debounce */ } /* * Plot the field lines * */ /* This is the procedure that controls plotting the lines. */ plotit() { v_hide_c(handle); /* Select which plotting style: grid or point-point */ /* grid style: go across screen, horiz & vertical, draw 1 line. */ if (gridstyle==1) { linelength=3; /* Go X across; for each X, do a Y from bottom to top of screen. */ for(xgridpt=0;xgridpt= 2.0 && ivlength <= 5.0) (set_color=vsl_color(handle,2); /* g */ $if(ivlength > 5.0) (set_color=vsl_color(handle,3); /* r */ &} /* 16 color mode: */ if(numcolors==16) %{ $if(ivlength < 0.2) (set_color=vsl_color(handle,1); /* 1 */ $if(ivlength > 0.2 && ivlength <= 0.4) (set_color=vsl_color(handle,2); /* 2 */ $if(ivlength > 0.4 && ivlength <= 0.6) (set_color=vsl_color(handle,3); /* 3 */ $if(ivlength > 0.6 && ivlength <= 0.8) (set_color=vsl_color(han vdle,4); /* 4 */ $if(ivlength > 1.0 && ivlength <= 1.2) (set_color=vsl_color(handle,5); /* 5 */ $if(ivlength > 1.2 && ivlength <= 1.4) (set_color=vsl_color(handle,6); /* 6 */ $if(ivlength > 1.4 && ivlength <= 1.8) (set_color=vsl_color(handle,7); /* 7 */ $if(ivlength > 1.8 && ivlength <= 2.2) (set_color=vsl_color(handle,8); /* 8 */ $if(ivlength > 2.2 && ivlength <= 3.0) (set_color=vsl_color(handle,9); /* 9 */ $if(ivlength > 3.0 && ivlength <= 4.0) (set_color=vsl_color(handle,10); /* 10 */ $if(ivlength > 4.0 && ivlength <= 5.0) (set_color=vsl_color(handle,11); /* 11 */ $if(ivlength > 5.0 && ivlength <= 6.0) (set_color=vsl_color(handle,12); /* 12 */ $if(ivlength > 6.0 && ivlength <= 8.0) (set_color=vsl_color(handle,13); /* 13 */ $if(ivlength > 8.0 && ivlength <= 15.0) (set_color=vsl_color(handle,14); /* 14 */ $if(ivlength > 15.0) (set_color=vsl_color(handle,15); /* 15 */ (} /* check screen bounds, try to draw. */ if (x1 < xmax && x1 > 1 && y1 < ymax && y1 > 1) { ptsin[0]=xcurrent; /* old x,y */ ptsin[1]=((ymax-ycurrent)+20); ptsin[2]=x1; /* calced x */ ptsin[3]=((ymax-y1)+20); /* calced y */ v_pline(handle,2,ptsin); /* draw line */ /* sprintf(outstring,"ivl=%f",ivlength); v_gtext(handle,width*1,height*6,outstring); */  } /* terminate bounds check if */ } /* terminate y loop */ /* If shift key held down when a new line starts, abort. */ vq_key_s(handle, &key_state) ; /* get state into keystate */ if(key_state != 0) goto quit; } /* terminate x loop */ } /* terminate if gridmode loop */ else { /* non-grid mode (normal) /* *( */ /* point-point plotting style. Draw continuous lines. */ /* Select which point to begin plotting from. */ for(currpt=0;currpt<=numpoints;currpt=currpt+1) { /* can't plot negative points, since they attract the line. */ if(charge[currpt]<=0) continue; /* bypass the rest of the loop (reloop) */ /* Calc starting point for this line. Use polar coordinates in a */ /* radius around each positive point. */ /* Generate initial x1,y1. from radius and theta (standard polar stuff) */ for(degree=1;degree<360;degree=degree+degreeinc) { theta = degree; theta = theta * (3.14159/180); x1 = (radius * cos(theta) ); y1 = (radius * sin(theta) ); x1 = ( x1 + xcoord[currpt] ); y1 = ( y1 + ycoord[currpt] ); newline = 0; /* flag: do "begin line" draw if 0. */ doanotherseg = 1; /* flag for following while loop..do another seg..*/ currcolor=1; /* init color at line's start */ set_color=vsl_color(handle,currcolor); /* init color */ /* *=/ /* Next segment entry point */ /* Comes here to draw the next segment of a line. */ while(doanotherseg == 1) { /* *< */ /* terminate line test.. if fails, a new line begins.*/ /* if big screen, use 2500 x 2500 field. If little, screensize only. */ if (clipit == 0) /* little screen size check.. */ { if (x1 > xmax || y1 > ymax || x1 <1 || y1 < 1)  { doanotherseg=0; /* no new seg.. */ } } else /* clipit != 0 */ /* big screen size check */ { if (x1 > 2500 || y1 > 2500 || x1 < -2500 || y1 < -2500) doanotherseg=0; /* no new seg.. */ } /* *< */ /* Test if we are so close to a negative point we are ping-ponging */ /* around it. If so, clip off this line. */ for(i=0;i<=numpoints;i=i+1) { if (charge[i]<0) { xdelta = (xcoord[i]-x1); if (xdelta < 0) xdelta = (-1*xdelta); /* abs(xdelta) */ ydelta = (ycoord[i]-y1); if (ydelta < 0) ydelta = (-1*ydelta); /* abs(ydelta) */ if (xdelta < radius && ydelta < radius) doanotherseg = 0; /* terminate line */ } /* end if-charge is neg */ } /* end for loop */ /* Line drawing. Do we need to begin a line? (Since we essentially do */ /* drawto's later.) */ if (newline == 0) /* begin a new line? */ { /* don't attempt to start a new line if we're offscreen.. while in */ /* bigscreen mode. */ if (x1 < xmax && x1 > 1 && y1 < ymax && y1 > 1) { ptsin[0]=x1; ptsin[1]=(( ymax - y1)+20); ptsin[2]=ptsin[0]+1; /* just do a 2 dot draw */ ptsin[3]=ptsin[1]; xcurrent=x1+1; /* reset these for drawto below */ ycurrent=y1; v_pline(handle,2,ptsin); /* Actual line draw */ newline=1; /* flag: we have started a new line. */ } } /* Line draw. If out-of-bounds, implies big screen mode, and still */ /* in bigscreen range. If so, just set newline flag, so we begin draw */ /* where it re-enters bounds. Otherwise, do a "drawto" from where we were, */ /* using the old ptsin array values. */ if (x1 < xmax && y1 < ymax && x1 > 1 && y1 > 1 ) { /* old "currents", recorded from x1,y1, above, for "draw from" info. */ ptsin[0]=xcurrent; /* old x */ ptsin[1]=((ymax-ycurrent)+20); /* old y, offset for menu */ ptsin[2]=x1; /* new x */ ptsin[3]=((ymax-y1)+20); /* new y */ v_pline(handle,2,ptsin); /* draw line */ /* bump color if in living color. If we go over maximum color #, */ /* wrap to color #1. Leave color 0 alone; that's background. */ /* Hence, it' 1-2-3-1-2-3 or 1-2-3..14-15-1-2-3- .. */ if (color_flag) { currcolor=currcolor+1; if (currcolor==numcolors) /* if past limit */ currcolor=1; /* reset color */ set_color=vsl_color(handle,currcolor); /* vdi color */ } } else /* we went offscreen in big screen mode */ { newline=0; /* specify a new starting place of line if */ /* it ever re-enters the atmosphere */ } /* We calc new xy after first pass through loop so it starts at + circle */ /* boundary.. */ calcnewxy(); /* calc new x1,y1 (see below..complex)*/ } /* end "while doanotherseg = 1" loop */ /* If shift key held down when a new line starts, abort. */ vq_key_s(handle, &key_state) ; /* get state into keystate */ if(key_state != 0) goto quit; /* Indenting was too much for screen (all these nested loops) so had to */ /* do it this way. */ } /* end "next degree" loop */ } /* end "next point" loop */ } /* end point-point or grid if-else */ /* entry for early abort. Yes, I used a GOTO, so what? */ quit: v_show_c(handle,0); slow(); /* debounce */ if (key_state != 4) v_gtext(handle,width*0,height*1, "End MagPlot. CTL exits; SHIFT restarts."); } /* end of plot-it */ /* * charge summer * */R /* Summer of charges at this x,y */ /* At the current x,y, calculate the vector force on us for each point. */ /* Sum up the vectors as an X and Y displacement, then setup a line draw */ /* of a fixed segment length with the same X and Y slope. Note we cannot */ /* actually calculate the slope because if delta Y is 0, we divide by 0 */ /* (delta X / delta Y) */ calcnewxy() { xcurrent=x1; /* save x,ycurrent as copy of current x1,y1. */ ycurrent=y1; xvectorsum = 0; /* initialize totals */ yvectorsum = 0; number = 64; /* quick scaler */ /* Loop through all points: */ for(i=0;i<=numpoints;i++) { /* Calculate force with formula: */ /* constant * charge1 * charge2 / (distance squared) */ /* I used X*X instead of X squared to try to optimize speed. */ /* xsqr = (current point x - old x) ^ 2 ; same with ysqr. */ xsqr=( (xcoord[i]-xcurrent) * (xcoord[i]-xcurrent) ); ysqr=( (ycoord[i]-ycurrent) * (ycoord[i]-ycurrent) ); /* FORCE = (ABS(CHARGE(I) * K2) / (XSQR+YSQR)) * NUMBER*/ forcetemp = charge[i]; if (forcetemp<0) /* ABS(forcetemp) */ forcetemp = (-1*forcetemp); force=( (forcetemp*k2) / (xsqr+ysqr) ); xdistance = ( -1* (xcurrent-xcoord[i]) * force ); ydistance = ( -1* (ycurrent-ycoord[i]) * force ); /* Reverse "polarity" based on charge */ if (charge[i]>0) { xdistance = (-1*xdistance); ydistance = (-1*ydistance); } /* Okay, now add these vectors to our running totals */ xvectorsum = xdistance+xvectorsum; /* Add to vector */ yvectorsum = ydistance+yvectorsum; /* summation */ } /* end for loop of summer */ /* Now scale the vectors */ xvectorsum = ( xvectorsum / number ); yvectorsum = ( yvectorsum / number ); /* Now scale a linelength-sized line to the slope indicated by the vector */ /* sums. */ xsqr = (xvectorsum * xvectorsum); ysqr = (yvectorsum * yvectorsum); ivtemp = (xsqr + ysqr); /* determine total length of calced vector */ ivlength = sqrt ( xsqr + ysqr); /* via pythagoras */ ivline = ( ivlength / linelength ); /* now adjust it to our fixed len */ /* Make new x1,y1 out of old x1,y1 (xcurrent,ycurrent) and adjustment. */ x1 = (xcurrent + (xvectorsum / ivline) ); /* and add adjusted to x,y */ y1 = (ycurrent + (yvectorsum / ivline) ); } /* * init globals * */ /* Initglobals: just sets up controlling vars. */ /* You can have a lot of fun playing with these. */ initglobals() { /* starting and ending radius of point. Please leave be. */ radius=10; /* radius around each starting point */ /* How "strong" magnetism is. Play your favorite diety! */ k2=10000; /* force constant */ /* How far to draw a given segment. Lower makes for finer, slower plot. */ linelength=5; /* length plotted of each calced vector */ /* How many degrees to increment polar coords of starting point. Less */ /* gives more lines (denser plot) but takes more time. */ degreeinc=5; /* amt of inc in circle at starting point */ /* Boolean. If 0, clips plot to screen size. If nonzero, lets plot go */ /* offscreen, which slows down plot but makes it more "complete". */ clipit=0; /* 0 = screen size only, 1 = full screen */ /* Boolean. Turns debugging messages on in earlier revisions. */ debug=0; /* my debug messages off */ } /* **** plot pos/neg * */ /* Plot POS NEG up on menu bar..2 spaces between. */ /* Note that this is more-or-less resolution independent, and where */ /* the POS and NEG plot determines where we look for a mouse-down to */ /* set the + / - charge. */ plotpn() { /* Calc text position as 3/4 of full screen.. */ xtext=(0.75 * xmax); /* absolute starting screen co-ords */ /* Calc all fields as offsets * character width from this.. */ v_gtext(handle,xtext,(height)-2,"POS NEG"); /*  01234567890 */ /* Set xposmin,max, xnegmin,xnegmax. These are used when inputting */ /* points to make this work in all modes. */ xposmin=xtext-width; /* start of POS area */ xposmax=xtext+(3*width); /* end of POS area */ xnegmin=xtext+(5*width); /* start of NEG area */ xnegmax=xtext+(8*width); /* end of NEG area */ } /* **** Clear pos/neg * */ /* Clear pos/neg field, including pesky line fragments */ /* Clears entire menu bar, to be frank (or bill.. Ack!) */ clearpn() { set_color=vsf_color(handle,0); /* 0 = white, 1 = black */ ptsin[0] = 0; /* upper left x */ ptsin[1] = 0; /* Upper left Y */ ptsin[2] = xmax; /* lower right x */ ptsin[3] = ymenu+1; /* lower right y. Needs +1. */ vr_recfl(handle,ptsin); /* do fill.. */ } /* **** cls * */ /* Clears screen to black screen. Since GEM has funny ideas about */ /* what register Black color is, force it to "white", which we have */ /* tweaked in hardware to black, using a constant. */ cls() { v_hide_c(handle); /* hide cursor, otherwise foulup happens */ set_color=vsf_color(handle,black); ptsin[0] = 0; /* upper right x */ ptsin[1] = ymenu-1; /* Leave menu bar area alone.. up right y */ ptsin[2] = xmax; /* lower right x */ ptsin[3] = yscreen; /* true y max..lower right y */ vr_recfl(handle,ptsin); /* do "fill" */ v_show_c(handle,0); /* show cursor, 0=regardless of nesting */ } /* **** gemopen * */ /* This is just the standard workstation stuff. Note, however, we save */ /* the screen size and some color info for later use. */ gemopen() { handle=graf_handle(&width,&height,&dummy,&dummy); /* more magic */ for(i=0; i<10; i++) { intin[i]=1; /* set them all to 1 */ } intin[10]=2; /* except for the last one (use "RC coord sys" flag) */ v_opnvwk(intin, &handle, intout); graf_mouse(0,0); /* make a mouse look like an arrow */ numcolors=intout[13]; /* 2,4, or 16, depending on resolution. */ color_flag = (numcolors == 4 || numcolors == 16); /* true/false */ /* Determine size of menu bar for fill & offset operations */ if (numcolors==2) ymenu=20; if (numcolors==4) ymenu=10; if (numcolors==16) ymenu=10; xmax=intout[0]; /* set color / mono width */ xscreen=intout[0]; ymax=intout[1]; /* set color / mono heighth */ yscreen=intout[1]; /* all Y outputs are done as (ymax-y) because screen is inverted.. */ ymax=ymax-20; /* (bypass menu bar - 1st 20 scan lines )*/ /* workstation open. */ } /* * waitmup * */ waitmup() /* Waits for mouse button up. */ { while (smouse == 1) /* 0 = means button up */ { vq_mouse(handle,&smouse,&xmouse,&ymouse); smouse=(smouse&1); /* mask to mouse bit; fall into loop test. */ } } /* * slow * */ /* slow is just a delay loop. Counts up to 32000. */ /* It is used to debounce the mouse (and the user); otherwise you can't */ /* get off the mouse fast enough to start a plot without aborting it. */ slow() { int slowcnt; /* local */ slowcnt = 0; for (slowcnt=1;slowcnt<32000;slowcnt++); } /* end of code */ `+~ *O.|1p*m - ЭЭм// ??<JNA NJ/<NA"/0<NBNuNVN*aBy9>Bg?<NJX35>w?<?<NJX35>w?<?<NJX35By:633aaaa^aRBy5`(.9?95N(TJy5g Jy:~faJy9g y9fL>5N' N+N^NuNV y:,fN>?<?<NJX35>p?<?<NJX35>?<?<NJX35 y:,f>?<?<NJX35>?<?<NJX35>p?<?<NJX35>@?<?<NJX35>?<?<NJX35>?<?<NJX35>?<?<NJX35>?<?<NJX35>p?< ?<NJX35>@?< ?<NJX35>w?< ?<NJX35>D?< ?<NJX35>D?< ?<NJX35>@?<?<NJX35>@?<?<NJX35N^NuNV>%NJ095R@35 y5fJ y:,fn>?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35 y:,f>?< ?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?<?<NJX35>5?< ?<NJX35>5?< ?<NJX35>5?< ?<NJX35>5?<?<NJX35>5?< ?<NJX35>5?< ?<NJX35By5N^NuNVaBy:By5By9`" y:,gL.,?9:"UW?9;h?95N'6\.,?9:"UW09;h2??95N'6\`".-?9:"UW?9;h?95N'6\.9?95N(T.3/<3/<;\?95N( 09;\|3;\ y;\fVa335335/9:N X35a3:`.3/<3/<;\?95N( y3l^ y;\fT093y:o093y:l35By:093y:o093y:l35By: y:gja>3?95N)DT35BW?95N)~T35>5?95?95?95N&\0y5:05pH/N ,X/095H/N ,X//9:8N!dP/NzP/N X?0y5:00y5505095R@3509:R@3:Jy5f095Y@3:2095\@3:4`095Y@3:2095T@3:4Jy5o".-:?9:4?9:2?95N'6\` .-5N' y:~fpH/N ,X#5By:<`VBy:x`09:?95N)T35/<B/9:NPm./<C/9:NPn>?95N)T35/<C/9:NPo>?95N)T35 y:,f/<>/9:NPl>?95N)T35/<>/9:NPo./?95N)T35/?95N)T35/<@/9:NPo./<@/9:NPn>?95N)T35/<A/9:NPo./?95N)T35/?95N)T35/<33A/9:NPo./?95N)T35/?95N)T35/ ?95N)T35/<B/9:NPo./<C/9:NPn> ?95N)T35/<C/9:NPo./<C/9:NPn> ?95N)T35/<C/9:NPo./<C/9:NPn> ?95N)T35/<C/9:NPo./<D/9:NPn> ?95N)T35/<D/9:NPo./<D/9:NPn>?95N)T35/<D/9:NPo>?95N)T35/9:./95NPl/95pH/N ,X/NPl/9:8/95NPl/95pH/N ,X/NPl/9:N X35pH/N ,X//9:/9:8N!dP/NzP/N X35/95N X35pH/N ,X//95/9:8N!dP/NzP/N X35.5?<?95N(LX09:xT@3:x09:xy:m.9?95N(TJy9f09::?95N)T35`&Jy:fx/9:./95NPnV/9:8/95NPn@/95pH/N ,X/NPn /95pH/N ,X/NPoBy7`/950< H/N ,X/NPmf/950< H/N ,X/NPmD/950</9:>B@H/N ,X/NPo$/9:>pH/N ,X/N!DP#:>/950y5"|:00H/N ,X/N!dP#:z/9:zB@H/N ,X/NPo$/9:zpH/N ,X/N!DP#:z/9:/9:>NPl/9:/9:zNPlBy7095R@35095y:oJy9f./9:./95NPl/95pH/N ,X/NPl/9:8/95NPl/95pH/N ,X/NPl/95N X35pH/N ,X//95/9:8N!dP/NzP/N X35095R@35355/95pH/N ,X/NzP#:#5:.5?<?95N(LX39/9:./95NPlb/9:8/95NPlJ/95pH/N ,X/NPl(/95pH/N ,X/NPl/9:N X35pH/N ,X//9:/9:8N!dP/NzP/N X35/95N X35pH/N ,X//95/9:8N!dP/NzP/N X35.5?<?95N(LXJy5g>09:R@3:09:y:,f3:>:?95N)T35`By9a y7g.9?95N(TJy9f<095y;35 yh5mf09;fR@3;f09;fy:o(BW?95N)Tab y9g$.->?9:"09;hB@??95N'6\N^NuNV#5:#5:B@H/N ,X#:B@H/N ,X#:p@H/N ,X#:By5`/9:0y5"|:00H/N ,X/N!dP//9:0y5"|:00H/N ,X/N!dP/N!DP#:/9:0y5"|:00H/N ,X/N!dP//9:0y5"|:00H/N ,X/N!dP/N!DP#:0y5"|500H/N ,X#5/95B@H/N ,X/NPo$/95pH/N ,X/N!DP#5/9:/9:NzP//9;^/95N!DP/NP#:/9:0y5"|:00H/N ,X//9:N!dP/pH/N ,X/N!DP/N!DP#:$/9:0y5"|:00H/N ,X//9:N!dP/pH/N ,X/N!DP/N!DP#:(0y55JPoH/9:$pH/N ,X/N!DP#:$/9:(pH/N ,X/N!DP#:(/9:/9:$NzP#:/9:/9:(NzP#:Ry5095y:o$/9:/9:NP#:/9:/9:NP#:/9:/9:N!DP#:/9:/9:N!DP#:/9:/9:NzP#;/9:/9:NzP.N #:/95/9:NP#:/9:/9:/9:NP/NzP#5/9:/9:/9:NP/NzP#5N^NuNVp H/N ,X#:0<'H/N ,X#;^pH/N ,X#53;By:By:N^NuNV/9:./<@N!DP/N X3:2.-f?9:"UW?9:2?95N'6\09:2y;h3:09;hy:23:09;hy:23:09;h@y:23:N^NuNVBW?95N)DT35By5By5/9:.N X35/97pH/N ,X/NzP/N X35.5?95N)TN^NuNV>5N'>:6?95N)DT35By5pH/N ,X//97N!dP/N X35/9:.N X353:5.5?95N)TBW?95N)TN^NuNV.5/<5/<:"/<;hN+ 35By5`0y510Ry5 y 5m31.3/<5/<1N'PBWBgN+\T33:, y:,g y:,gB@`p35 y:,fpH/N ,X#7 y:,fp H/N ,X#7 y:,fp H/N ,X#7093H/N ,X#:.33:093H/N ,X#:833:pH/N ,X//9:8N!dP#:8N^NuNV`4.3/<3/<;\?95N( 09;\|3;\ y;\gN^NuNVBn=|`Rn n}mN^Nu#1tNN/91tNu#1tNM/91tNu#1tNA/91tNuNVH..,. N# LN^NuNVH..,. N$LN^NuNVH..,. N$ LN^NuNVH..N! LN^NuNVH..N! LN^NuNVH..N# LN^NuNVHJl| .D-@`BFJfB`^~` .-@R .f` .-@S. g .-@޼@ JFg .JLN^NuNVH .м<JgJFlB`V .:|oJEg <` <`0..μ|`RFJFm`SFJFnJEg D. JLN^NuNVH..,. N%B LN^NuNVH..,. N# LN^Nu?<`$?<`?<`<bTJNuBgJk<8cH~$<cP<c <L~TNu,<>.N%B<<XDxB묈<΄,<CN%B,.N#$(< .BJk<FD<c~䯾o$`<D<c~DDl`z,k^g>k^g2k8<d,&B<ރeNuRid~S<Nu.NuJNu:ڼ.gNugRghEDvi^E]HE:BB8HD&HC؃HF&؃BDHDHGHFHEބj ޼gNuSiex@ބއdRgNu~NujJ<Nu!T3~SUU ???xBJg.jD<¼bHF<܆[Jj ܼdRNumc68343 floating point firmware (c) copyright 1981 by motorola inc.NV3 53 5By5By535By53 :3:By:3:3:N*&N^NuNV3e:By:By:3:N*&N^NuNV3 53 5Bn nH|2n12RRnJ@f3:3:Sn3:3:N*&N^NuNV3{:By:By:3:N*&N^NuNV#1|#1 .мZ#13d:By:3 : n 3:N*& n 0:#11|#31#71#51N^NuNV# 13:3 :By:3:N*&#51N^NuNV3:By:By:3:N*& n 03N^NuNV3|:By:By:3:N*& n 03 n07 n07N^NuNV# 13r:3:By:3:N*&#51N^NuNV3 13:By:3:3:N*&093N^NuNV3 13:By:3:3:N*&093N^NuNV3 13z:By:3:3:N*&N^NuNV3 13:By:3:3:N*&093N^Nu#:1x"<1xpsNBNuNV3:B0.|Hм+~-@=|` nH2n:B2RRn nm.:N>B@09:jN^NuNV#:B5#95#:J5#:j5#:5#;b5#5:> aF3:j:pN^NuNV>a*pN^NuNV>MN*< n0:l n 0:n n0:p n0:rB@09:jN^NuNV3:J# :>NN* #include #include /*G/ /* DEFINES "*/ /*G/ #define MIDI (3) #define CONSOLE (2) #define window_kind (NAME|CLOSER) #define MAXSONG (37000L) #define Supexec(a) xbios(38,a) /*Delete this if using Megamax Compiler */ /*G/ /* GLOBAL VARIABLES */ /*G/ int wi_handle, ap_id, phys_handle, ph, intin[128],work_in[11],h,w,hh,ww; int contrl[12],ptsin[128],intout[128],ptsout[128],work_out[60]; int xdesk, ydesk, wdesk, hdesk, dum, clip[4]; int tempo, flag1, res; long songlength; char *notebuffer, selection[13], path[64] = "A:\*.SNG"; /*G/ /* ALERT BOXES */ /*G/ V char alert1[] = "[3][This program does not run|in low-resolution mode.][ OK ]"; char alert2[] = "[2][ Would you like to ][RECORD|PLAYBACK|QUIT]"; char alert3[] = "[3][The file extension| must be '.SNG' ][ OK ]"; char alert4[] = "[2][ Would you like to ][LISTEN| SAVE | ERASE ]"; char alert5[] = "[3][Not enough memory][ OK ]"; char alert6[] = "[3][You have filled the | allocated space. ][ OK ]"; char alert7[] = "[2][ A file with that name |already exists. Overwrite?][ YES | NO ]"; /*G/ /*G/ /* E*/ /* PROGRAM CONTROL */ /* E*/ /*G/ /*G/ main() { Init(); /*open GEM workstation*/ res = Getrez(); if(res == 0) /*must be medium or hi- res*/ form_alert(1,alert1); else { Openwindow(); /*open the window*/ Titlescreen(); /*put up the credits*/ Loop(); /*start the show*/ } Mfree(notebuffer); /*free the space allocated*/ wind_close(wi_handle); /*close the window*/ wind_delete(wi_handle); v_clsvwk(ph); /*close GEM workstation*/ appl_exit(); } /*G/ ,/*Main program control loop*/ Loop() { int end; do { switch(form_alert(0,alert2)) /*options*/ { case 1: /*"RECORD"*/ Rcordinstructions(); In_loop(); /*MIDI and time input*/ Save_options(); Clearscreen(); Titlescreen(); end = 0; break; case 2: /*"PLAYBACK"*/ Selectsong(); /*Choose a song*/ if(flag1 == 1) /*1 = "OK", 0 = "cancel"*/ #{ (Playbackinstructions(); (Loadsong(path); (Playsong(); #} Clearscreen(); Titlescreen(); end = 0; break; case 3: /*"QUIT"*/ end = 1; break; } } while(end == 0); /*Keep looping until "Quit" is chosen*/ } /*G/ /*after recording you can listen, save, or erase*/ Save_options() { int end; do { switch(form_alert(0,alert4)) { case 1: Playsong(); /*"Listen"*/ end = 0; break; case 2: Selectsong(); /*"Save"*/ if(flag1 == 1) /*1 = "OK", 0 = "cancel"*/ (end = Savesong(path); else (end = 0; break; case 3: /*"ERASE"*/ end = 1; break; } } while(end == 0); } /*G/ /*monitor the keyboard for ESC, F1, or F2* f/ Checkkeyboard()  { long keycode; int end; if(Bconstat(CONSOLE) != 0) { keycode = Bconin(CONSOLE); keycode >>= 16; /*we just want high word*/ if(keycode == 0X3BL) &/*F1*/ { tempo++; if (tempo == 500) /*check bouandaries*/ tempo = 499; return(0); } else if(keycode == 0X3CL) !/*F2*/ { tempo--; if(tempo == 0) /*check bouandaries*/ tempo = 1; return(0); } else if(keycode == 0X01L) /*escape*/ { end = 1; Allnotesoff(); /*shut off synth*/ return(1); } else return(0); } else return(0); /*no keys pressed*/ } /*G/ 1/*open GEM workstation*/ Init() { long temp; int i; ap_id = appl_init(); ph = graf_handle(&h,&w,&hh,&ww); for(i = 1; i < 10; work_in[i++] = 1); work_in[0] = ap_id; work_in[10] = 2; v_opnvwk(work_in, &ph, work_out);  temp = Malloc(MAXSONG); /*allocate enough space for song*/ if(temp == 0) form_alert(1,alert5); /*warn if not enough space*/ else notebuffer = (char *)temp; } /*G/ /*G/ /* E*/ /* INCOMING MIDI DATA ("RECORD") */ /* E*/ /*G/ /*G/ 6/*main input loop*/ In_loop() { long In_timer(), time; register long basetime, i, notelength; /*register variables are faster*/ register char midi[50]; int a,b,c; notebuffer[56] = 36; /*set the base tempo*/ notebuffer[64] = 255; /*start with a short rest*/ notebuffer[65] = 20; i = 66L; /*offset to first MIDI value*/ while(Bconstat(MIDI) != 0) /*flush MIDI buffer*/ Bconin(MIDI); basetime = In_timer(); /*get a starting value*/ do { for(c = 0; Bconstat(MIDI) != 0; c++) /*get MIDI input*/ midi[c] = (char)Bconin(MIDI); if(midi[0] == 0) /*get rid of leading 0 caused by turning on*/ a = 1; /*a CZ-101 after "RECORD" is selected*/ else a = 0; /*G/ /* E*/ /* NOTE '*/ /* E*/ /* The following section parses the incoming MIDI data to make it */ /* compatible with the graphics routines in MIDIMagic. If you wish to */ /* eliminate this code you will have to replace it with a loop that */ /* will read the contents of the array "midi[]" into the notebuffer */ /* array, or else put the results of the Bconin(MIDI) calls directly */ /* into the notebuffer. 0*/ /* E*/ /*G/ /*now parse the incoming MIDI data and put it in a form the graphics routines in MIDIMagic can read */ while(a < c ) { if(midi[a] < 0 || midi[a] > 127) /*status byte*/ { for(b = 0; b < 3; b++) /*take it as is*/ { if(a < c) "*(notebuffer+i++)=midi[a++]; else /*make sure there are enough #'s*/ "*(notebuffer+i++)=(char)Bconin(MIDI); } } else /*if running status add $90 before first byte*/ { *(notebuffer + i++) = -112; for(b = 0; b < 2; b++) !{ #if(a < c) %*(notebuffer+i++)=midi[a++]; #else %*(notebuffer+i++)=(char)Bconin(MIDI); !} } } /*G/ /* End of parsing section */ /*G/ time = In_timer(); /*wait for next event and get time*/ if(time != 0) { *(notebuffer + i++) = 255;  notelength = (time - basetime)/4; /*note length*/ if(notelength == 0) i--; else { while(notelength > 127) /*no negative values*/ { $*(notebuffer + i++) = 127; $*(notebuffer + i++) = 255; $notelength -= 127; } *(notebuffer + i++) = (char)notelength; basetime = time; /*reset for next note*/ } if(i >= MAXSONG-10)/*check to make sure piece is not*/ { /*too long for allocated space*/ form_alert(1,alert6); time = 0; } } } while(time != 0); /*until ESC is pressed or buffer is full*/ *(notebuffer + i++) = 255; /*end of song marker*/ *(notebuffer + i++) = 255; *(notebuffer + i++) = 255; songlength = i; /*return the song length*/ } /*G/ /*Waits for MIDI event or ESC, returns 200Hz clock if MIDI*/ long In_timer() {  long (*pter)(), Getclick(), time; int end; pter = Getclick; /*set up the function pointer*/ for(end = 0; Bconstat(MIDI) == 0 && !end; )/*check for MIDI or*/ end = Checkkeyboard(); /*keyboard input*/ if(end) /*if user has pressed ESC return a 0 to the*/ return(0L); /*calling function*/ else /*otherwise return the value in the 200 Hz timer*/ { time = Supexec((*pter)); /*get the time in supervisor mode*/ return(time); } } /*G/ /*reads the 200Hz click from supervisor mode*/ long Getclick()  { /*Location $04BA give the current 200Hz click value*/ static long time = 0X4BA; /*It is in protected space so it must be*/ */*accessed in supervisor mode*/ return(*((long *)time)); } /*G/ /*G/ /* E*/ /* DISK I/O !*/ /* E*/ /*G/ /* d* 0) /*see if file exists*/ { if(form_alert(2,alert7) == 2) /*overwrite?*/ { Fclose(fhandle); /*don't overwrite*/ return(0); } } fhandle = Fcreate(song,0); Fwrite(fhandle,songlength,notebuffer); Fclose(fhandle); return(1); } /*G/ /*Use fsel_input to get the name of a file to load or save*/ Selectsong() { int exbutton, accomplished; do { /*keep trying until a correct choice is made or*/ 3/*"cancel" is chosen*/ accomplished = 1; Getpath(); /*find out the current path*/ selection[0] = '\0'; /*no default selection*/ fsel_input(path,selection,&exbutton); vs_clip(ph,0,clip); /*reset clipping rectangle*/ Clearscreen(); if(exbutton) /* OK was chosen*/ { Setpath(); Dsetpath(path); if(Checkend() == 0) /*file ext must be .SNG*/ accomplished = 0; flag1 = 1; } else /*cancel was chosen*/ flag1 = 0; } while(accomplished == 0); } /*G/ /*G/ /* E*/ /* OUTGOING MIDI DATA ("PLAYBACK") */ /* E*/ /*G/ /*G/ /*Pl ay the song in notebuffer at the tempo set in notebuffer[56]*/ Playsong() { static int m = 0, ps; unsigned int pi, end; char midistring[200]; register long n; while(Bconstat(CONSOLE) != 0) /*flush keyboard buffer*/ Bconin(CONSOLE); n = 64; /*first byte of song data*/ tempo = notebuffer[56];  for(end = 0; end == 0; ) { while (!end && *(notebuffer + n) != -1)/*get MIDI bytes*/ midistring[m++] = *(notebuffer + (n++)); if (m != 0) !/*send them*/ Midiws(m-1, midistring); if (!end && *(notebuffer + (++n)) != -1) /*check for EOF FFFF*/ { for(ps = 0; !end && ps < *(notebuffer + n); ps++) { end = Checkkeyboard(); Out_timer();/*wait one standard interval*/ m = 0; } } else "/*if EOF ($FF FF)*/ { end = 1; Allnotesoff(); /*shut off synth*/ } m = 0; n++; } } /*G/ /*shuts off all possible notes to avoid "hung notes"*/ Allnotesoff() { char notesoff[3]; int ai, aj; notesoff[0] = 0X80; "/*note off*/ notesoff[2] = 0; "/*velocity 0 */ for(ai = 0; ai < 128; ai++) /*loop through all the notes*/ { notesoff[1] = ai; Midiws(2,notesoff); /*send the string*/ for(aj = 0; aj < 500; aj++); /*wait just a bit*/ } } /*G/ %/*timing loop for Playsong routine*/ /*This can be replaced with a more sophisticated interrupt timer*/ /*I do not recommend using the GEM evnt_timer for this purpose*/ Out_timer() { int ti, th; for(ti = 0; ti < tempo; ti++) for(th = 0; th < 75; th++); } /*G/ /*G/ /* E*/ /* SCREEN DISPLAYS */ /* E*/ /*G/ /*G/ 8/*Open a window*/ Openwindow() { static char winame[] = " * A Simple Sequencer * "; wind_get(0,WF_WORKXYWH,&xdesk,&ydesk,&wdesk,&hdesk); wi_handle = wind_create(window_kind,xdesk,ydesk,wdesk,hdesk); wind_set(wi_handle,WF_NAME,winame,0,0); wind_open(wi_handle,xdesk,ydesk,wdesk,hdesk); clip[0] = xdesk; clip[1] = ydesk; clip[2] = wdesk; clip[3] = hdesk; } /*G/ 5/*Clear the screen*/ Clearscreen() { static int screen[] = {4,22,636,198}; if(res == 2) /*for monochrome monitors*/ { screen[1] = 40; screen[3] = 394; } graf_mouse(M_OFF,0X0L); vsf_interior(ph,2); vsf_style(ph,8); vsf_color(ph,0); v_bar(ph,screen); graf_mouse(M_ON,0X0L); } /*G/ "/*displays the title and instructions*/ Titlescreen() { graf_mouse(M_OFF,0X0L); vst_height(ph,6,&dum,&dum,&dum,&dum); vst_effects(ph,4); v_gtext(ph,200,30*res,"START, the ST Quarterly, Presents:"); vst_height(ph,20,&dum,&dum,&dum,&dum); 1 vst_effects(ph,32); v_gtext(ph,220,60*res,"A SIMPLE SEQUENCER"); vst_height(ph,9,&dum,&dum,&dum,&dum); vst_effects(ph,0); v_gtext(ph,230,155*res,"by Tom Jeffries"); vst_height(ph,6,&dum,&dum,&dum,&dum); v_gtext(ph,200,170*res,"Copyright 1986 by Tom Jeffries"); v_gtext(ph,240,178*res,"All rights reserved"); v_gtext(ph,150,186*res,"This program is not in the public domain."); v_gtext(ph,100,194*res,"Unathorized copying or publication is expressly forbidden"); graf_mouse(M_ON,0X0L); } /*G/ '/*instructions for record screen*/ Rcordinstructions() { graf_mouse(M_OFF,0X0L); Clearscreen(); vst_height(ph,20,&dum,&dum,&dum,&dum); vst_effects(ph,16); v_gtext(ph,250,60*res,"RECORDING"); vst_height(ph,6,&dum,&dum,&dum,&dum); vst_effects(ph,0); v_gtext(ph,160,140*res,"Recording will start when you begin playing."); v_gtext(ph,210,160*res,"Press ESC to stop recording."); graf_mouse(M_ON,0X0L); } /*G/ %/*instructions for playback screen*/ Playbackinstructions() { graf_mouse(M_OFF,0X0L); Clearscreen(); v_gtext(ph,150,140*res,"Press F1 to slow down, press F2 to speed up."); v_gtext(ph,260,160*res,"Press ESC to stop."); graf_mouse(M_ON,0X0L); } /*G/ /*G/ ` *O.|*m - ЭЭм// ??<JNA NJ/<NA"/0<NBNuNVa>N`3$,Jy$,f.?<NT` a a Na@.#V?<INT>$XN>>$XNX>$VNNN^NuNV.BgNT`Ra aFada `a Bn`Jah y$.fa .bataa 2a Bn`=|``|g|g|gJngN^NuNV.NBgNT`8aBn`@a y$.f.baN=@`Bn`=|``|g°|gư|gJngN^NuNV>?<NpTJg>?<NpT-@r .-@ ;fRy! y!f3!B@`J`D ?<NpT>?<NpTJfa&.Bn`& N2n/?<?<NpXH _@Rn>?<NpTJfJ.f=|`Bn` N2nJ(m N2n (o\Bn`L0.Ȱnl F#V"N4nRnR`" F#V/?<?<NpXH _RRn nm`h F#VRBn`L0.Ȱnl F#V"N4nRnR`" F#V/?<?<NpXH _RRn nm0.Ȱnma-@Jg F#VR/< ./NP*JfS`@`" F#VR F#VRn H"F#VR..~m.?<NTBJf F#VR F#VR F#VR##ZJLN^NuNV-|Bn`a=@>?<NpTJfJngJngB``.?<&N`T-@ .N^NuNV y( N^NuNV>N=@0.|Ab,=|` |b2n"|,4nRn nmN^NuNV.ba=@0nb (Sf$0nb (Nf0nb (Gg.?<NTB@``pN^NuNV.baT=@`SnJng"0n"|b0H@|\g .:f |b2nB.!&/<ba,XN^NuNVBn`Rn nHRJf0.N^NuNV`R nJf n H"nR RJ@fN^NuNVBW/.?<=N\=@.#V/<?.?<?NP>?<>NTN^NuNV>/.?<=N\=@o,.?<NT|f>?<>NTB@`DBW/.?<?<>NTpN^NuNV=|aB9!&.U/<!&/<bN2P.!Bg?9$VNXaJng,a .b?<;NTaJ@fBn3$.`By$.JngN^NuNV4H`>?<NpT>?<NpTJf~@ y#V(8H3!Bn`` N2y4"G#VQ4RRy4Jnf G#V fJy4g.4?94SW?< N`XJnfLR G#V g$2?9$Z?9$b?9$`?<NP3$XBWBg/<6?<?9$XN >$2?9$Z?9$b?9$`?9$XNP3$`!3$b! 3$Z!"3$2!$N^NuNV y$,f3(h3lB?<NT>?9$VNnT>?9$VNTBW?9$VN4T.f?9$VNTB?<NTN^NuNVB?<NT.$&/<$&/<$&/<$&?<?9$VN>?9$VNT.n09$,??<?9$VN\.$&/<$&/<$&/<$&?<?9$VN> ?9$VNT.09$,?9$VNT.K09$,N^Nu#$6"<psNBNuNVH?BCB..,. f# <`hlDRCJlDRCn8fzB`0l :HGH`xe`Jge`|fD# D`# JLN^NuNV3#x0.|Hм-@=|` nH2n#x2RRn nm.$(N>B@09#N^NuNV##x!##8!##! ##!#$N!#$\!#!$(> aF3#$4pN^NuNV>a*pN^NuNV3## $N>4N2N^NuNV#$N# $R>ZN2 n0#B@09#N^NuNV>MN2 n0# n 0# n0# n0#B@09#N^NuNV3## $N>NN2N^NuNV3#3 #3 #3#3#>dN2N^NuNV3#3 #3 #3#3#>eN2N^NuNV3#>fN2N^NuNV3#>gN2N^NuNV3#3 #>hN2 n 0# n0# n0# n0#B@09#N^NuNV3#3 #3 #3#3#3#>iN2N^Nu    -A:*.SNG9[3][This program does not run|in low-resolution mode.][ OK ][2][ Would you like to ][RECORD|PLAYBACK|QUIT][3][The file extension| must be '.SNG' ][ OK ][2][ Would you like to ][LISTEN| SAVE | ERASE ][3][Not enough memory][ OK ][3][You have filled the | allocated space. ][ OK ][2][ A file with that name |already exists. Overwrite?][ YES | NO ]A:*.SNG * A Simple Sequencer * |START, the ST Quarterly, Presents:A SIMPLE SEQUENCERby Tom JeffriesCopyright 1986 by Tom JeffriesAll rights reservedThis program is not in the public domain.Unathorized copying or publication is expressly forbiddenRECORDINGRecording will start when you begin playing.Press ESC to stop recording.Press F1 to slow down, press F2 to speed up.Press ESC to stop..&  * FH"  6   *R :   & " r     "      BN                      &f  $          `E`99`66`I`//`B9E@`6>I4`8`>`88`44`//`8>46`@B`E`9`>`I`99`L`66`IJ`L//`B9JD`6>E4`8`>`B`D88`44`(`//`44` 6`>>`B88`;`>=`86;4/(-`4`7`9`;`99`494`7;7`9`;`99`;77`94==`@`==`@&`7-B`=-`6`9`;`=`;;`99`;;`==`;;`99`=6&;-=`9/`BB`6`9`?`E`;`BB`E9=6;/G`B,`4`D`8`G;`@`G`?DD`E`8@;4,GDI`*`1`4`6`9`=`EB`BB` BB`=I=`E`EB=61*94I`E`*`1`4`6`9`=`EE`E=B`E`I=`61*94D`6`G`=BE?`B`E`I`D?@`D`GEDB@/`K`G`B`6IE`K6`I`L`GD`EG`9`LIE`DI`;`GG`I6/I`B9GEL`B`P`S`ILK`N`U`Q`NSPKL`P`QW`S`G`UPLN` Q`SP`QS`NB;GWZ` (`/`4`8`X`Z;`_;;`8(XSPB`4/E`J`=`L`>`I`J=;LG`>G4`>`ID`G`BEI` 46`>=`B`DE`IGBB`E /`9`?`6=D` (`/B/`B`8`>`?D9 @`8B>8`>`B`@G`J`N`6BN-`/4`89`(=`>B`JG@`4B94`=9`@=`@`E`I` P`=PQ`Q;`E=@I9-4E`L` J`=`LL`>`JI`=L;G`G>4`I>`G`D`EI`=`6`D>4E`@`IGB`E ?`9`/`@B6=B`B-`3`/B`=`9?D`,`-;`=4`B3B`D @`B;;`@4*`4`9`,=`;6=9/`=`9`4*@`/(`9@//`;`9`@`=8`9((`4`2`8@;46`9`*`/(6=`92;`9`;8`;`9=>`8(`;B`*>@`>`@=`>@`D`=B@-`(G`DE`D`EB`DE`&`I`GBE2`-L`IJ`I`G`JIJ`LN`&/`2Q`NJG >`;`6`B`J`G` Q(`JD`/G4`J`B6>;N` L`NE`DI`(J-`4N`L L`N4`IJ`LI`JEE`B`J`-I I`@`BJ >`G`EI@=`E`>G =42`E6`9`*`=`;`99`;8`9;`>`=(`B`86*>;2@`>`@=`>@`BD`(G`-`D=@E`D`GEB`E`DI`&`2`L`IB-EJ`I`JG`IJ`L&N`JG/`Q`2N 6`>`;`J`G`B` QN`GG`JJ`NN` /6NB>;JG>`;`6`J`G`B`P`N`PP` 6B>>`;L`NGPJJ`LL`I`JL 6`B`G`IG8`G`A`BI`=`9`86G>E`A@`IB`E9/`?`9`=@BD`(`//`?98`>`B`D @`B8>>`@8`N`J`G`B`7NB8-`(4`/=`>9`B`JG@`4B94`=9`=`@@`E`I` P`8PQ`E;`QB`=@94-L`IJ`=`LL`>`I`=L;JG`>GIB>`4`G`D`I`=`6`E`D>IG4D`E/`?`9`6=B`DB3`-`?B`=`/9D`,`;`-=B34`B`D @`B;;`@4,*`9`4`=`;49=*/`=`9`4@`"/9@(`/`;`9`=@` 8`9((`/4`8((`0`<`C`7`@;4A`CC`0<)`(75`0`CA<`9`@`5>`<95`+`;`0)@<`-`+;9`54`>/`2`-5`7`49<<`4`0`-`2/75-+`2`0;`7`4>`<<`9`A`>;72+<4`(`C`<`7`0`9A <&`<`)`(742`0-`E`CH`&J`HA`G`<2-)E +`2` 5`7`C`AA`CC`JH`GO`A752+M`OO`L`MO E`CA`J`LHC`F`H`L`JEAM`E`A`LFCA@`HEC`MO`H` M`OO` ML`O5O`LD`CP`O N`PP`L`NPI`H P`D@?`=`?LQ`IP@`E`I`L`N`P`QINLK`=E@G`D`?`;`9`N`K?;PGD=`B`E`I`K`L`NKIB=9G`ED`@`;`8`6`8D@;G9`=`I`LB`E`4`6N`B9E=I9`=`I`B`NE`=943`9`=`II`BB`EE`1`3=B9N`E9`@`Q`E`II`1I/`NE@96`9`=`QQ`?`B`E`*QEE`N`B9N=6?/E/`4`L`N`8`}I`L;`L`N8G`I8`I`4LD`4`G/G`I/`B`D(`D`B8;4/G@`D1`D`@4`?`D8`=`88`4=4`=`?11`((`1;`84=/`4`L`N`8`I`;L;`L`N8G`I8`I`4LD`4`G/G`I/`B`(D(`D`8B;4/G@`D1`D`4`@?`D8`=`88`4==`4`1?1`*`;`814(=9`1`;;`4`=`6`99`66`@`4?`1@1`@`==`;61*@?91`4`D`8`;`88`44`D@`11`-`?`8;14=@=`?4`?`6`@`?9`==`9D`9`66`B`D44`D`@9.`-6DB=4@`4`8`I`=`1`=8.@46`:`F`II`F@`F`I4`D`:61F:`=`@L`D:4D`6`==`I`@`LL`IF`LI`:`=6FD@P`I@`D`I`N`P=`P`ID:N@B`F`L`N`P:`P`=FBNL@`D`I`N`P:=`P`NID@B`N`PF` L`P`N==`Q`FBPL@`E`I`L`N`P`=QNLI@EK`G`D`?`;`9`N`?PKD;G=`B`E`I`K`L`B9NKIE=G`D`@`;`8`=`LQ`@8D;G@`E`S`I`L`EE`U`QUSQ`;`=I@E?`P`D`QQ`LK`G`DPD`?P`?`Q?;I`9`DGK=`B`E`N`BPB`==`=B98`G`EI;`@`D`@L`@`;N;`8D6`@;9`J`G>`LL`E`B`>>`9N`9`J4`NL6B>98`I`=`J`D`@`E=I=`8I`8`J2`B`D@=846`;`>`G`;6I;`6`1`@`6>;2B4`9`=`E`99`4G4`/`>`=941@5`D`8`ED;`E`8D`8`5E5`-`=`8;5>/I`D1`E`6`I9`B`6E6`11`-,`;`691=/`@`B4`8`B`4/@4`@`B/` *`,8;4/E`@1`4`6`9`;`=`EE`?EE`*=61;94D`E/`3`8`;`?`DD`G`K`GG`GB`?83KD;//`3`9`;`?`E`G`!GG` ?3;9/GE@`B/`4`X`Z`8`U`X;`X`Z8S`U8`U`4X4`P`S/S`/`UN`P(`NS8@;4/L`1`P`4`K`LP8`=`88`44`I`K11` ((`G`=81I4/`4`L`N`8`I`L;`NG8G`8`II`4D`4`G/G`I/`B`(D(`BGD`8;4/@`D1`D`4`?`@D8`=`88`4=4`=`?11`((`;`184=4`/`=`8`44`;@`;`88`B`==`44`@;@`;`=I`@BD`@`DD`IN`@@`NP`DX`PP`XPX`S`XSL`X`ALXX`S`/4(4`(`8@;/|XS4(JS6AQ"wu6홱hˍ@[m%)H-C xiNw>.rGG]8:~6G>wޯVxhBhFP0" EQ0*Pq(@Id%-hD2AC )2eÕ)LecxX`Wuҁ)JU* @]00fq돏\{3ęr$ɑnt29sLgM^ENTRTAIN4S %F%J@V@L@X@J@V@T@H@X@L@E@Q@T@H@S@G@Q@E@O@C@G@S@C@O@J@>@@@L@>@J@<@H@@@L@9@E@<@H@;@G@E@9@7@C@;@G@C@7@>@2@@@4@>@2@0@<@4@@@9@-@-@-@0@<@/@;@/@/@9@-@-@9@-@-@;@/@,@8@9@-@+@7@,@8@+@7@+@@O@J@G@C@@+@C@O@J@G@7@;@>@7@;@?@>@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@H@7@@@7@+@@@<@:@H@:@<@H@@@5@)@)@5@9@<@9@<@4@(@H@H@L@T@(@4@7@<@J@M@V@T@H@L@<@7@W@K@N@M@J@V@+@O@L@X@N@W@K@L@L@T@H@O@X@+@4@7@<@J@M@V@T@H@L@4@<@7@L@O@X@M@J@V@+@J@S@G@+@O@J@L@X@5@7@;@J@M@V@G@S@;@7@5@M@J@V@0@L@H@T@0@4@<@7@4@<@7@4@7@<@4@<@7@7@;@>@T@H@L@;@7@?@>@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@H@@@+@:@<@@@H@:@<@H@@@5@)@)@5@9@<@<@9@4@(@(@4@H@3@'@H@E@H@Q@O@H@C@Q@E@3@'@H@2@&@H@N@B@C@O@E@B@&@N@2@H@Q@2@6@9@H@<@T@Q@E@2@6@<@9@L@X@T@H@2@J@V@2@X@L@9@6@<@T@H@J@V@6@<@9@E@T@H@Q@7@M@J@;@V@Q@E@;@7@7@+@+@7@9@-@-@9@/@;@>@/@/@M@J@V@?@>@;@/@0@@@?@H@0@@@4@<@7@4@<@7@@@H@+@H@7@7@@@7@+@7@@@<@:@H@:@<@H@@@5@)@)@5@9@<@9@<@4@(@H@H@L@T@(@4@7@<@J@M@V@T@H@L@<@7@W@N@K@M@J@V@O@+@L@X@N@W@K@L@+@L@T@H@O@X@4@<@7@J@M@V@T@H@L@4@<@7@O@X@L@M@J@V@+@J@S@G@+@J@O@L@X@5@J@7@M@;@V@G@S@;@7@5@J@M@V@0@L@H@T@0@4@7@<@4@<@7@7@<@@@T@H@T@H@<@@@7@L@J@V@T@H@0@<@L@X@J@V@H@T@X@L@0@<@<@7@J@@@V@H@T@@@<@7@L@X@J@V@:@.@T@H@:@.@X@L@7@<@J@@@V@T@H@@@<@7@H@T@J@V@9@L@-@X@T@H@H@T@-@9@X@L@9@<@J@V@A@T@H@L@X@A@<@9@J@V@,@8@T@H@,@8@X@L@8@<@J@V@A@H@T@8@A@<@H@T@J@V@7@+@O@X@L@T@H@L@L@H@T@+@O@X@7@7@<@@@J@M@V@T@H@L@@@<@7@L@X@O@M@J@V@+@J@S@G@+@O@L@X@J@J@7@;@M@V@G@S@;@7@M@J@V@0@<@7@O@T@H@0@<@7@7@+@+@7@9@-@-@9@/@;@>@/@/@O@T@H@?@>@;@/@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@7@H@@@7@+@7@:@<@@@H@:@<@7@H@@@5@)@)@5@9@<@<@9@4@(@H@L@T@H@(@4@7@<@J@M@V@T@H@L@<@7@K@W@N@M@J@V@+@O@L@X@N@W@K@L@L@T@H@O@X@+@4@<@7@M@J@V@T@H@L@4@<@7@O@L@X@M@J@V@+@J@S@G@+@O@J@L@X@5@7@J@;@M@V@G@S@;@7@5@M@J@V@0@L@T@H@0@4@7@<@4@<@7@4@7@<@4@<@7@7@;@>@H@T@L@;@7@?@>@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@7@H@@@7@+@<@:@@@7@H@7@:@<@H@@@5@)@)@5@9@<@<@9@4@(@(@4@H@'@3@H@E@Q@H@H@O@C@Q@E@3@H@'@2@&@N@H@C@O@B@E@B@&@N@2@H@Q@2@6@9@<@H@T@Q@E@2@6@<@9@L@X@T@H@2@J@V@2@X@L@9@6@<@T@H@J@V@6@<@9@E@T@Q@H@7@;@J@M@V@Q@E@;@7@+@7@+@7@9@-@-@9@/@;@/@/@>@M@J@V@?@>@;@/@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@H@7@@@7@+@@@:@<@H@:@<@H@@@5@)@)@5@9@<@<@9@4@(@H@H@L@T@(@4@<@7@J@M@V@T@H@L@<@7@W@K@N@M@J@V@+@O@L@X@N@W@K@L@+@L@H@T@O@X@4@<@7@J@M@V@T@H@L@4@<@7@L@O@X@M@J@V@+@J@S@G@+@O@J@L@X@5@7@J@;@V@M@G@S@;@7@5@J@M@V@0@L@H@T@0@4@<@7@4@<@7@@@7@<@T@H@H@T@<@@@7@L@J@V@T@H@0@<@L@X@J@V@T@H@X@L@0@<@<@7@@@J@V@T@H@@@<@7@L@X@J@V@.@:@T@H@.@:@X@L@7@<@@@J@V@T@H@<@@@7@H@T@J@V@9@L@-@X@T@H@H@T@-@9@X@L@9@<@J@V@A@T@H@L@X@A@<@9@J@V@,@8@H@T@,@8@X@L@8@<@J@V@A@T@H@8@A@<@H@T@J@V@+@7@L@O@X@T@H@L@L@H@T@+@O@X@7@7@<@@@J@M@V@H@T@L@@@<@7@L@X@O@M@J@V@+@J@S@G@+@O@X@L@J@7@J@;@M@V@G@S@;@7@M@J@V@0@<@L@7@H@T@0@<@7@7@+@L@+@7@0@$@H@@@L@H@0@$@T@J@M@A@@@H@L@N@K@A@M@J@B@O@0@L@$@C@B@N@K@0@C@O@$@L@7@<@@@L@E@Q@L@<@@@7@O@L@C@Q@E@+@L@@@L@H@+@C@O@7@<@J@M@A@H@L@J@<@@@7@J@N@A@M@B@0@L@O@C@N@B@J@0@L@C@O@7@<@E@@@L@Q@L@<@@@7@L@O@Q@C@E@+@L@+@L@O@C@7@<@@@H@L@<@@@7@C@H@E@)@C@G@)@E@9@<@A@H@G@A@<@9@J@H@5@L@J@J@5@L@<@8@A@H@J@8@A@<@J@H@4@C@J@L@4@C@7@<@@@M@L@@@<@7@O@M@+@O@Q@O@+@Q@7@<@@@L@O@<@@@7@M@L@0@L@O@C@M@0@L@O@C@7@<@@@E@L@Q@L@<@@@7@O@L@C@Q@E@+@L@@@L@H@+@C@@@O@7@<@@@J@M@A@H@L@<@@@7@K@N@A@M@J@B@0@L@C@O@B@N@K@O@C@L@7@<@@@E@L@0@Q@L@<@@@7@O@L@C@Q@E@4@O@O@C@L@4@3@Q@O@R@Q@3@2@O@J@S@O@R@J@S@O@S@J@2@7@;@>@S@>@;@7@S@N@H@O@J@2@Q@N@2@S@H@9@<@N@H@>@Q@>@9@<@J@N@H@7@O@;@G@>@J@;@7@>@5@)@)@4@(@5@@@L@(@4@H@O@G@2@&@J@M@A@@@H@L@K@N@A@M@J@B@&@2@0@$@O@L@C@B@N@K@L@0@$@C@O@7@<@E@@@L@Q@L@<@@@7@C@O@L@Q@E@+@L@@@L@H@+@@@O@C@@@7@<@J@M@A@H@L@<@@@7@K@N@B@A@M@J@O@0@L@C@B@N@K@0@L@C@O@7@<@E@@@L@Q@L@<@@@7@L@O@C@Q@E@+@L@L@+@O@C@7@<@@@H@L@@@<@7@C@H@E@)@C@G@E@)@9@<@H@A@G@A@9@<@J@H@5@L@J@J@5@L@<@8@A@H@J@8@A@<@J@H@4@H@J@4@<@7@@@<@@@7@0@C@0@H@<@:@@@C@:@@@<@C@5@9@<@H@A@C@A@<@9@5@5@<@9@E@A@H@H@A@E@<@9@5@?@<@6@9@E@?@6@<@9@H@?@6@9@<@H@E@E@?@6@9@<@H@<@7@@@C@E@H@C@<@@@7@7@<@@@L@H@O@@@7@<@L@7@@@<@L@7@<@@@O@7@@@<@H@L@C@@@<@7@H@2@<@E@B@C@B@2@E@<@9@2@H@B@2@9@B@H@7@;@L@A@A@A@J@;@7@L@7@;@@@H@;@7@A@J@0@<@0@<@7@+@+@7@4@(@L@X@T@@@H@(@4@2@&@Y@M@V@T@X@L@Z@N@W@M@V@Y@&@2@0@$@O@X@[@N@W@Z@0@$@X@O@7@<@@@[@X@]@Q@X@<@@@7@O@[@X@Q@]@+@X@X@L@T@O@[@+@@@<@7@Y@M@V@T@L@X@@@<@7@Z@W@N@M@V@Y@0@O@[@X@N@W@Z@0@O@X@[@@@7@X@<@]@Q@X@<@@@7@O@X@[@Q@]@+@X@X@O@[@+@7@<@@@T@X@<@@@7@O@T@)@Q@O@S@)@Q@9@<@T@A@S@A@<@9@V@T@5@X@V@V@X@5@<@8@T@A@V@8@A@<@V@T@4@O@V@X@X@X@4@O@<@7@@@Y@X@@@<@7@[@Y@+@]@[@[@+@]@@@7@<@X@[@<@@@7@Y@X@0@[@O@X@Y@0@O@X@[@7@<@@@X@]@Q@X@@@<@7@X@[@O@Q@]@+@X@X@L@T@+@X@O@X@[@7@<@@@Y@M@V@T@X@L@<@@@7@Z@W@N@M@V@Y@0@O@[@X@N@Z@W@0@O@X@X@7@<@@@]@[@Q@X@<@@@7@[@O@X@Q@]@4@[@[@O@X@4@3@]@[@^@]@3@2@[@V@_@^@_@[@V@[@V@_@2@7@;@>@_@V@[@>@;@7@Z@_@T@2@]@2@_@T@Z@Z@9@<@T@>@]@>@<@9@V@T@Z@7@;@S@[@>@V@>@;@7@5@)@)@5@4@(@@@L@H@S@[@(@4@2@&@J@M@A@L@@@H@K@N@A@B@M@J@&@2@$@0@O@L@C@B@N@K@0@O@C@$@L@7@<@@@E@L@Q@L@<@@@7@O@L@C@Q@E@+@L@@@L@H@+@C@O@@@7@@@<@J@M@A@H@L@<@@@7@K@N@A@M@J@B@0@O@L@C@B@N@K@0@O@C@L@7@<@@@E@L@Q@L@<@@@7@O@L@Q@C@E@+@L@L@+@C@O@<@7@@@H@<@@@7@C@L@H@E@)@C@G@E@)@9@<@H@A@G@A@<@9@J@H@5@L@J@J@L@5@<@8@A@H@J@8@A@<@J@H@4@H@J@4@7@<@@@@@<@7@0@C@0@H@:@<@@@B@C@:@<@@@C@B@5@9@<@H@C@A@A@9@<@5@5@9@E@<@H@A@A@9@<@5@H@E@?@<@6@9@?@6@9@<@E@H@?@6@9@H@<@E@?@6@<@9@E@H@7@<@@@C@E@<@@@7@H@C@<@@@L@7@H@@@<@7@O@L@@@7@<@@@<@7@L@O@@@7@<@H@L@@@<@7@C@H@2@E@<@C@B@B@2@E@<@2@9@H@B@2@9@B@H@7@;@L@A@A@;@7@J@A@L@;@7@;@7@@@H@A@J@0@<@0@<@+@7@+@7@0@$@0@$@>@@@H@?@>@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@7@H@@@+@7@@@7@<@:@H@:@7@<@H@@@5@)@)@5@9@<@<@9@4@(@H@H@L@T@(@4@<@7@J@M@V@T@H@L@<@7@K@W@N@M@J@V@+@L@O@X@N@W@K@L@H@L@T@O@X@+@4@7@<@J@M@V@T@H@L@4@<@7@L@O@X@M@J@V@+@J@S@G@+@O@J@L@X@5@7@J@;@M@V@G@S@;@7@5@M@J@V@0@H@L@T@0@4@7@<@4@<@7@4@7@<@4@<@7@7@;@>@T@H@L@;@7@?@>@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@7@H@@@+@7@7@@@:@<@H@:@<@7@H@@@5@)@)@5@9@<@<@9@4@(@(@4@H@3@'@E@H@Q@H@H@O@C@Q@E@H@3@'@H@2@&@N@C@O@B@E@B@N@&@2@Q@H@2@6@9@H@<@T@Q@E@2@6@<@9@L@X@T@H@2@J@V@2@X@L@6@9@<@H@T@J@V@6@<@9@E@Q@T@H@7@;@J@M@V@Q@E@;@7@7@+@+@7@9@-@-@-@-@9@/@;@>@/@/@M@J@V@?@>@;@/@0@@@?@H@0@@@4@7@<@4@<@7@@@H@+@H@7@@@+@7@<@:@@@7@H@:@<@7@H@@@5@)@)@5@9@<@<@9@4@(@H@H@L@T@(@4@7@<@M@J@V@T@H@L@<@7@K@W@N@M@J@V@+@O@L@X@N@W@K@L@+@L@H@T@O@X@4@7@<@J@M@V@T@H@L@4@<@7@L@O@X@M@J@V@+@J@S@G@+@O@J@L@X@5@J@7@;@M@V@G@S@;@7@5@J@M@V@0@H@L@T@0@4@<@7@4@<@7@7@<@@@T@H@T@H@@@<@7@L@J@V@T@H@0@<@L@X@J@V@T@H@X@L@0@<@<@7@J@V@@@T@H@@@<@7@L@X@J@V@.@:@T@H@:@.@X@L@7@<@J@V@@@T@H@@@<@7@T@H@J@V@9@L@-@X@T@H@H@T@-@9@X@L@9@<@J@V@A@T@H@L@X@A@9@<@J@V@,@8@T@H@,@8@X@L@8@<@J@V@A@T@H@8@A@<@H@T@J@V@7@+@L@O@X@T@H@L@L@H@T@+@O@7@X@7@<@J@V@@@M@T@H@L@@@<@7@X@L@O@M@J@V@+@J@S@G@+@O@X@L@J@7@J@;@V@M@G@S@;@7@M@J@V@0@<@7@O@T@H@0@<@7@7@+@+@O@T@7@H@0@$@H@L@T@0@$@T@H@L@ M@)@Q@P@)@Q@M@9@<@M@A@P@Q@A@9@<@Q@0@Q@Q@0@M@9@<@M@T@A@Q@A@<@9@Q@M@T@.@M@R@V@.@:@>@A@F@:@>@A@E@F@5@E@F@H@F@5@:@J@>@A@M@H@>@:@A@J@R@V@&@J@M@L@&@M@J@M@J@9@A@>@L@>@A@9@-@-@J@M@9@J@M@>@A@Q@>@A@9@J@Q@R@J@+@O@M@+@:@>@C@>@:@C@B@2@C@B@E@C@2@:@O@>@R@E@>@F@:@O@J@F@J@.@:@O@:@.@J@:@O@>@>@:@J@O@+@7@O@J@+@7@J@,@8@O@,@8@J@9@-@H@-@9@9@<@A@A@<@9@2@M@H@2@9@>@A@>@A@9@4@L@M@P@L@4@;@S@@@>@P@>@;@@@X@X@X@S@8@V@8@X@;@@@S@>@V@>@;@@@T@S@9@<@@@Q@T@Q@@@<@9@Q@@@R@7@<@Q@0@7@@@<@0@M@)@R@Q@P@Q@M@)@9@<@M@A@P@Q@A@9@<@0@Q@0@M@9@<@M@A@T@Q@A@<@9@Q@M@T@.@R@M@V@.@:@A@>@F@>@:@A@E@F@5@F@E@H@F@5@:@J@A@>@H@>@:@A@M@R@J@V@&@M@J@L@M@J@&@M@9@J@>@A@L@>@A@9@-@-@J@M@9@J@M@>@A@Q@>@A@9@Q@M@J@R@+@J@O@+@:@>@C@>@:@B@C@2@C@B@E@2@C@:@>@F@O@E@>@:@O@J@F@R@J@:@.@O@:@.@:@J@O@>@>@:@J@O@+@7@O@+@J@7@J@,@8@O@,@8@9@-@H@J@5@)@-@9@4@(@)@5@2@&@(@4@1@%@H@M@&@G@2@D@D@D@M@M@D@G@1@%@E@$@M@H@0@Q@H@H@T@Q@E@0@$@9@<@A@A@<@9@O@T@H@F@0@<@H@F@0@O@<@0@J@$@H@F@L@J@0@F@$@5@E@M@)@L@)@M@E@5@G@H@G@J@H@L@J@M@L@O@M@M@)@O@Q@P@)@Q@M@9@<@M@A@P@Q@A@<@9@0@Q@0@M@9@<@M@A@T@Q@A@<@9@Q@M@T@.@R@M@V@.@:@A@>@F@>@:@A@E@F@5@E@F@H@F@5@:@J@>@A@H@>@:@A@M@R@J@V@&@M@J@L@&@J@M@M@J@9@>@A@L@>@A@9@-@-@M@J@9@J@M@A@>@Q@>@A@9@J@Q@R@+@J@O@M@+@:@>@C@>@:@C@B@2@C@B@E@2@C@:@O@>@R@E@F@>@:@O@J@F@J@.@:@O@.@:@J@:@O@>@>@:@J@O@+@7@O@J@+@7@J@,@8@O@,@8@J@9@-@H@-@9@<@9@A@A@<@9@2@M@H@2@9@>@A@>@A@9@4@L@M@P@L@4@;@@@S@>@P@>@;@@@X@S@8@V@8@X@@@;@S@>@V@>@;@@@T@S@9@<@@@Q@T@Q@Q@Q@@@<@9@Q@@@R@7@<@Q@0@7@@@<@0@M@)@R@Q@P@Q@M@)@9@<@M@A@P@Q@A@<@9@0@Q@0@M@9@<@M@T@A@Q@A@<@9@Q@M@T@.@R@M@V@.@:@>@A@F@>@:@A@E@F@5@F@E@H@F@5@:@J@>@A@H@>@:@A@M@R@J@V@&@M@J@L@M@J@&@J@M@9@>@A@L@>@A@9@-@-@M@J@M@9@J@>@A@Q@>@A@9@Q@M@J@R@+@J@O@+@:@>@C@>@:@B@C@2@C@B@E@2@C@:@>@O@E@F@>@:@O@J@F@R@:@J@.@O@:@.@J@:@O@>@>@:@J@O@+@7@O@+@J@7@J@,@8@O@,@8@9@-@H@J@5@)@-@9@4@(@)@5@2@&@(@4@1@%@D@H@M@&@G@2@M@M@D@G@1@%@0@$@E@H@M@H@Q@H@T@Q@E@0@$@9@<@A@A@9@<@O@F@T@H@0@<@H@F@O@0@<@0@J@$@H@L@J@0@$@5@E@M@)@L@)@M@E@5@ @M@Y@)@T@Q@)@Q@M@@T@Y@ 5@9@<@A@H@A@9@<@5@H@5@9@E@<@A@A@<@9@5@H@E@?@6@9@<@6@?@<@9@E@H@?@6@9@<@H@E@?@6@<@9@E@H@7@<@@@C@E@@@<@7@H@C@7@L@<@@@H@@@<@7@O@L@7@<@@@@@<@7@L@O@@@7@<@H@L@@@<@7@C@H@2@E@<@C@B@2@<@B@E@2@9@H@B@2@9@B@H@7@;@L@A@A@;@7@J@A@L@7@;@;@7@@@H@A@J@0@<@ 0@@@<@H@0@$@O@L@T@H@0@O@$@T@H@L@ )@A@>@)@5@9@@@=@>@A@9@5@A@>@=@@@-@@@=@>@A@-@5@9@>@A@=@@@9@5@>@A@)@E@)@5@9@J@A@E@9@5@E@A@J@-@H@E@J@H@-@5@9@H@J@9@5@E@H@0@@@C@E@0@C@@@?@4@7@<@B@4@<@7@C@@@B@?@+@?@@@C@B@+@4@@@7@<@C@B@?@4@<@7@C@@@0@H@0@4@7@<@L@C@H@4@<@7@H@C@L@+@J@H@L@J@+@4@7@<@J@L@4@<@7@H@J@+@J@G@H@+@J@G@5@7@I@;@F@;@7@5@J@G@F@I@/@/@/@I@/@G@F@J@5@;@7@J@G@F@I@;@7@5@J@G@+@M@+@5@7@;@G@M@Q@;@7@5@M@Q@G@2@O@M@O@Q@2@5@7@O@;@Q@;@7@5@M@O@3@6@<@T@H@M@T@H@T@H@T@3@6@<@H@3@6@<@T@H@3@6@<@H@6@3@<@H@T@Q@Q@3@6@<@H@4@<@7@O@H@4@7@O@<@H@@@C@C@@@@@C@C@@@@@C@C@@@@@C@C@@@)@>@A@)@>@A@5@9@=@@@9@5@>@A@=@@@-@@@=@A@-@>@5@9@A@>@=@@@9@5@>@A@)@E@)@5@9@J@A@E@9@5@E@A@J@-@H@E@J@H@-@5@9@H@J@9@5@E@H@0@@@C@E@0@C@@@4@?@7@<@B@4@<@7@@@C@B@?@+@?@+@B@@@C@4@@@C@<@7@B@?@4@<@7@C@@@0@H@0@4@7@<@L@C@H@4@<@7@H@C@L@+@J@H@L@J@+@4@7@<@J@L@4@<@7@H@J@5@E@)@H@D@E@)@5@2@&@E@D@E@E@O@&@2@4@(@E@E@M@O@(@4@5@)@E@E@H@M@)@5@+@7@L@C@E@H@K@+@C@7@L@<@7@@@L@K@@@<@7@Q@L@?@6@<@T@Q@6@?@<@7@<@@@O@T@L@O@@@<@7@9@-@H@B@L@B@H@-@9@2@&@H@B@&@B@2@H@+@7@L@A@G@A@G@J@A@G@L@+@7@/@;@/@/@@@C@H@A@J@G@;@/@0@<@0@C@@@<@H@@@C@C@@@@@C@C@@@@@C@C@@@@@C@C@@@)@A@>@ `)@5@9@=@>@@@A@9@5@A@>@=@@@-@@@=@>@A@-@5@9@>@A@=@@@9@5@>@A@)@E@)@5@9@J@A@E@9@5@E@A@J@-@H@E@J@H@-@5@9@H@J@9@5@E@H@0@@@E@C@0@C@@@?@4@7@<@B@4@<@7@@@C@B@?@+@?@@@C@B@+@4@@@7@<@C@B@?@4@<@7@C@@@0@H@0@4@<@7@L@C@H@4@<@7@H@C@L@+@J@H@L@J@+@4@7@<@J@L@4@<@7@H@J@+@J@G@H@+@J@G@5@7@;@I@F@;@7@5@J@G@F@I@/@/@/@I@/@G@F@J@5@7@J@;@G@F@I@;@7@5@G@J@+@M@+@5@7@;@G@M@Q@;@7@5@M@Q@G@2@O@M@O@Q@2@5@7@O@;@Q@;@7@5@M@O@3@6@<@T@H@M@T@H@H@T@3@H@6@T@<@3@6@<@H@T@3@6@<@H@3@6@<@H@T@Q@Q@3@6@<@H@4@<@7@H@O@7@O@4@<@H@@@C@C@@@@@C@C@@@@@C@@@C@@@C@C@@@)@>@A@)@>@A@5@9@=@@@9@5@>@A@=@@@-@@@=@A@-@>@5@9@>@A@=@@@9@5@A@>@)@E@)@5@9@J@A@E@9@5@E@A@J@-@H@E@J@H@-@5@9@H@J@9@5@E@H@0@@@C@E@0@@@C@4@?@7@<@B@4@<@7@C@@@B@?@+@?@B@+@@@C@4@@@C@7@<@B@?@4@<@7@C@@@0@H@0@4@7@<@L@C@H@4@<@7@H@C@L@+@J@H@L@J@+@4@7@<@J@L@4@<@7@H@J@5@E@)@H@D@E@)@5@2@&@E@D@E@E@O@&@2@4@(@E@E@M@O@(@4@5@)@E@E@H@M@)@5@+@7@L@C@E@H@K@+@C@7@L@<@L@7@@@K@<@@@7@Q@L@?@6@<@T@Q@6@?@<@<@7@@@O@T@L@O@@@<@7@9@-@H@B@L@B@H@-@9@2@&@H@B@&@B@2@H@+@7@L@A@G@A@G@A@G@J@L@+@7@/@;@/@/@@@C@H@A@G@/@;@J@0@<@0@<@7@+@+@C@@@7@H@0@$@O@L@H@T@0@O@$@T@H@L@ @ @ .  s ..  s EPSON S s BINSTAL S s ;INSTALL ACC s +INSTALL BAT s hINSTALL C s 'JX80C S s VSAVER BAT s <SAVER C s CGP220 PRT s EPSON PRT s PROWTR PRT s OKI20C PRT  t B*# * Epson 2-way B&W graphics dumper * * Written by Tom Hudson * * Copyright 1986, not to be sold * *# PHASE .equ 64 KBSHIFT .equ 65 X .equ 66 Y .equ 68 REZ .equ 70 .globl _dumper ;convenient labelfor dump routine .text _dumper: move.l a0,d0 ;save A0 move.l 16(a7),a0 ;get work area address movem.l d0-a7,(a0) ;shove registers in work area move.l 8(a7),a1 ;screen address--->A1 move.l 12(a7),a2 ;palette address--->A2 tst.w 4(a7) ;init? bne process ;no, go dump! * reset & initialize printer * init: link a6,#-4 move.w #$FFFF,(sp) ;get... move.w #11,-(sp) ;kbshift status trap #13 unlk a6 move.l 16(a7),a0 ;get work area pointer again move.b d0,KBSHIFT(a0) ;save kbshift status move.w 6(a7),REZ(a0) ;save rez * BUILD PIXEL TABLE * move.l #$f,1200(a0) ;black... move.l #$55ff55ff,1204(a0) move.l #$55bb55ee,1208(a0) move.l #$aa55aa55,1212(a0) move.l #$aa44aa11,1216(a0) move.l #$aa00aa00,1220(a0) move.l #$88002200,1224(a0) move.l #$0,1228(a0) ;to white move.b KBSHIFT(a0),d0 ;get kbshift and.b #8,d0 ;ALT? beq sethoriz ;no, do horizontal cmp.w #2,REZ(a0) ;hi rez? beq hivinit ;yes! * reset phase counter * move.b #192,PHASE(a0) ;2 pixels per scan line bra fininit hivinit: move.b #128,PHASE(a0) ;1 pixel per scan line bra fininit sethoriz: tst.w REZ(a0) ;hi rez? beq lowhinit ;yup! * reset phase counter * move.b #128,PHASE(a0) ;1 pixel per scan line bra fininit lowhinit: move.b #192,PHASE(a0) ;2 pixels per scan line * set init string * fininit: move.l #$1b401b41,100(a0) ;finish init by resetting printer & move.w #$080d,104(a0) ;setting linefeed, etc. move.l #6,d2 ;6 bytes in init buffer lea 100(a0),a3 ;point to bytes bsr printit ;print the init stuff lea 100(a0),a3 ;point to print buffer move.w #242,d1 ;clear 242 * 4 bytes clpln: clr.l (a3)+ subq #1,d1 bne clpln tst.w d0 bpl exit * exit w/error condition (0) * error: movem.l (a0),d0-a7 move.l d0,a0 clr.w d0 ;0 indicates error rts * exit the subroutine (no error) * exit: movem.l (a0),d0-a7 move.l d0,a0 move.w #1,d0 ;1 indicates success rts * exit w/abort condition (2) * abort: movem.l (a0),d0-a7 move.l d0,a0 move.w #2,d0 ;2 indicates abort rts * process the pixels and send to printer * process: move.b KBSHIFT(a0),d0 ;get keyboard info and.b #8,d0 ;ALT? beq hformat ;no! tst.w REZ(a0) ;low rez? beq lowvert ;yes! cmp.w #1,REZ(a0) ;med rez? beq medvert ;yes! bra hivert ;only one left... *# * horizontal format dump routines * *# hformat: tst.w REZ(a0) ;low rez? beq lowproc ;yes! cmp.w #1,REZ(a0) ;med rez? beq medproc ;yes! * HI-REZ PROCESSOR * clr.w X(a0) ;start at X=0 nx2: lea 104(a0),a4 ;point A4 to print buffer move.w #399,Y(a0) ;start at Y=399 * GET PIXEL * nx2b: bsr get2 ;get a pixel move.b d0,d1 ;value in d1 (0 or 1) andi.l #$0ff,d1 lsl.l #1,d1 ;mult by 2 for palette index add.l a2,d1 ;add palette start address movea.l d1,a5 ;shove in A5 btst.b #0,1(a5) ;low bit on? bne white ;yes, it's white! * black pixel * move.b (a4),d1 ;get print buffer byte or.b PHASE(a0),d1 ;turn on bits using PHASE move.b d1,(a4)+ ;put it back in print line move.b d1,(a4)+ ;(twice) bra np2 ;next pixel! * white pixel * white: addq.l #2,a4 ;bypass next 2 printer bytes np2: subq.w #1,Y(a0) ;next Y position bpl nx2b ;branch if more move.b PHASE(a0),d1 ;get PHASE lsr.b #1,d1 ;shift right 1 bit move.b d1,PHASE(a0) ;put back in PHASE tst.b d1 ;any bits left? bne xl2 ;yes, loop back. move.b #128,PHASE(a0) ;reset PHASE bsr doprnt ;print the line! tst.w d0 ;OK? bmi error ;no! xl2: bsr pabchk ;check for UNDO tst.w d0 ;UNDO? bne abort ;yes -- abort! addq.w #1,X(a0) ;next X position cmp.w #640,X(a0) ;end of line? bne nx2 ;no! bsr cleanup ;all done, cleanup printer... bra exit ;and exit * MEDIUM-REZ PROCESSOR * medproc: clr.w X(a0) ;start at X=0 nx1: lea 104(a0),a4 ;point to printer buffer move.w #199,Y(a0) ;start at Y=199 * GET PIXEL * nx1b: bsr get1 ;get a pixel bsr ppix ;put in print line subq.w #1,Y(a0) ;next Y bpl nx1b ;loop if more move.b PHASE(a0),d1 ;get PHASE lsr.b #1,d1 ;shift it right 1 bit move.b d1,PHASE(a0) ;put back tst.b d1 ;end of phase run? bne xl1 ;no! move.b #128,PHASE(a0) ;reset PHASE bsr doprnt ;print the line tst.w d0 ;print error? bmi error ;yes! xl1: bsr pabchk ;check for UNDO abort tst.w d0 ;UNDO? bne abort ;yes! addq.w #1,X(a0) ;next X cmp.w #640,X(a0) ;X done? bne nx1 ;no! bsr cleanup ;cleanup printer... bra exit ;and exit! * LOW-REZ PROCESSOR * lowproc: clr.w X(a0) ;start X at 0 nx0: lea 104(a0),a4 ;point to printer buffer move.w #199,Y(a0) ;start Y at 199 * GET PIXEL * nx0b: bsr get0 ;get a pixel bsr ppix ;put in print line subq.w #1,Y(a0) ;next Y bpl nx0b ;loop if more Y move.b PHASE(a0),d1 ;get phase lsr.b #2,d1 ;shift right 2 bits move.b d1,PHASE(a0) ;put back in phase byte tst.b d1 ;end of phase run? bne xl0 ;no! move.b #192,PHASE(a0) ;reset phase bsr doprnt ;print the line tst.w d0 ;error? bmi error ;yes! xl0: bsr pabchk ;check for UNDO abort tst.w d0 ;UNDO? bne abort ;yes! addq.w #1,X(a0) ;next X cmp.w #320,X(a0) ;done? bne nx0 ;no, loop back. bsr cleanup ;all done, cleanup printer... bra exit ;and exit! * Vertical-format dump routines * * HI-REZ PROCESSOR * hivert: clr.w Y(a0) ;start Y ay 0 vnx2: lea 104(a0),a4 ;point to print buffer clr.w X(a0) ;start X at 0 * GET PIXEL * vnx2b: bsr get2 ;get a pixel move.b d0,d1 ;put it in D1 andi.l #$0ff,d1 lsl.l #1,d1 ;multiply by 2 for index add.l a2,d1 ;add start of color palette movea.l d1,a5 ;stick in A5 btst.b #0,1(a5) ;low bit on? bne vwhite ;yes, it's white! * black pixel * move.b (a4),d1 ;turn on printer bits or.b PHASE(a0),d1 move.b d1,(a4)+ move.w X(a0),d2 ;get X and.w #1,d2 ;even pixel? bne vnp2 ;no! move.b d1,(a4)+ ;it's even, do it twice. bra vnp2 * white pixel * vwhite: addq.l #1,a4 ;skip printer byte move.w X(a0),d2 ;get X and.w #1,d2 ;is it even? bne vnp2 ;no! addq.l #1,a4 ;do it twice vnp2: addq.w #1,X(a0) ;next X cmpi.w #640,X(a0) ;X done? bne vnx2b ;no, loop! move.b PHASE(a0),d1 ;get phase lsr.b #1,d1 ;shift right 1 bit move.b d1,PHASE(a0) ;put it back tst.b d1 ;end of phase run? bne vxl2 ;no! move.b #128,PHASE(a0) ;reset phase bsr dovprnt ;print it! tst.w d0 ;print OK? bmi error ;no! vxl2: bsr pabchk ;check for UNDO tst.w d0 ;UNDO? bne abort ;yes! addq.w #1,Y(a0) ;next Y position cmp.w #400,Y(a0) ;end of Y? bne vnx2 ;no, loop back. bsr cleanup ;all done, cleanup printer... bra exit ;and exit. * MEDIUM-REZ PROCESSOR * medvert: clr.w Y(a0) ;start Y at 0 vnx1: lea 104(a0),a4 ;point to print line clr.w X(a0) ;start X at 0 clr.w d7 ;clear counter * GET PIXEL * vnx1b: bsr get1 ;get a pixel bsr ppix ;put in print line addq.w #1,X(a0) ;next X cmpi.w #640,X(a0) ;end of X? bne vnx1b ;no! move.b PHASE(a0),d1 ;shift phase lsr.b #2,d1 move.b d1,PHASE(a0) tst.b d1 ;end of phase run? bne vxl1 ;no! move.b #192,PHASE(a0) ;reset phase bsr dovprnt ;print it! tst.w d0 ;print OK? bmi error ;no! vxl1: bsr pabchk ;UNDO check tst.w d0 ;UNDO? bne abort ;yes, abort! addq.w #1,Y(a0) ;next Y cmp.w #200,Y(a0) ;Y done? bne vnx1 ;no! bsr cleanup ;cleanup printer... bra exit ;and exit! * LOW-REZ PROCESSOR * lowvert: clr.w Y(a0) ;start Y at 0 vnx0: lea 104(a0),a4 ;point to printer buffer clr.w X(a0) ;start X at 0 * GET PIXEL * vnx0b: bsr get0 ;get pixel bsr ppix ;put in print line addq.w #1,X(a0) ;next X cmpi.w #320,X(a0) ;X done? bne vnx0b ;no! move.b PHASE(a0),d1 ;shift phase bits lsr.b #2,d1 move.b d1,PHASE(a0) tst.b d1 ;end of phase run? bne vxl0 ;no! move.b #192,PHASE(a0) ;reset phase bsr dovprnt ;print it! tst.w d0 ;print OK? bmi error ;no! vxl0: bsr pabchk ;UNDO check tst.w d0 ;UNDO? bne abort ;yes! addq.w #1,Y(a0) ;next Y cmp.w #200,Y(a0) ;Y done? bne vnx0 ;no! bsr cleanup ;cleanup printer... bra exit ;and exit! * * print string to printer * *-* * input: * * d2.L # of bytes to print * * a3: address of 1st byte * * returns: * * d0 = -1: error! * * d0 = 0: OK! * * printit: move.l #270000,d1 ;timeout count (works out to +/- 30 secs.) statloop: link a5,#-20 ;save registers on stack move.l a0,(sp) move.l a1,-(sp) move.l a2,-(sp) move.l d1,-(sp) move.l d2,-(sp) link a6,#-4 ;Request printer clr.w (sp) ;output status move.w #8,-(sp) trap #13 unlk a6 move.l (sp)+,d2 ;restore registers move.l (sp)+,d1 move.l (sp)+,a2 move.l (sp)+,a1 move.l (sp)+,a0 unlk a5 tst.l d0 ;printer ready? bmi prtrdy ;yes! subq.l #1,d1 ;decrement timeout counter bpl statloop ;and try again move.w #-1,d0 ;printer error! rts prtrdy: link a5,#-20 ;save registers move.l a0,(sp) move.l a1,-(sp) move.l a2,-(sp) move.l d1,-(sp) move.l d2,-(sp) link a6,#-6 move.b (a3),d0 ;get byte to print andi.w #$00FF,d0 ;mask off to be safe move.w d0,(sp) ;put on stack clr.w -(sp) ;device #0 (printer) move.w #3,-(sp) ;conout trap #13 ;send to printer! unlk a6 move.l (sp)+,d2 ;restore registers move.l (sp)+,d1 move.l (sp)+,a2 move.l (sp)+,a1 move.l (sp)+,a0 unlk a5 addq.l #1,a3 ;point to next byte subq.w #1,d2 ;decrement counter bne printit ;loop if more bytes clr.w d0 ;OK! rts * CHECK FOR UNDO KEY ABORT * pabchk: link a5,#-20 ;Save registers move.l a0,(sp) move.l a1,-(sp) move.l a2,-(sp) move.l d1,-(sp) move.l d2,-(sp) link a6,#-4 ;request keyboard status move.w #2,(sp) ;(returns with D0 = 0 if no characters) move.w #1,-(sp) trap #13 unlk a6 tst.w d0 ;any keys? beq abcexit ;no! link a6,#-4 ;there's a keypress waiting... move.w #2,(sp) ;don't make it wait! move.w #2,-(sp) trap #13 ;get key... unlk a6 cmp.l #$00610000,d0 ;UNDO? bne nobort ;no! move.w #1,d0 ;yes, set abort flag abcexit: move.l (sp)+,d2 ;restore the saved registers move.l (sp)+,d1 move.l (sp)+,a2 move.l (sp)+,a1 move.l (sp)+,a0 unlk a5 rts nobort: clr.w d0 ;clear D0 (no abort) bra abcexit ;and go to exit point * GET hi-rez pixel (0-1) * get2: link a5,#-20 ;save the registers on stack move.l a0,(sp) move.l a1,-(sp) move.l a2,-(sp) move.l d1,-(sp) move.l d2,-(sp) move.w Y(a0),d0 ;get Y coordinate and.l #$0000ffff,d0 ;mask it mulu #80,d0 ;mult. by 80 adda.l d0,a1 ;add to screen base move.w X(a0),d1 ;get X move.w d1,d2 lsr.w #3,d1 ;divide X by 8 adda.w d1,a1 ;add to screen pointer move.b (a1),d0 ;get screen byte and.l #7,d2 ;get byte mask number move.b #$80,d1 ;set up bit mask lsr.b d2,d1 ;shift mask into position and.b d1,d0 ;mask a bit bne set2 clr.w d0 bra getx2 ;bit off! set2: move.w #1,d0 ;bit on! getx2: move.l (sp)+,d2 ;restore registers move.l (sp)+,d1 move.l (sp)+,a2 move.l (sp)+,a1 move.l (sp)+,a0 unlk a5 rts * get medium-rez pixel * get1: link a5,#-24 ;save registers move.l a0,(sp) move.l a1,-(sp) move.l a2,-(sp) move.l d1,-(sp) move.l d2,-(sp) move.l d3,-(sp) clr.w d0 ;zero result register move.w Y(a0),d3 ;grab Y coordinate and.l #$0000ffff,d3 ;mask it off mulu #160,d3 ;multiply by 160 (# of bytes per scan line) adda.l d3,a1 ;add to screen base address move.w X(a0),d1 ;get X coordinate move.w d1,d2 ;duplicate in D2 lsr.w #2,d1 ;divide it by 4 and.w #$00fc,d1 ;turn off lower 3 bits adda.w d1,a1 ;add to screen address move.w (a1),d3 ;get the screen word and.l #15,d2 ;mask X to 0-15 (index within group) move.w #$8000,d1 ;set up a bit mask lsr.w d2,d1 ;shift it by the group index and.w d1,d3 ;get low-order color bit beq bit1b ;it's off, go to next color bit move.w #1,d0 ;set bit in result register bit1b: move.w 2(a1),d3 ;get second pixel group from screen and.w d1,d3 ;get high-order color bit beq getx1 ;it's off, go exit. or.w #2,d0 ;it's on, turn on appropriate color bit in result getx1: move.l (sp)+,d3 ;restore the registers move.l (sp)+,d2 move.l (sp)+,d1 move.l (sp)+,a2 move.l (sp)+,a1 move.l (sp)+,a0 unlk a5 rts * get low-rez pixel * get0: link a5,#-24 ;save registers move.l a0,(sp) move.l a1,-(sp) move.l a2,-(sp) move.l d1,-(sp) move.l d2,-(sp) move.l d3,-(sp) clr.w d0 ;zero result register move.w Y(a0),d3 ;get Y coordinate and.l #$0000ffff,d3 ;mask off for multiply mulu #160,d3 ;multiply by 160 (# of bytes per scan line) adda.l d3,a1 ;add to screen base address move.w X(a0),d1 ;get X coordinate move.w d1,d2 ;duplicate it in D2 lsr.w #1,d1 ;divide it by 2 and.w #$00f8,d1 ;turn off lower 3 bits adda.w d1,a1 ;add to screen address register move.w (a1),d3 ;grab screen word and.l #15,d2 ;mask X to 0-15 move.w #$8000,d1 ;set up bit mask lsr.w d2,d1 ;shift bit mask 0-15 bits and.w d1,d3 ;mask off bit 0 beq bit0b ;bit's off, go get next color bit move.w #1,d0 ;turn on bit 0 in result bit0b: move.w 2(a1),d3 ;get screen word for bit 1 of color and.w d1,d3 ;get bit 1 beq bit0c ;it's off, try bit 2 or.w #2,d0 ;turn on bit 1 in result bit0c: move.w 4(a1),d3 ;get screen word for bit 2 and.w d1,d3 ;get bit 2 beq bit0d ;it's off, try bit 3 or.w #4,d0 ;turn on bit 2 in result bit0d: move.w 6(a1),d3 ;get word for bit 3 and.w d1,d3 ;get bit 3 beq getx0 ;it's off! or.w #8,d0 ;turn on bit 3 in result getx0: move.l (sp)+,d3 ;restore the registers move.l (sp)+,d2 move.l (sp)+,d1 move.l (sp)+,a2 move.l (sp)+,a1 move.l (sp)+,a0 unlk a5 rts cleanup: move.b #12,100(a0) ;do a page eject on printer move.l #1,d2 lea 100(a0),a3 bsr printit rts ;and exit * horizontal format print * doprnt: move.l #$1b4c2003,100(a0) ;build print line header... move.w #$0d0a,904(a0) ;and print line tail (CR/LF) move.l #806,d2 ;print 806 bytes lea 100(a0),a3 bsr printit lea 100(a0),a3 ;clear print line move.w #210,d1 clpln2: clr.l (a3)+ subq #1,d1 bne clpln2 rts * vertical format print * dovprnt: move.l #$1b4cc003,100(a0) ;build print header move.w #$0d0a,1064(a0) ;and tail (CR/LF) move.l #966,d2 ;print 966 bytes lea 100(a0),a3 bsr printit lea 100(a0),a3 ;clear print line move.w #242,d1 vclpln2: clr.l (a3)+ subq #1,d1 bne vclpln 2 rts * CHANGE COLOR TO GRAY-SCALE * * AND PUT IN PRINT LINE * ppix: move.b d0,d1 ;put pixel index in d1 andi.l #$0ff,d1 ;mask it lsl.l #1,d1 ;multiply by 2 add.l a2,d1 ;add palette start address movea.l d1,a5 ;put in a5 move.w (a5),d0 ;get color ($000-$777) move.w d0,d2 ;duplicate it and.w #7,d2 ;mask BLUE bits move.w d0,d1 ;duplicate again lsr.w #4,d1 ;shift... and.w #7,d1 ;and mask GREEN bits add.w d1,d2 ;add green and blue move.w d0,d1 ;duplicate color AGAIN! lsr.w #8,d1 ;shift... and.w #7,d1 ;and mask RED bits add.w d1,d2 ;add to total (now 0-21) and.l #$0ff,d2 ;mask for divide divu #3,d2 ;divide by 3 (now 0-7) lsl.w #2,d2 ;mult by 4 for index into gray-scale table lea 0(a0,d2.w),a5 ;get effective address adda.l #1200,a5 ;add table start offset move.b KBSHIFT(a0),d1 ;get keybd bits and.b #8,d1 ;ALT (vert format)? bne vchange ;yes, do vert! * handle pixel color * move.b (a5),d1 ;get gray-scale byte and.b PHASE(a0),d1 ;mask with phase or.b (a4),d1 ;or with print byte move.b d1,(a4)+ ;and set print bits move.b 1(a5),d1 ;do three more times (4 dots per pixel) and.b PHASE(a0),d1 or.b (a4),d1 move.b d1,(a4)+ move.b 2(a5),d1 and.b PHASE(a0),d1 or.b (a4),d1 move.b d1,(a4)+ move.b 3(a5),d1 and.b PHASE(a0),d1 or.b (a4),d1 move.b d1,(a4)+ rts *