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 * handle vertical pixel color * vchange: move.b 0(a5,d7.w),d1 ;get gray-scale byte addq.w #1,d7 ;increment D7 (printer dot counter) and.w #3,d7 ;force D7 0-3 and.b PHASE(a0),d1 ;mask with phase or.b (a4),d1 ;or with print byte move.b d1,(a4)+ ;put in print line tst.w REZ(a0) ;low rez? beq dump3 ;yes! move.w X(a0),d1 ;med rez: and.w #1,d1 ;is X even? beq dump2 ;yes! rts ;no, exit dump3: move.b 0(a5,d7.w),d1 ;dump second & third bytes for low rez addq.w #1,d7 and.w #3,d7 and.b PHASE(a0),d1 or.b (a4),d1 move.b d1,(a4)+ dump2: move.b 0(a5,d7.w),d1 ;dump second byte for medium rez+even addq.w #1,d7 and.w #3,d7 and.b PHASE(a0),d1 or.b (a4),d1 move.b d1,(a4)+ rts filler .ds.l 500 ;pad to make sure it's at least 2000 bytes * That's all! *   *- * DEGAS(TM) Printer Driver Installer * * Assembly language source code * * written by Tom Hudson * * Copyright 1986, ANTIC Publishing * * Freeware, not to be sold * * +* * ---> NOTE: Link with INSTALL.C <--- * *- .globl _install ;Routine to change SCRDMP vector .globl _scrdump ;My screen dump printer driver code .text _install: move.l #doit,-(sp) ;point to the vector changer code move.w #38,-(sp) ;we want to do it in supervisor mode! trap #14 ;execute it! addq.l #6,sp ;restore stack pointer rts ;and return to caller doit: move.l #_dumpctrl,$502 ;point the system screen dump vector to my routine rts ;and return _scrdump: .ds.l 500 ;reserve 2000 bytes for driver code * * End of listing * * ` F\ .|N .NA"/0<NBNuNVJHN @.?9NN $T=@.N n(f0.nf.?<N T3 yfBy `3 >N |A@|:BW/?<GN \./^aXX./^aXB.J. /J/^N P3DJyDo y f.^aD.J/^aXBW/^?<=N \:JEmj./<??<?N P#J>?<>N T Jg.l?<N T`8N.?<N T``.B?<N T````v`NJLN^NuNV`R nJf n H"nR RJ@fN^NuNV n H"nR RJ@fN^NuNVHBG`RG nHRJf0JLN^NuNVH.a>`0G \gSGJGl0GB(JLN^NuNV>N =@>N #Bn`*0n/? ?< N T./</9?.BgN =@Jng&./</9?.?<N BW?< N TN^Nu/<?<&NN\Nu#Nu#NN/9Nu#NM/9Nu#NA/9NuNV30.|Hм F-@=|` nH2n2RRn nm.FNB@096N^NuNV####6#j#r#F> aF36NpN^NuNV>a*pN^NuNV#j>N N^NuNV3# j>4N N^NuNV#j# n>ZN n08B@096N^NuNV3# j>#N N^Nu    - Printer Driver[1][DEGAS Printer Installer|by Tom Hudson| | 1986 ANTIC Publishing|Version 1.0][Horizontal| Vertical ][1][Printer driver installed][ OK ][3][ |Can't open driver file!| ][ Sorry ][3][ |That is not a printer driver!| ][ Sorry ]*.PRT"  " :   "     $     as68 -l -u instal.s cp68 install.c install.i c068 install.i install.1 install.2 install.3 -f rm install.i c168 install.1 install.2 install.s rm install.1 rm install.2 as68 -l -u install.s rm install.s link68 install.68k=accstart,install,instal,osbind,vdibind,aesbind rm instal.o rm install.o relmod install.68k install.acc rm install.68k wait  /*,/ /* DEGAS(TM) Printer Driver Installer */ /* Written by Tom Hudson */ /* Copyright 1986, ANTIC Publishing */ /* Freeware, not to be sold */ /* **/ /* Installs a DEGAS printer driver as */ /* the default screen dump routine. */ /* ---> NOTE: Link with INSTALL.S <--- */ /*,/ #include #define HORIZONTAL 0 #define VERTICAL 8 extern scrdump(); /* The printer driver code */ extern int gl_apid; /* ID of our accessory */ int contrl[13]; /* Idiotic bindings */ int intin[128]; int ptsin[128]; int intout[128]; int ptsout[128]; int fresult,fbutton,mexit,prtmode; long bcount; char menuname[] = " Printer Driver"; /* Name in desk menu */ /*-/ /* Our miscellaneous form_alert strings */ /*-/ char intro[] = "[1][DEGAS\277 Printer Installer|by Tom Hudson| |\275 1986 ANTIC Publishing|Version 1.0][Horizontal| Vertical ]"; char instOK[] = "[1][Printer driver installed][ OK ]"; char cantopen[] = "[3][ |Can't open driver file!| ][ Sorry ]"; char notpd[] = "[3][ |That is not a printer driver!| ][ Sorry ]"; /*-/ /* Start of desk accessory code */ /*-/ main() { register int i,j,handle; int menuID1,mgbuf[8]; char defpath[64],workpath[80],filename[20]; /*-/ /* Initialize the desk accessory application */ /*-/ appl_init(); /*-/ /* Install our accessory name in menu bar */ /*-/ menuID1 = menu_register(gl_apid, menuname); /*-/ /* Loop forever looking for startup call */ /*-/ for (;;) { evnt_mesag(mgbuf); /* Wait on a message event */ /*-/ /* We are being called! */ /*-/ if (mgbuf[0] == 40 && mgbuf[4] == menuID1) { for (;;) { /*-/ /* Display configuration alert box */ /* prtmode sets either normal (horizontal) */ /* or Alternate (vertical) modes. */ /*-/ mexit=form_alert(2,intro); if(mexit == 1) prtmode=HORIZONTAL; else prtmode=VERTICAL; /*-/ /* Build pathname with *.PRT extension */ /*-/ defpath[0] = Dgetdrv() + 'A'; defpath[1] = ':'; Dgetpath(&defpath[2], 0); strcpy(workpath, defpath); strcat(workpath,"*.PRT"); filename[0]=0; /*-/ /* Use file selector to get the driver file */ /*-/ fresult=fsel_input(workpath,filename,&fbutton); /*-/ /* If file was selected, grab info! */ /*-/ if(fresult>0 && fbutton==1) { trunname(workpath); strcat(workpath,filename); /*-/ /* Attempt to load the printer driver file */ /*-/ handle = Fopen(workpath,0); if (handle >= 0) { bcount=Fread(handle,2000L,&scrdump); Fclose(handle); /*-/ /* A driver file must be 2000 bytes long! */ /*-/ if(bcount!=2000L) { form_alert(1,notpd); break; } /*-/ /* Install the driver, everything's GO! */ /*-/ install(); form_alert(1,instOK); break; } else /*-/ /* Can't open the file, pal! */ /*-/ { form_alert(1,cantopen); break; } } else { break; } } } } } /*-/ /* General-utility string concatenator */ /*-/ strcat(to,from) char *to,*from; { while (*to) ++to; while (*to++ = *from++); } /*-/ /* General-purpose string copier */ /*-/ strcpy(to,from) char *to,*from; { while (*to++ = *from++); } /*-/ /* General-purpose string length test */ /*-/ strlen(string) char *string; { register int ix; for (ix=0; *string++; ++ix); return ix; } /*-/ /* Strip off *.PRT from pathname */ /*-/ trunname(string) char *string; { register int ix; for(ix=strlen(string); ix>=0; --ix) { if(string[ix] == 92) /* is it \? */ break; } string[ix+1]=0; } /*-/ /* Our code which replaces the system dumper */ /*-/ dumpctrl() { int ix,rez,result; static int palette[16]; static char *screen,workarea[1280]; /*-/ /* Grab screen resolution and base address */ /*-/ rez=Getrez(); screen=Physbase(); /*-/ /* Grab the system color palette */ /*-/ for(ix=0; ix<16; ++ix) palette[ix]=Setcolor(ix,-1); /*-/ /* Force monochrome palette to 000/777 */ /*-/ if(rez==2) { if(palette[0] & 0x0001) { palette[0]=0x0777; palette[1]=0x0000; } else { palette[0]=0x0000; palette[1]=0x0777; } } /*-/ /* Force alternate key mode to prtmode */ /*-/ Getshift(prtmode); /*-/ /* Initialize screen dumper code & printer */ /*-/ result=scrdump(0,rez,screen,palette,workarea); /*-/ /* Dump the screen if initialization was OK */ /*-/ if(result) scrdump(1,rez,screen,palette,workarea); /*-/ /* Return Alternate key mode to normal */ /*-/ Getshift(0); } /*-/ /* End of program! */ /*-/ *# * Epson JX-80 color screen dumper * * Written by Tom Hudson * * Copyright 1986, not to be sold * *# X .equ 66 ;screen X coordinate Y .equ 68 ;screen Y coordinate REZ .equ 70 ;resolution indicator PRTX .equ 72 ;printer X coordinate PRTY .equ 74 ;printer Y coordinate YTIME .equ 76 ;Y coord repeat count XTIME .equ 78 ;X coord repeat count COLOR .equ 80 ;color bit mask (yellow, magenta, cyan) SAVE .equ 82 ;temporary storage PHASE .equ 84 ;printer bit phase XMAX .equ 86 ;screen X limit MASK .equ 88 ;printer pin mask YCOUNT .equ 90 ;Y counter BLACK .equ 200 ;gray-scale table offset WHITE .equ 300 ;white-scale table offset .globl _dumper ;convenient label for dump routine .text _dumper: move.l a0,d0 ;save A0 move.l 16(a7),a0 ;point A0 at the work area start movem.l d0-a7,(a0) ;save all registers move.l 8(a7),a1 ;point A1 to screen base move.l 12(a7),a2 ;point A2 to palette start address tst.w 4(a7) ;initialize command (0)? bne process ;no, dump it! * reset & initialize printer * init: * BUILD BLACK PIXEL TABLE * move.w #%1,200(a0) ;Black... move.w #%1111011011110110,202(a0) move.w #%1011011010110110,204(a0) move.w #%1001011010010110,206(a0) move.w #%1000011010000110,208(a0) move.w #%10101010,210(a0) move.w #%1010,212(a0) move.w #%0,214(a0) ;...to white * BUILD WHITE PIXEL TABLE * move.w #%10,300(a0) ;low white... move.w #%1010,302(a0) move.w #%101010,304(a0) move.w #%10101010,306(a0) move.w #%100001101010,308(a0) move.w #%1000011010000110,310(a0) move.w #%1001011010000110,312(a0) move.w #%1001011010010110,314(a0) move.w #%1011011010010110,316(a0) move.w #%1011011010110110,318(a0) move.w #%1111011010110110,320(a0) move.w #%1111011011110110,322(a0) move.w #%1011110110,324(a0) move.w #%1011110111,326(a0) ;...to high white * set init string * fininit: bsr preset ;reset printer tst.w d0 ;reset successful? bmi error ;no! move.l #$1b410800,150(a0) ;reset, set linefeed to 8 dots move.l #3,d2 ;3 bytes in init string lea 150(a0),a3 ;point to init string bsr printit ;and print it! clr.l 150(a0) ;clear that portion of work area tst.w d0 ;was print OK? bpl exit ;yes! * exit w/error condition (0) * error: movem.l (a0),d0-a7 ;restore registers move.l d0,a0 ;restore old A0 clr.w d0 ;set error condition rts * exit the subroutine (no error) * exit: movem.l (a0),d0-a7 ;restore registers move.l d0,a0 ;restore old A0 move.w #1,d0 ;set OK condition rts * exit w/abort condition (2) * abort: movem.l (a0),d0-a7 ;restore registers move.l d0,a0 ;restore old A0 move.w #2,d0 ;set abort condition rts * process the pixels and send to printer * process: move.w 6(a7),REZ(a0) ;save resolution tst.w 6(a7) ;was it 0 (low)? beq lowvert ;yes! cmp.w #1,6(a7) ;was it 1 (medium)? beq medvert ;yes! bra abort ;can't dump hires with this dumper! * MEDIUM-REZ PROCESSOR * medvert: move.w #640,XMAX(a0) ;set X maximum bra ALLDUMP ;and dump it! * LOW-REZ PROCESSOR * lowvert: move.w #320,XMAX(a0) ;set X maximum ALLDUMP: clr.w Y(a0) ;start at Y=0 clr.w PRTY(a0) ;and printer Y=0 move.l #$80,MASK(a0) ;init pin mask * GET PIXEL * newpass: move.b #%100100,COLOR(a0) ;start with yellow pass nx0strt: bsr linestrt ;start off the print operation clr.w X(a0) ;set screen X coord to 0 clr.w PRTX(a0) ;set printer X coord to 0 nx0yel: tst.w REZ(a0) ;low-res? beq threex ;yes, that's three printer dots! move.w X(a0),d1 ;grab screen X and.w #1,d1 ;is is even? beq onex ;yes, that gets only 1 printer dot move.w #2,XTIME(a0) ;it's odd, make it 2 printer dots. bra doppix ;do convert on pixel onex: move.w #1,XTIME(a0) ;set up 1 printer dot bra doppix threex: move.w #3,XTIME(a0) ;set up 3 printer dots doppix: bsr procit ;process the pixel bmi error ;if error, return. addq.w #1,X(a0) ;increment screen X coord move.w X(a0),d1 ;get the X coord cmp.w XMAX(a0),d1 ;end of screen scan line? bne nx0yel ;nope, loop for more! move.b #$0D,150(a0) ;new color, send CR move.l #1,d2 ;1 byte to print lea 150(a0),a3 ;point to the CR bsr printit ;and print it! clr.l 150(a0) ;clear that part of the work area bsr pabchk ;check for abort (UNDO) tst.w d0 ;abort? beq NOabort ;no! bsr preset ;they bailed out, reset printer bra abort ;and exit w/abort condition NOabort: move.b COLOR(a0),d1 ;get color mask lsr.b #1,d1 ;shift right one bit move.b d1,COLOR(a0) ;and put back in the mask and.b #%111000,d1 ;done with all 3 colors? bne nx0strt ;no, loop for next color move.b #$0a,150(a0) ;new line, send LF move.l #1,d2 ;a LF is just 1 byte, lea 150(a0),a3 ;point to LF bsr printit ;and print it! clr.l 150(a0) ;clear that area addq.w #4,Y(a0) ;increment screen Y by 4 (4 lines per pass) add.w #8,PRTY(a0) ;add 8 to printer's Y (8 pins per pass) cmpi.w #200,Y(a0) ;end of screen? bmi newpass ;no! bsr preset ;all done, reset printer bra exit ;and exit! preset: move.w #$1b40,150(a0) ;set up printer reset codes move.l #2,d2 ;it's 2 bytes lea 150(a0),a3 ;point to string bsr printit ;reset printer! clr.l 150(a0) ;clean up print buffer rts ;and exit! linestrt: move.l #$1B72001B,150(a0) ;set up start of color set string cmpi.b #%100100,COLOR(a0) ;yellow pass? bne notyel ;no, try magenta move.b #$34,152(a0) ;it's yellow, set ribbon color bra setcolor ;and do it. notyel: cmpi.b #%010010,COLOR(a0) ;magenta? bne notmag ;no, it's cyan! move.b #$31,152(a0) ;set ribbon color to magenta bra setcolor ;and do it. notmag: move.b #$32,152(a0) ;set ribbon color to cyan! setcolor: move.l #$4CC00300,154(a0) ;set up end of string (dots per line = 960) move.l #7,d2 ;7 bytes to print lea 150(a0),a3 ;point to string bsr printit ;and print them! clr.l 150(a0) ;clear print area clr.l 154(a0) rts procit: move.w #4,YCOUNT(a0) ;do 4 screen pixels per head pass proc2: bsr getpixel ;get a pixel! move.w #2,YTIME(a0) ;each pixel repeated 2X (8 pins/4 pixels) bsr ppix ;convert pixel & send to printer bmi procx ;exit if error addq.w #1,Y(a0) ;next screen Y coord subq.w #1,YCOUNT(a0) ;1 less pixel to do bne proc2 ;loop if more addq.w #1,PRTX(a0) ;increment printer X count subq.w #4,Y(a0) ;reverse Y coord to top of print head sub.w #8,PRTY(a0) ;and printer Y as well subq.w #1,XTIME(a0) ;decrement X repeat counter bne procit ;loop if more clr.w d0 ;clear error flag procx: rts ;and return * * 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 getpixel: cmpi #200,Y(a0) ;Y beyond end of screen? bmi getit ;no, get the pixel move.b #-1,d0 ;return -1 for color rts ;and exit getit: tst.w REZ(a0) ;low rez? beq get0 ;yes, get low-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 * CHANGE COLOR TO PRINTER FORMAT * * AND PUT IN PRINT LINE * ppix: move.w PRTX(a0),d1 ;get printer X coordinate move.w PRTY(a0),d2 ;get printer Y coordinate and.w #3,d1 ;mask X to 0-3 and.w #3,d2 ;mask Y to 0-3 lsl.w #2,d2 ;multiply Y by 4 add.w d2,d1 ;add them for index of 0-15 for printer pixel table move.w d1,PHASE(a0) ;got printer black/white phase index, put in PHASE move.b d0,SAVE(a0) ;save the color for repeat use tst.b d0 ;is color >= 0? bpl d0OK ;yes! clr.w d0 ;no, change it to 0 d0OK: move.b d0,d1 ;duplicate color in D1 andi.l #$0ff,d1 ;mask it lsl.l #1,d1 ;multiply by 2 for index into palette add.l a2,d1 ;add to palette base address movea.l d1,a5 and put in an address register move.w (a5),d0 ;got color 000-777 move.w d0,d2 ;duplicate it... and.w #7,d2 ;get blue index move.w d0,d1 ;duplicate again... and.w #$0070,d1 ;get green index lsr.w #1,d1 ;shift the green index right 1 bit add.w d1,d2 ;and add to total move.w d0,d1 ;duplicate again!! and.w #$0700,d1 ;get red index lsr.w #2,d1 ;shift right 2 bits add.w d1,d2 ;now we have a color # of 0-511 bsr getcvals ;get color bit table addr in a5 move.w d0,d3 ;not AGAIN?? (gotta save it for next operation) move.b 0(a5,d2.w),d0 ;load color bits * calc color brightness total * move.w d3,d1 ;put color in D1 and.w #7,d1 ;mask blue brite move.w d3,d2 ;put color in D2 lsr.w #4,d2 ;divide by 4 and... and.w #7,d2 ;mask green brite add.w d2,d1 ;add to total brite lsr.w #8,d3 ;now shift color 8 bits right... and.w #7,d3 ;mask red brite add.w d3,d1 ;add to total brite tst.b d0 ;table color bits = %0 (gray scale)? beq grayit ;yes! cmp.w #7,d1 ;total brite < 7? bmi blakck ;yes, add some black! beq normal ;brightness = 7, it's a solid color! whitck: move.w PHASE(a0),d2 ;get printer pixel phase (0-15) sub.w #8,d1 ;decrement pixel brightness by 8 lsl.w d1 ;and multiply by 2 for index lea 0(a0,d1.w),a5 ;generate a table offset using brightness adda.l #WHITE,a5 ;index into WHITE table move.w (a5),d3 ;get white addition word btst.l d2,d3 ;and check bit indicated by PHASE bne nobitson ;if bit is on, make it white! bra normal ;otherwise, make it normal color grayit: and.l #$0FF,d1 ;mask in preparation for divide divu #3,d1 ;divide brightness by 3 move.w PHASE(a0),d2 ;get printer phase lsl.w d1 ;multiply brightness by 2 for index lea 0(a0,d1.w),a5 ;generate a table offset using brightness / 3 adda.l #BLACK,a5 ;index into BLACK table move.w (a5),d3 ;get black addition word btst.l d2,d3 ;check bit indicated by PHASE bne turnbitson ;if it's on, add black! bra nobitson ;otherwise, it's white! blakck: move.w PHASE(a0),d2 ;get printer pixel phase lsl.w d1 ;multiply brightness by 2 for index lea 0(a0,d1.w),a5 ;generate an offset using brightness adda.l #BLACK,a5 ;index into BLACK table move.w (a5),d3 ;grab black addition word btst.l d2,d3 ;if it's on, add black bne turnbitson ;otherwise, it's normal color normal: and.b COLOR(a0),d0 ;mask the table color with color pass bits (y, m or c) move.w PRTX(a0),d1 ;get printer X coord add.w PRTY(a0),d1 ;add printer Y coord and.w #1,d1 ;is it an even pixel? beq evenpix ;yes! * ODD pixel on printer, use color 2 lsr.b #3,d0 ;shift so color #2 is used bra orit ;and go put in printer byte evenpix: and.b #7,d0 ;use color #1 orit: tst.b d0 ;any bits on? beq nobitson ;no! turnbitson: tst.b SAVE(a0) ;is original pixel on screen? bmi nobitson ;no, leave white! move.l 150(a0),d0 ;get printer byte or.l MASK(a0),d0 ;OR on the appropriate bit move.l d0,150(a0) ;and put byte back nobitson: move.l MASK(a0),d2 ;get printer pin mask lsr.l d2 ;move to next pin move.l d2,MASK(a0) ;save mask tst.l d2 ;any more pins left? bne noprtyet ;yes! move.l #$80,MASK(a0) ;reset pin mask to top pin move.l #1,d2 ;1 byte to print lea 153(a0),a3 ;point to byte bsr printit ;and print the byte! bmi ppixout ;branch if error clr.l 150(a0) ;clear print work area noprtyet: addq.w #1,PRTY(a0) ;increment printer Y coordinate move.b SAVE(a0),d0 ;restore color to D0 subq.w #1,YTIME(a0) ;decrement Y repeat counter bne ppix ;loop back if more clr.w d0 ;zero D0 to report success ppixout: rts *, * Color table start -- do not add any code * * between GETCVALS and CVALUES! * *, getcvals: lea 4(pc),a5 ;point A5 at our color value table rts *? * The CVALUES table is a 512-byte table (one byte per color * * combination possible on the ST.) Each byte is made up of * * two color indicator bit groups. Bits 0-2 are termed * * color 1, and are used when the printer pixel X and Y * * coordinates add to an even value. Bits 3-5 are termed * * color 2, and are used when the printer pixel X and Y * * coordinates add to an odd value. The three bits in each * * color represent (from high bit to low bit) yellow, magenta * * and cyan. That is, 100 is yellow, 010 is magenta, 001 is * * cyan. These bits are combined to make: 011=blue, 101=green,* * 110=red, 111=black, 000=white. Gray scales are represented * * by 000, and are automatically shaded by the color routine. * *? cvalues: * 000-077 * .dc.b %0,%011001,%011001,%011001,%011001,%011001,%011001,%011001 .dc.b %101101,%001001,%011101,%011101,%011001,%011001,%011001,%011001 .dc.b %101101,%101011,%001001,%011101,%011101,%011001,%011001,%011001 .dc.b %101101,%101101,%101001,%001001,%001001,%011001,%011101,%011101 .dc.b %101101,%101101,%101011,%101001,%001001,%001001,%011101,%011101 .dc.b %101101,%101101,%101101,%101011,%101011,%001001,%011001,%011001 .dc.b %101101,%101101,%101011,%101011,%101011,%101011,%001001,%011001 .dc.b %101101,%101101,%101101,%101011,%101011,%101011,%101001,%001001 * 100-177 * .dc.b %110110,%010010,%011010,%011010,%011001,%011001,%011001,%011001 .dc.b %100100,%0,%011001,%011001,%011001,%011001,%011001,%011001 .dc.b %101100,%101101,%001001,%011001,%011001,%011001,%011001,%011001 .dc.b %101101,%101011,%101001,%001001,%011001,%011101,%011001,%011001 .dc.b %101101,%101101,%101011,%101001,%001001,%011001,%011101,%011001 .dc.b %101101,%101101,%101101,%101011,%101001,%001001,%011001,%011001 .dc.b %101101,%101101,%101101,%101011,%101011,%101001,%001001,%011001 .dc.b %101101,%101101,%101101,%101101,%101011,%101011,%101001,%001001 * 200-277 * .dc.b %110110,%110010,%010010,%011010,%011010,%011001,%011001,%011001 .dc.b %110100,%110110,%010010,%011010,%011010,%011001,%011001,%011001 .dc.b %100100,%100100,%0,%011001,%011001,%011001,%011001,%011001 .dc.b %100100,%100100,%100100,%001001,%011001,%011001,%011001,%011001 .dc.b %101100,%101100,%101101,%101001,%001001,%011001,%011001,%011001 .dc.b %101101,%101101,%101101,%101101,%101001,%001001,%011001,%011001 .dc.b %101101,%101101,%101101,%101101,%101101,%101001,%001001,%011001 .dc.b %101101,%101101,%101101,%101101,%101101,%101101,%101001,%001001 * 300-377 * .dc.b %110110,%110110,%110010,%010010,%011010,%011001,%011001,%011001 .dc.b %110110,%110010,%110010,%010010,%011010,%011010,%011001,%011001 .dc.b %110100,%110100,%110110,%010010,%011010,%011001,%011001,%011001 .dc.b %100100,%100100,%100100,%0,%011001,%011001,%011001,%011001 .dc.b %101100,%101100,%101100,%101001,%001001,%011001,%011001,%011001 .dc.b %101101,%101101,%101101,%101101,%101001,%001001,%011001,%011001 .dc.b %101101,%101101,%101101,%101101,%101011,%101001,%001001,%011001 .dc.b %101101,%101101,%101101,%101101,%101101,%101101,%101001,%001001 * 400-477 * .dc.b %110110,%110110,%110010,%110010,%010010,%011010,%011001,%011001 .dc.b %110110,%110110,%110110,%110010,%010010,%011010,%011001,%011001 .dc.b %110110,%110110,%110110,%110010,%010010,%011010,%011001,%011001 .dc.b %110100,%110100,%110110,%110110,%010010,%011010,%011010,%011001 .dc.b %100100,%100100,%100100,%100100,%0,%011001,%011001,%011001 .dc.b %101100,%101100,%101100,%101101,%101101,%001001,%011001,%011001 .dc.b %101101,%101101,%101101,%101011,%101011,%101001,%001001,%011001 .dc.b %101101,%101101,%101101,%101101,%101011,%101011,%101001,%001001 * 500-577 * .dc.b %110110,%110110,%110110,%110110,%110010,%010010,%011010,%011010 .dc.b %110110,%110110,%110110,%110110,%110010,%010010,%011010,%011010 .dc.b %110110,%110110,%110110,%110110,%110010,%010010,%011010,%011010 .dc.b %110100,%110100,%110110,%110110,%110010,%010010,%011010,%011010 .dc.b %110100,%110100,%110100,%110110,%110010,%010010,%011010,%011010 .dc.b %100100,%100100,%100100,%100100,%100100,%0,%011001,%011001 .dc.b %101100,%101100,%101100,%101100,%101101,%101001,%001001,%011001 .dc.b %101100,%101100,%101100,%101101,%101011,%101001,%101001,%001001 * 600-677 * .dc.b %110110,%110110,%110110,%110110,%110010,%110010,%010010,%011010 .dc.b %110110,%110110,%110110,%110110,%110010,%110010,%010010,%011010 .dc.b %110100,%110110,%110110,%110110,%110010,%110010,%010010,%011010 .dc.b %110100,%110100,%110100,%110110,%110010,%110010,%010010,%011010 .dc.b %110100,%110100,%110110,%110110,%110110,%110010,%010010,%011010 .dc.b %110100,%110100,%110100,%110100,%110100,%110110,%010010,%011010 .dc.b %100100,%100100,%100100,%100100,%100100,%100100,%0,%011001 .dc.b %101100,%101100,%101100,%101100,%101100,%101100,%101101,%001001 * 700-777 * .dc.b %110110,%110110,%110110,%110110,%110010,%110010,%110010,%010010 .dc.b %110110,%110110,%110110,%110110,%110010,%110010,%110010,%010010 .dc.b %110110,%110110,%110110,%110110,%110010,%110010,%110010,%010010 .dc.b %110110,%110110,%110110,%110110,%110010,%110010,%110010,%010010 .dc.b %110100,%110100,%110100,%110100,%110110,%110010,%110010,%010010 .dc.b %110100,%110100,%110100,%110100,%110100,%110110,%110010,%010010 .dc.b %110100,%110100,%110100,%110100,%110100,%110100,%110110,%010010 .dc.b %100100,%100100,%100100,%100100,%100100,%100100,%100100,%0 filler .ds.l 500 ;pad the end of the routine to be sure of 2000 bytes f as68 -l -u epson.s cp68 saver.c saver.i c068 saver.i saver.1 saver.2 saver.3 -f rm saver.i c168 saver.1 saver.2 saver.s rm saver.1 rm saver.2 as68 -l -u saver.s rm saver.s link68 saver.68k=apstart,saver,epson,osbind,vdibind,aesbind rm epson.o rm saver.o relmod saver.68k epson.prg rm saver.68k wait  /*+/ /* DEGAS(TM) Printer Driver Saver */ /* Written by Tom Hudson */ /* Copyright 1986, ANTIC Publishing */ /* Freeware, not to be sold */ /* )*/ /* Link with DEGAS printer driver object */ /* file and execute, specifying the name */ /* of the printer driver file (be sure */ /* to use a .PRT extension for the file! */ /*+/ #include extern dumper(); /* The printer driver code */ /* Be sure to use the label _dumper in your printer */ /* driver before the first instruction! */ int contrl[13]; /* Standard GEM bindings */ int intin[128]; int ptsin[128]; int intout[128]; int ptsout[128]; /*-/ /* Our miscellaneous form_alert strings */ /*-/ char saveOK[] = "[1][ |Printer driver written!| ][ OK ]"; char cantopen[] = "[3][ |Can't open driver file!| ][ Sorry ]"; char wrterr[] = "[3][ |Error writing file!| ][ Sorry ]"; /*)/ /* Start of file write code */ /*)/ main() { int handle,fresult,fbutton; long bcount; char defpath[64],workpath[80],filename[20]; /*-/ /* Initialize the application */ /*-/ appl_init(); /*-/ /* Build a pathname with a .PRT extension */ /*-/ defpath[0] = Dgetdrv() + 'A'; defpath[1] = ':'; Dgetpath(&defpath[2], 0); strcpy(workpath,defpath); strcat(workpath,"\\*.PRT"); filename[0]=0; /*-/ /* Use file selector to get the driver name */ /*-/ fresult=fsel_input(workpath,filename,&fbutton); /*-/ /* If filename was entered, write the file! */ /*-/ if(fresult>0 && fbutton==1) { trunname(workpath); strcat(workpath,filename); /*-/ /* Attempt to save the printer driver file */ /*-/ handle = Fcreate(workpath,0); if (handle >= 0) { bcount=Fwrite(handle,2000L,&dumper); Fclose(handle); if(bcount<2000L) form_alert(1,wrterr); else form_alert(1,saveOK); } else { form_alert(1,cantopen); } } } /*-/ /* General-utility string concatenator */ /*-/ strcat(to,from) char *to,*from; { while (*to) ++to; while (*to++ = *from++); } /*-/ /* General-purpose string copier */ /*-/ strcpy(to,from) char *to,*from; { while (*to++ = *from++); } /*-/ /* General-purpose string length test */ /*-/ strlen(string) char *string; { register int ix; for (ix=0; *string++; ++ix); return ix; } /*-/ /* Strip off *.PRT fzrom pathname */ /*-/ trunname(string) char *string; { register int ix; for(ix=strlen(string); ix>=0; --ix) { if(string[ix] == 92) /* is it \? */ break; } string[ix+1]=0; } /*-/ /* End of program! */ /*-/ u  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|F1| dtGdaGd2<J@j L @0<NuL @0<NuL @0<Nu1oFJogH og 1|V1|X1|Z1|\1|``>1|V1|X1|Z1|\1|``1|V1|X1|@Z1|\1|`1|D1|H1|J1|^|@1hXL!|CPdtGdak21|d1|Ba1hVN|$PakRhB2(BhZf1|Bap1hVN|PakRhB2(BhZf1|BaD1hVN| PaxkRhB2(BhZf2(J|g aJ@fRhJ1|HRh^2(^h`f 1|^`,ShLf$RhD2(Dh\f`b"<NU./ / //NV>?<NMN^$"$_"_ _N]Jk Sj0?<?<NMN^$"$_"_ _N]RSBf0<NuNU./ / //NV>?<NMN^J@g*NV>?<NMN^af0<$"$_"_ _N]Nu0<` hFg hFgRNU./ / //0(DP2(B4Iļ<)g0<`0<$"$_"_ _N]NuNU./ / ///0<6(DƼ2(B4I|6ļ2<iAg0<6)Ag|&$"$_"_ _N]NuNU./ / ///0<6(DƼ2(B4I|6ļ2<iAg0<6)Ag|6)Ag|6)Ag|&$"$_"_ _N]Nu2(H4(J||JB1AT@RҊ*A04|2|pIA2|IAa65 2|4J|BK|CJg&|kN|k^4(TQAIK,6fd`D¼4(TIK6ļƼfB`44(TIK6f*(P2(HhJ|g`<Jg (d(@@d(@ B@Jf|@tGdak1|dRhH(RShNf0<NuKNu       $- 6      $%- &$- 66 666    $$%- $%%- &&$- 666    $$%%- $$$%- $$$%- &&$$- 6666   $$$$%- $$$$%- $$$$%- &&$$%- &&&$%- 6  $$$$%%- $$$$%%- &$$$%%- &&&$%%- &&$$$%- &$- 6 $$$$%%%-$$$$%%%-$$$$%%%-$$$$%%%-&&&&$%%-&$%-&$-6?NV0  oH"o$o JofNV>?< NMN^ o@A1oF!|!|UU!|UU!|UU!|D!|!|"!|(A<g hFg|@`|@`JhFg|@`|@!|@Ad1| htGdaGd2<BSAfJ@j L @B@NuL @0<NuL @0<Nu(A<gJhFg< hFg`Bg?<NMN^$"$_"_ _N]RSBfB@NuNU./ / //NV>?<NMN^J@gNV>?<NMN^af0<$"$_"_ _N]NuB@`NU./ / //0(DP2(B4Iļ<)fB@`0<$"$_"_ _N]NuNU./ / ///B@6(DƼ2(B4I|6ļ2<iAg0<6)Ag|&$"$_"_ _N]NuNU./ / ///B@6(DƼ2(B4I|6ļ2<iAg0<6)Ag|6)Ag|6)Ag|&$"$_"_ _N]Nu| dtGdaNu!|L d1| $<&GdaGd2<BSAfNu!|Ld1| ($<GdaGd2<BSAfNuҊ*A04|2I|A2I|AļJK (A<f0(@-(@-(@-(@Nu5pRG|(@JhFg 2(B|gNu5pRG|(@5pRG|(@Nu0  oH"o$o JofNV>?< NMN^ o@A1oF!|!|UU!|UU!|UU!|D!|!|"!|(A<g og|@`|@`Jog|@`|@!|Q d!|T16h1|>lt GdaGd2<BSAfJ@j L @B@NuL @0<NuL @0<Nu(A<gJog6 og`8Jog ogvBhBIj1|Da(Ҋ*A Uwg (@`TShDj(@ A@Jf|@a0J@kXaJ@fdRhB hBfa`DBhBIj1|DaaZShDj(@ A@Jf|@aJ@ka6J@f RhB hBfa`BhBIj1|Da aShDj(@ A@Jf|@aJ@kaJ@fRhB h@BfaD`BhDIjBhBaҊ*A Uwg(@4(B|f`R4(B|fRRhB hBf(@ A@Jf|@a"J@kaNJ@f$RhD hDf|a`BhDIjBhBBGaaRhB hBf(@ A@Jf|@aJ@kaJ@fRhD hDfaT`BhDIjBhBaaRhB h@Bf(@ A@Jf|@afJ@k\aJ@fhRhD hDfa`H"<NU./ / //NVBW?<NMN^$"$_"_ _N]Jk Sj0Bg?<NMN^$"$_"_ _N]RSBfB@NuNU./ / //NV>?<NMN^J@g*NV>?<NMN^af0<$"$_"_ _N]NuB@`NU./ / //0(DP2(B4Iļ<)g0<`B@$"$_"_ _N]NuNU./ / ///B@6(DƼ2(B4I|6ļ2<iAg0<6)Ag|&$"$_"_ _N]NuNU./ / ///B@6(DƼ2(B4I|6ļ2<iAg0<6)Ag|6)Ag|6)Ag|&$"$_"_ _N]Nu!|ANd!|< htGdaNu!|S08d1|00h1| $<(GdaGd2<BSAfNu!|S09d1|60h1| *$<GdaGd2<BSAfNuҊ*A04|2I|A2I|AļJK (A<f0(@-(@-(@-(@Nu5pRG|(@JhFg 2(B|gNu5pRG|(@Nu5pRG|(@5pRG|(@Nu.  t ..  t MEMOPS S t CPRINTOUTC t @PRTSHELLBAT t MPRTSHELLC t PRTSHELLPRG t FILE ONE "t FILE TWO %t ILE ONE 't I:*I * MEMOPS.S - MC68000 Machine language cohort for a DRI C host * * whose sole function in life is the wholesale altering of memory * * Copyright 1986 Daniel Matejka )* * Feel free to use these things, but credit would be appreciated... * *I .globl _setmem .globl _movmem .text *I * setmem(addr,count,value) .* * char *addr; int count,value; (* * fills memory beginning at "addr" with "count" reps of "value" * *I * a0.l is "addr" * d0.w is "count" * d1.b is "value" _setmem: * load data from stack to appropriate registers * clr.l d0 clr.l d1 move.l 4(sp),a0 move.w 8(sp),d0 move.w 10(sp),d1 move.w d1,d2 * copy for future reference tst d0 * count is zero? beq fillend * if so, bail out * * d1 becomes the (byte) fill value repeated four times (long word) * lsl.l #8,d1 or.b d2,d1 lsl.l #8,d1 or.b d2,d t1 lsl.l #8,d1 or.b d2,d1 * * is destination address odd? if so, fix that * move.l a0,d2 btst #0,d2 beq lfinit move.b d1,(a0)+ * set first byte subq.w #1,d0 * * hokay, fill memory with long register value, count / 4 times * lfinit: move.l d0,d2 lsr #2,d0 * divide count by 4 bra lfs lfb: move.l d1,(a0)+ lfs: dbf d0,lfb * * now clean up the remaining fill (by the byte, count mod 4 times) * andi.w #3,d2 bra bfs bfb: move.b d1,(a0)+ bfs: dbf d2,bfb fillend: rts *I * movmem(source,destination,count) &* * char *source,*destination; ** * int count; 8* * movmem moves "count" bytes from "source" to "destination" * *I * a0 is "source" * a1 is "destination" * d0 is "count" _movmem: * transfer data from stack to appropriate registers * clr.l d0 move.l 4(sp),a0 move.l 8(sp),a1 move.w 12(sp),d0 tst d0 * is count zero? bne movbeg * if not, continue rts * * if destination > source, branch to routine which moves from high to low * movbeg: cmpa.l a0,a1 bhi revord * to reverse order routines * * here we are moving from low to high addresses * move.l a0,d1 btst #0,d1 * is source odd? beq nseven move.l a1,d1 btst #0,d1 * is destination odd? beq nmix * * source, destination both odd. make them both even * move.b (a0)+,(a1)+ subq.w #1,d0 bra nlm * * one is odd, the other even. sorry. do the move byte-by-byte * nmloop: move.b (a0)+,(a1)+ nmix: dbf d0,nmloop rts * * source is even. check destination for same * nseven: move.l a1,d1 btst #0,d1 bne nmix * odd destination * * move memory by 4-byte chunks, then clean up with 1-byte chunk routine * nlm: move.l d0,d1 andi.w #3,d0 * d0 mod 4 asr.w #2,d1 * d0 div 4 bra nls nlloop: move.l (a0)+,(a1)+ nls: dbf d1,nlloop bra nmix * finish up remaining move * * here we are doing things from high to low addresses. this is otherwise * the same as the low-to-high routine described above. * revord: adda.l d0,a0 adda.l d0,a1 * go to high end of move move.l a0,d1 btst #0,d1 * source even? beq rseven move.l a1,d1 btst #0,d1 * destination even? beq rmix move.b -(a0),-(a1) * both odd: move one byte subq.w #1,d0 bra rlm rmloop: move.b -(a0),-(a1) * one odd, one even rmix: dbf d0,rmloop rts rseven: move.l a1,d1 btst #0,d1 * destination odd? bne rmix rlm: move.l d0,d1 andi.w #3,d0 lsr.w #2,d1 bra rls rlloop: move.l -(a0),-(a1) * both even rls: dbf d1,rlloop bra rmix G/*F/ /* PRINTOUT.C - Unit responsible for Printing Files */ /* 20 Mar 86 :*/ /* Copyright 1986 Daniel Matejka &*/ /* Feel free to use this (it's been done before), */ /* but credit would be appreciated... !*/ /*F/ /* Procedures of interest are: startprint(), endprint(), and printstr(). startprint() initializes whatever needs to be initialized for the print session. endprint() reverses whatever startprint() does that needs to be reversed. printstr() takes a string and shoves it onto the output device. */ #include #include #define USEMEMOPS 1 /* use the Assembly language unit MEMOPS */ #define PAGELENGTH 58 /* # lines to print before form feed */ #define PAGEWIDTH 80 /* # of columns across page of printer */ static int oktocontinue, /* human flagged a stop */ toprinter, /* destination */ pagewidth, /* number of characters across page */ curline, /* current line number, for pagination */ curcol, /* current column number, for line wrap */ dofff, /* do form feed flag */ pbindex, /* index in printer buffer */ scpixel, /* screen (vertical) location */ window, /* display window handle */ windrect[4], /* window work area position and size */ scrollrect[4], /* subset of windrect[] for scrolling */ *scrbase; /* screen memory location */ static char *pagehdr[2], /* page header */ *prnbuffer; /* (screen) printer buffer */ extern int schandle, /* screen handle from v_opnvwk() */ cellwidth, cellheight, /* current font cell size */ ptsin[]; /* allocated by main unit for GEM */ /*H/ /* Some utility routines useful to the point of being necessary */ /*H/ /* C versions of the Assembly procedures in MEMOPS.S */ #if USEMEMOPS == 0 /* set memory to some byte value * / setmem(addr,count,val) register char *addr; register int count,val; { while (count--) *addr++ = val; } /* end setmem */ /* move memory from one location to another * / movmem(source,dest,count) register char *source,*dest; register int count; { if (source > dest) while (count--) *dest++ = *source++; else { source += count; dest += count; while (count--) *--dest = *--source; } } /* end movmem */ #endif /* return string length * / int strlen(s) char *s; { register char *seeker; seeker = s; while (*seeker++); return (int) (seeker-s) - 1; } /* end strlen */ /* copy second string into first string * / strcpy(a,b) register char *a,*b; { while (*a++ = *b++); } /* end strcpy */ /*H/ /* Printing Routines */ /*H/ /* scroll the active window * / scroll(dy) int dy; { register int linesize, /* number of words in a screen line */ linewidth, /* number of BYTES in a scrollrect[] line */ linestart, /* beginning of scrollrect[] line */ ctr; ctr = 2 - Getrez(); linesize = ctr == 0 ? 40 : 80; /* 40 words high, 80 low/med */ linewidth = (scrollrect[2] >> 3) << ctr; linestart = (scrollrect[0] >> 4) << ctr; v_hide_c(schandle);  /* scroll up dy pixels */ for (ctr = scrollrect[1]+dy; ctr < scrollrect[1]+scrollrect[3]; ctr++) movmem(scrbase + linesize*ctr + linestart, scrbase + linesize*(ctr-dy) + linestart, linewidth); /* clear duplicate area at bottom */ ptsin[0] = scrollrect[0]; ptsin[1] = scrollrect[1] + scrollrect[3]; ptsin[2] = ptsin[0] + scrollrect[2] - 1; ptsin[3] = ptsin[1] - dy; vr_recfl(schandle,ptsin); v_show_c(schandle,1); } /* end scroll */ /* print a status line (screen reports) * / static statusline(which) int which; { char msg[60]; if (!which) { /* mouse is out there causing trouble */ v_hide_c(schandle); /* take mouse back */ wind_update(BEG_MCTRL); } /* erase unscrolled area at window bottom */ ptsin[0] = scrollrect[0] + 1; ptsin[2] = scrollrect[0] + scrollrect[2] - 1; ptsin[1] = scrollrect[1] + scrollrect[3]; ptsin[3] = windrect[1] + windrect[3] - 1; vr_recfl(schandle,ptsin); if (which) strcpy(msg,"any key continues ..."); else strcpy(msg," pauses, quits"); v_gtext(schandle, scrollrect[0],scrollrect[1] + scrollrect[3] + 3*cellheight/2, msg); if (which) { wind_update(END_MCTRL); /* give mouse back */ v_show_c(schandle,0); evnt_keybd(); /* hang out */ } } /* end statusline */ /* start a new page * / static newpage() { curline = 0; /* reset line counter */ if (toprinter) { if (*pagehdr[0]) { /* print first line of page header */ printstr(pagehdr[0]); printchar('\r'); printchar('\n'); } if (*pagehdr[1]) /* print second line */ printstr(pagehdr[1]); printchar('\r'); printchar('\n'); printchar('\n'); } else { if (*pagehdr[0]) /* likewise */ v_gtext(schandle,scrollrect[0],scrollrect[1]-2*cellheight, pagehdr[0]); if (*pagehdr[1]) v_gtext(schandle,scrollrect[0],scrollrect[1]-cellheight, pagehdr[1]); } } /* end newpage */ /* is printer on-line and awake? * / static int prstatus() { evnt_timer(50,0); /* Atari needs some time to think: 1/20th second */ return (int) gemdos(0x11); } /* end prstatus */ /* did human ask us to pause or stop? * / static checkeydown() { int key; key = 0; if ((int) gemdos(0xB) != 0) { /* key has been pressed */ key = evnt_keybd() & 0xFF; /* eat it */ switch (key) { case ' ' : if (toprinter) form_alert(1,"[1][Printing Paused][Continue]"); else { statusline(1); /* demand another */ statusline(0); } break; case '\r' : oktocontinue = 0; /* stop */ } /* end switch (key) */ } /* end key pressed */ } /* end checkeydown */ /* print a character * / static printchar(c) int c; { int ctr,delay; if (dofff && c != '\n') { /* form feed flag set: do it first */ dofff = 0; newpage(); } if (c == '\n' && curline >= PAGELENGTH || c == '\0' && curline >= PAGELENGTH+2) /* skip perf */ c = '\f'; if (c == '\0') /* '\0' means newline, but delay skip perf */ c = '\n'; if (c == '\n' && toprinter) curline++; if (c == '\f') { curline = 0; /* because '\n' is called repeatedly */ dofff = 1; } if (toprinter){ gemdos(0x05,c); /* send character to printer */ if (c == '\r') { curcol = 0; /* new line: reset line counter */ checkeydown(); /* check for instructions */ } else if (c != '\n' && c != '\f') curcol++; } else /* to screen */ switch (c) { case '\n' : scpixel += cellheight; if (scpixel > scrollrect[1] + scrollrect[3]) { scpixel -= cellheight; scroll(cellheight); } break; case '\f' : /* page length < 10 go boom, here */ for (ctr = 0; ctr < 10; ctr++) printchar('\n'); break; case '\r' : prnbuffer[pbindex] = 0; pbindex = 0; curcol = 0; v_gtext(schandle,scrollrect[0],scpixel,prnbuffer); /* wait a rbit, just to slow down the screen printout. evnt_timer() seems to eat the typeahead */ for (delay = 0; delay < 1000; delay++) checkeydown(); break; default : prnbuffer[pbindex++] = c; curcol++; } /* end switch (c) */ } /* end printchar */ /* output a string, with wordwrap * / printstr(ptr) char *ptr; { register char *seeker; /* looks for word boundaries */ char *rmargin; /* don't print past this ... */ while (oktocontinue && *ptr) { /* look for next word end or string end */ rmargin = ptr + (pagewidth-curcol); seeker = ptr; if (*ptr == ' ' || *ptr == '\r') seeker++; while (*seeker != ' ' && *seeker != 0 && *seeker != '\r') seeker++; /* if word fits on line, or is too long to fit comfortably */ if (seeker < rmargin || seeker - ptr > pagewidth/2) while (ptr < seeker && ptr < rmargin) printchar(*ptr++); /* go to next line, if necessary */ if (curcol + (seeker - ptr) >= pagewidth) { printchar('\r'); printchar('\0'); while (*ptr == ' ') ptr++; } } /* end while */ } /* end printstr */ /* initialize a print session * / static startprint() { toprinter = form_alert(1,"[1][Send display to][Screen|Printer]") == 2; oktocontinue = 1; if (toprinter) while (oktocontinue && !prstatus()) oktocontinue = 1 == form_alert(1, "[3][Turn on the printer][OK|Cancel]"); else { if (!openwind()) { oktocontinue = 0; form_alert(1,"[3][Please close|some windows.][ OK ]"); /* zero these pointers so endprint()'s free() won't choke */ prnbuffer = 0; pagehdr[0] = 0; pagehdr[1] = 0; return; } clrwindow(); statusline(0); } if (toprinter) pagewidth = PAGEWIDTH; else pagewidth = scrollrect[2]/cellwidth; if (pagewidth & 1) /* make it even */ pagewidth++; prnbuffer = Malloc((long) (pagewidth+2)); pagehdr[0] = Malloc((long) (pagewidth+2)); pagehdr[1] = Malloc((long) (pagewidth+2)); curline = 0; curcol = 0; pbindex = 0; dofff = 1; scpixel = scrollrect[1] + cellheight - 1; scrbase = (int *) xbios(3); } /* end startprint */ /* end a print session * / static endprint() { if (toprinter) { if (prstatus()) /* was printer-turn-on cancelled? */ printchar('\f'); } else { statusline(1); wind_close(window); wind_delete(window); } if (pagehdr[1]) Mfree(pagehdr[1]); if (pagehdr[0]) Mfree(pagehdr[0]); if (prnbuffer) Mfree(prnbuffer); } /* endprint */ /* center a pageheader * / centerhdr(hdr) char *hdr; { int hdrlen,hdroff; hdrlen = strlen(hdr); hdroff = (pagewidth-hdrlen)/2; if (hdroff > 0) { movmem(hdr,hdr+hdroff,hdrlen+1); setmem(hdr,hdroff,' '); } } /* end centerhdr */ /*H/ /* Dealing with Windows */ /*H/ /* clear the display window * / clrwindow() { v_hide_c(schandle); ptsin[0] = windrect[0]; ptsin[1] = windrect[1]; ptsin[2] = windrect[0]+windrect[2]-1; ptsin[3] = windrect[1]+windrect[3]-1; vr_recfl(schandle,ptsin); v_show_c(schandle,1); } /* end clrwindow */ /* open the display window * / /* Value returned is nonzero iff it worked */ int openwind() { int wbx,wby,wbw,wbh, /* window border size and position */ algn; /* alignment guide */ wind_get(0,WF_WORKXYWH,&wbx,&wby,&wbw,&wbh); /* desktop window size */ /* use something less than the whole screen for the display window */ wbh /= 2; wby += wbh/2; wbw = 4*wbw/5; wbx += wbw/10; wind_calc(WC_WORK,NAME,wbx,wby,wbw,wbh, &windrect[0],&windrect[1],&windrect[2],&windrect[3]); window = wind_create(NAME,wbx,wby,wbw,wbh); if (window < 0)  * return 0; wind_set(window,WF_NAME," See the file... "); wind_open(window,wbx,wby,wbw,wbh); /* set up scroll area, which is subset of window on a word boundary */ movmem(windrect,scrollrect,4*sizeof(int)); /* allow some space for unscrolled lines on top and bottom */ scrollrect[1] += 3*cellheight; /* three on top */ scrollrect[3] -= 5*cellheight; /* and two on bottom */ scrollrect[3] = cellheight*(scrollrect[3]/cellheight); /* align scrollrect[] on a word boundary */ algn = scrollrect[0] & 0xF; /* is it already? */ if (algn) { /* No, adjust scroll area */ scrollrect[0] = (scrollrect[0] + 0x10) & ~0xF; scrollrect[2] = (scrollrect[2] + algn - 0x10) & ~0xF; } else scrollrect[2] &= ~0xF; return 1; } /* end openwind */ /*H/ /* The Driver Routine */ /*H/ /* read and display a file * / showfile(fname) char *fname; { int fhandle, /* file TOS handle */ readlen, /* number of bytes to read */ actlen; /* number of bytes actually read */ long flength, /* number of bytes in file */ fpos; /* current position */ char *buffer; /* read/print buffer */ fhandle = Fopen(fname,0); if (fhandle < 0) { form_alert(1,"[1][That file doesn't exist.][ Fool ]"); return; } flength = Fseek(0L,fhandle,2); /* inquire file length */ Fseek(0L,fhandle,0); /* back to the beginning */ buffer = Malloc(514L); /* one block + space needed by printstr() */ startprint(); fpos = 0L; strcpy(pagehdr[0],"Some Sort of"); strcpy(pagehdr[1],"Header"); centerhdr(pagehdr[0]); centerhdr(pagehdr[1]); while (oktocontinue) { readlen = flength-fpos > 512 ? 512 : flength-fpos; if (readlen > 0) { actlen = Fread(fhandle,(long) readlen,buffer); fpos += actlen; buffer[actlen] = 0; printstr(buffer); if (actlen != readlen) { form_alert(1,"[3][File is damaged][OK|Not OK]"); oktocontinue = 0; } } else oktocontinue = 0; } endprint(); Mfree(buffer); Fclose(fhandle); } /* end showfile */ static char copyright[] = { "(C) 1986 by Daniel Matejka " }; |as68 -l -u memops.s cp68 printout.c printout.i c068 printout.i printout.1 printout.2 printout.3 -f rm printout.i c168 printout.1 printout.2 printout.s rm printout.1 rm printout.2 as68 -l -u printout.s rm printout.s cp68 prtshell.c prtshell.i c068 prtshell.i prtshell.1 prtshell.2 prtshell.3 -f rm prtshell.i c168 prtshell.1 prtshell.2 prtshell.s rm prtshell.1 rm prtshell.2 as68 -l -u prtshell.s rm prtshell.s link68 prtshell.68k=apstart,prtshell,printout,memops,osbind,vdibind,aesbind rm memops.o rm printout.o rm prtshell.o relmod prtshell rm prtshell.68k wait /*@/ /* PRTSHELL.C - Driver Shell for PRINTOUT.C */ /* Copyright 1986 Daniel Matejka */ /*@/ #include #include int contrl[12], intin[128], intout[128], ptsin[128], ptsout[128], /* these five variables to satisfy GEM gluttony */ message[8], /* GEM message pipe */ schandle, /* screen (workstation) handle */ cellheight, cellwidth, /* character size */ colors, /* number of colors supported by the screen */ scrxmax, scrymax, /* screen size */ trash; /* for those not too useful returns ... */ /* Menu and Item numbers */ #define DESKMENU 3 #define HELPMENU 4 #define QUIT 16 #define FIRSTHELP 18 /* (the menu) * / OBJECT menudata[] = { /* menu owner */ -1, 1, 5, G_IBOX, NONE, NORMAL, 0x0L,16,0,240,64, /* titles parent and other miscellaneous garbage */ 5, 2, 2, G_BOX, NONE, NORMAL, 0x1100L,0,0,96,11, 1, 3, 4, G_IBOX, NONE, NORMAL, 0x0L,0,0,96,11, /* menu titles */ 4, -1, -1, G_TITLE, NONE, NORMAL," Desk ",0,0,48,11, 2, -1, -1, G_TITLE, NONE, NORMAL," Help",48,0,48,11, /* items parent */ 0, 6, 15, G_IBOX, NONE, NORMAL, 0x0L,0,11,432,64, /* desk menu */ 15, 7, 14, G_BOX, NONE, NORMAL, 0xFF1100L,0,0,160,64, 8, -1, -1, G_STRING, NONE, NORMAL," About Printout", 0, 0,160,8, 9, -1, -1, G_STRING, NONE, DISABLED,"-",0, 8,160,8, 10, -1, -1, G_STRING, NONE, NORMAL,"", 0,16,160,8, 11, -1, -1, G_STRING, NONE, NORMAL,"", 0,24,160,8, 12, -1, -1, G_STRING, NONE, NORMAL,"", 0,32,160,8, 13, -1, -1, G_STRING, NONE, NORMAL,"", 0,40,160,8, 14, -1, -1, G_STRING, NONE, NORMAL,"", 0,48,160,8, 6, -1, -1, G_STRING, NONE, NORMAL,"", 0,56,160,8, /* combination file/help menu */ 5, 16, 19, G_BOX, NONE, NORMAL, 0xFF1100L, 48, 0,192,32, 17, -1, -1, G_STRING,NONE, NORMAL," (Quit)", 0, 0,192,8, 18, -1, -1, G_STRING,NONE,DISABLED,"-",0, 8,192,8, 19, -1, -1, G_STRING,NONE, NORMAL," About Something", 0,16,192,8, 15, -1, -1, G_STRING,LASTOB, NORMAL," About Something Else", 0,24,192,8, }; /* startup up the GEM workstation * / initialize() { int ctr; /* initialize GEM virtual workstation */ appl_init(); schandle = graf_handle(&cellwidth,&cellheight,&trash,&trash); for (ctr = 0; ctr < 10; ctr++) intin[ctr] = 1; intin[10] = 2; v_opnvwk(intin,&schandle,intout); scrxmax = intout[0]; scrymax = intout[1]; colors = intout[13]; /* set some fill parameters: this could be done in v_opnvwk(), but I find it somewhat less cryptic here, myself */ vsf_interior(schandle,0); /* so we really know where text is going */ vst_alignment(schandle,0,3,&trash,&trash); /* adjust menu for high resolution screen (text is double height) */ if (colors == 2) { /* black & white screen */ ctr = 0; do { menudata[ctr].ob_y *= 2; menudata[ctr].ob_height *= 2; } while (!(menudata[ctr++].ob_flags & LASTOB)); } /* clear menu bar, then draw menu bar */ v_hide_c(schandle); ptsin[0] = 0; ptsin[1] = 0; ptsin[2] = scrxmax; ptsin[3] = menudata[1].ob_height - 1; vr_recfl(schandle,ptsin); menu_bar(menudata,1); /* initialize mouse */ graf_mouse(0,0); v_show_c(schandle,0); } /* end initialize */ /* handle menu selections by human * / int menuselect(menu,item) int menu,item; { static char *fnames[] = { /* list of file names */ "file.one", "file.two", "etc" }; int tuesday = 1; switch (menu) { case DESKMENU : form_alert(1, "[1][PRINTOUT:|Read & Display Files| |(C) 1986 Daniel Matejka][OK|Not OK]"); break; case HELPMENU : if (item == QUIT) tuesday = 0; else showfile(fnames[item-FIRSTHELP]); } /* end switch(menu) */ menu_tnormal(menudata,menu,1); return tuesday; } /* end menuselect */ /* handle window events * / int dowindows() { if (message[0] == MN_SELECTED) /* just in case */ return menuselect(message[3],message[4]); return 1; } /* end dowindows */ /* the program * / main() { /* open the GEM workstation */ initialize(); do { /* for the life of the program */ evnt_multi(MU_MESAG, /* just window messages */ 0,1,1, /* leftmost button */ 0,0,0,0,0, /* ignore mouse movement */ 0,0,0,0,0, /* continue doing so */ message, /* GEM message pipe address */ 0,0, /* no timer events */ &trash,&trash, /* mouse position */ &trash, /* mouse button status */ &trash, /* special keys status */ &trash, /* keyboard events */ &trash); /* number of button clicks */ /* at this point we of course have a window message */ } while (dowindows()); /* close the GEM workstation and exit */ v_clsvwk(schandle); appl_exit(); } /* end main */ &`Tx *O.| *m - ЭЭм// ??<JNA N/<NA"/0<NBNuNVN4."/<"/<%/<#N 3%Bn`0n!0Rn n m3!.."/<%/<!N8P3"%3"%3"6%BW?9%NT."/<"?<Bg?9%Nd y%fNBn0.м @0.м @0. @"|B@00| RnJ@g>%NBy#FBy#H3%#J09S@3#L.#F?9%NT>/<N@XBWBgNTBW?9%N0TN^NuNV=|0.`@.6?<NT`8 n fBn`0n "|.N ` |g|g>?./<Nb\0.N^NuNV y #6f>#>?9#%NxNN^NuNVH*nJf S@JL N^NuNVH *n(n fJL0N^NuNVHx>NH@JDfp(`pP><9 F0f:9 E0e>%N89 n`B>02n@H2AHЁй /0@H2AHЁй /NPRD09 y @m3 #F09 y 3#H09#Fy S@3#J09#Hn3#L.#F?9%NT>?9%N0TJLN^NuNVJnf>%N>N09 R@3#F09 y S@3#J09 y 3#H09 y S@3#L.#F?9%NTJng./aNBW?9%N0TNN^NuNVBy Jy gR y Jg. a> a0> a( y Jg . a> a > a> a`f y Jg*. ?9 09%@W?9 ?9%N\ y Jg(. ?9 09%ƑW?9 ?9%N\N^NuNVBW?<2NT>NhN^NuNVBn> NhJgTN|=@0.`4Jy g.?<NT`>aBWa`By ` | g| gN^NuNVJy g n g By a n f y: lJnf y< m=| Jnf=|  n fJy gRy n fBy 3 Jy g>>?<NhT n f By a` n g n gRy `0.`09%y 09 y y l09%Ƒy >%a|`Bn` > aRn n m` y 2y BBy By . ?9 ?9 ?9%N\Bn`a*Rn nm`:0.2y Ry Ry `| g.| g`| gv`N^NuNVH`09 Ԑy HЮ-@*n n  g n  fR`R  g Jg  fe 29 HHo$` nH>aRc .e09 H" Ё0y ԰m> aBWa`R n  gJy g nJf2JL N^NuNV.?<NT|gB@`p3 3 Jy g8`$.?<NT|gB@`p3 Jy ganJ@g`@axJ@f.By .9?<NTB B B `aBWaFJy g 3P `09 H#3 9 gRy 09 T@H.?<HNhT# 09 T@H.?<HNhT# 09 T@H.?<HNhT# By By By 3 09 y%S@3 >NH# N^NuNVJy gaFJ@g> a` >aN> N> NJ g. ?<INhTJ g. ?<INhTJ g. ?<INhTN^NuNV.a=@09 ԐnH=@Jno4>RW .2.HЁ//.NP> ?./.Nt\N^NuNV>%N3 #F3 #H09 y S@3#J09 y S@3#L.#F?9%NT>?9%N0TN^NuNV.Q/]/Y/U?<BgN40.H=@0.Hn0.@H=@0.H n. /< /< /< ?.?.?.?.?<?<N>?.?.?.?<NP3 Jy lB@`._?<?9 NX>?.?.?.?9 NP>/< /< NP09%y 09%y 09 H%%3 09 |=@Jng.09 ||3 09 n||3 `y pN^NuNVBW/.?<=Nh\=@Jnl.q?<NT`H>?.B?<BNhP-@BW?.B?<BNhP.?<HNhT-@aB./9 aX./9 aX. a. a` .o <` .=@Jno`.0n/?.?<?NhP=@0.HѮ n2nB.aj0.ng.?<NTBy `By Jy fha.?<INhT>?<>NhTN^NuBB o0/2/ 4J@g0ቂቂቂ$gS@$H` QB`QNuB o"o0/ J@fNub8"g" gS@`QNu" f"@A`"Q`"g" g S@` QNu" f"@I`# Q`#!NN/9!Nu#!NM/9!Nu#!NA/9!NuNV3e%By%By%3%NN^NuNV3 #F3 #HBn nH|2n!2RRnJ@f3%3%Sn3%3%NN^NuNV3{%By%By%3%NN^NuNV#! #! .мZ#!3d%By%3 % n 3%N n 0%#!! #"!#$F!##F!N^NuNV# !3r%3%By%3%N##F!N^NuNV3 !3%By%3%3%N09"N^NuNV3 !3z%By%3%3%NN^NuNV3 !3 !3'%By%3%3%N n0" n0"N^Nu#%!"<!psNBNuNV3%d0.|HмT-@=|` nH2n%d2RRn nm.%N>B@09%N^NuNV#%d##%F#"#%l#&#%#*#%#.#%#2##%> aF3%%pN^NuNV>a*pN^NuNV>NN^NuNV3%l3 %n>NN^NuNV3%l3 %n3 %p3%r3%t3%v3%x3%z3%|3%~3%3%3 %3"%#$%3(%3*%>N n,0% n00% n40% n80% n<0% n@0%B@09%N^NuNV3%l# %>4NN^NuNV>MN n0% n 0% n0% n0%B@09%N^NuNV3%l# %>NNN^NuNV#%3 %l>NN^NuNV#%3 %l3%n>!NN^NuNV3%l3 %n3 %p3%r3%t>dNN^NuNV3%l3 %n3 %p3%r3%t>eNN^NuNV3%l>fNN^NuNV3%l>gNN^NuNV3%l3 %n>hN n 0% n0% n0% n0%B@09%N^NuNV3%l3 %n3 %p3%r3%t3%v>iNN^NuNV3%l>kNN^NuNV3%l3 %n3 %p3%r3%t3%v>lN n0% n0% n0% n 0%B@09%N^Nu    - @`  `  0  00  @@      (080    )2 Desk Help About Printout- (Quit)- About Something About Something Elsefile.onefile.twoetc[1][PRINTOUT:|Read & Display Files| |(C) 1986 Daniel Matejka][OK|Not OK](C) 1986 by Daniel Matejka any key continues ... pauses, quits[1][Printing Paused][Continue][1][Send display to][Screen|Printer][3][Turn on the printer][OK|Cancel][3][Please close|some windows.][ OK ] See the file... [1][That file doesn't exist.][ Fool ]Some Sort ofHeader[3][File is damaged][OK|Not OK].     $  (X $       $      ", $2J6(     "   2 &F         J4      &               H0  If you can see this, you must be printing the contents of a file named, surprisingly enough, file.one. If you were looking for wit or humor, please realize that it's 4:00 in the morning; worse than that in Hawaii. The contents of FILE.TWO look like this: *I * MEMOPS.S - MC68000 Machine language cohort for a DRI C host * * whose sole function in life is the wholesale altering of memory * * Copyright 1986 by Daniel Matejka &* *I .globl _setmem .globl _movmem .text unexpected end of file on line 2,000,000 .  t. ..  t. DEBUG C 9t TEXTDEMOBAT TXDEMO RSC St @X /*@/ /* debug.c -- Debugging routines for GEM applications */ /* by Corey Cole, Visionary Systems, ppn 76224,66 */ /* Credit appreciated if you use this. */ /* Copyright 1986 ANTIC Publishing */ /*@/ #include "portab.h" /* portability macros */ #include "machine.h" /* machine depndnt conv */ #include "obdefs.h" /* object definitions */ #include "gembind.h" /* gem binding structs */ #define DEBUGOFF 4 #define DEBUGPART 28 #define DEBUGLINES 5 #define DEBUGLEN (DEBUGPART * DEBUGLINES) char big_buf[DEBUGLEN + 2]; /* General debug buffer */ static char debugger[] = "[1][1234567890123456789012345678|\ 1234567890123456789012345678|1234567890123456789012345678|\ 1234567890123456789012345678|1234567890123456789012345678][ Continue ]"; debug(dbstring) /* Print a debug message */ char *dbstring; { int len, ctr; char *foo, *foo2; len = LSTRLEN(dbstring); if (len > DEBUGLEN) len = DEBUGLEN; foo = (char *) debugger + DEBUGOFF; for (ctr = 0; ctr < DEBUGLEN; ctr += DEBUGPART) { if (len > DEBUGPART) LBCOPY(ADDR(foo), ADDR(dbstring), DEBUGPART); else { for (foo2 = foo; foo2 < foo + DEBUGPART; ++foo2) *foo2 = ' '; if (len > 0) LBCOPY(ADDR(foo), ADDR(dbstring), len); } if (ctr != DEBUGLEN - DEBUGPART) foo[DEBUGPART] = '|'; foo += DEBUGPART + 1; dbstring += DEBUGPART; len -= DEBUGPART; } form_alert(1, debugger); } /* * xprintf -- Simplified version of "sprintf" -- allows up to 9 numeric * arguments, always prints them in hex. Only formatting codes * allowed are "%x" (hexadecimal word), "%d" (decimal word), and * "%%" (literal '%'). Any other letter following a '%' is treated * as though it were an 'x'. Other characters are passed through * unchanged (feel free to add other capabilities as you need them). */ char * xprintf(sformat, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) char *sformat; int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9; { int argptr[9], argindex; char *foobuf; argindex = 0; argptr[0] = arg1; argptr[1] = arg2; argptr[2] = arg3; argptr[3] = arg4; argptr[4] = arg5; argptr[5] = arg6; argptr[6] = arg7; argptr[7] = arg8; argptr[8] = arg9; for (foobuf = big_buf; *sformat != '\0'; ++sformat) { if (*sformat != '%') *foobuf++ = *sformat; else { if (*++sformat == '%') *foobuf++ = *sformat; else if ((*sformat | 0x20) == 'd') { foobuf += decnum(foobuf, argptr[argindex++]); } else { foobuf += hexnum(foobuf, argptr[argindex++]); } } } *foobuf = '\0'; /* Append NULL terminator to string */ return (big_buf); } int decnum(tostr, val) /* Places ASCII equiv of dec val in tostr */ char *tostr; int val; { int digits, num; char decchar(), *ptr; digits = 5; if (val < 1000) digits = 3; for (ptr = tostr + digits - 1; ptr >= tostr; --ptr) { if (val == 0) { if (ptr == (tostr + digits - 1)) *ptr = '0'; else *ptr = ' '; /* Leading space */ } else { num = val % 10; val /= 10; *ptr = '0' + num; } } return (digits); } int hexnum(tostr, val) /* Places ASCII equiv of hex val in tostr */ char *tostr; int val; { int digits; char hexchar(), *ptr; digits = 4; for (ptr = tostr + digits - 1; ptr >= tostr; --ptr) { *ptr = hexchar(val); /* Bottom four bits */ val = val >> 4; /* Next four bits */ } return (digits); } char hexchar(val) /* Returns ASCII equiv of hex digit, or '-' */ int val; { char charcode; val &= 0xF; if (val >= 16) charcode = '-'; else if (val >= 10) charcode = val - 10 + 'A'; else charcode = val + '0'; return (charcode); } #if MC68K /* Note that LBCOPY and LWCOPY don't really return BYTE and WORD values. They are declared this way to match the EXTERN declarations from MACHINE.H, thus avoiding annoying compilation errors. */ BYTE LBCOPY(dest, src, len) /* Copy "len" bytes from *src into *dest */ char *dest; register char *src; register int len; { register char *p = dest; if ( xdest == src) return; else if (dest < src) { /* Copying backwards */ for ( ; len > 0; --len) *p++ = *src++; } else { /* Forward copy, so start at end and work back */ src += len; p += len; for ( ; len > 0; --len) *--p = *--src; } } WORD LWCOPY(dest, src, len) /* Copy "len" bytes from *src into *dest */ int *dest; register int *src; register int len; { register int *p = dest; if (dest == src) return; else if (dest < src) { /* Copying backwards */ for ( ; len > 0; --len) *p++ = *src++; } else { /* Forward copy, so start at end and work back */ src += len; p += len; for ( ; len > 0; --len) *--p = *--src; } } WORD LSTRLEN(s) /* String length */ char *s; { register char *p = s; while (*p) ++p; return ((int) (p - s)); } #endif cp68 debug.c debug.i c068 debug.i debug.1 debug.2 debug.3 -f rm debug.i c168 debug.1 debug.2 debug.s rm debug.1 rm debug.2 as68 -l -u debug.s rm debug.s cp68 textdemo.c textdemo.i c068 textdemo.i textdemo.1 textdemo.2 textdemo.3 -f rm textdemo.i c168 textdemo.1 textdemo.2 textdemo.s rm textdemo.1 rm textdemo.2 as68 -l -u textdemo.s rm textdemo.s link68 textdemo.68k=apstart,textdemo,debug,osbind,vdibind,aesbind rm textdemo.o rm debug.o relmod textdemo rm textdemo.68k wait  /* * textdemo.c -- Demonstrates ways of using GEM's text features. * by Corey S. Cole * Copyright 1986 ANTIC Publishing * Thanks to Digital Research Inc. for their "DOODLE.C" application; * Save buffer and dialogue handling based on doodle, with permission. */ #include "portab.h" /* portable program conventions */ #include "machine.h" /* machine dependencies */ #include "gembind.h" /* gem binding structs */ #include "obdefs.h" /* gem object definitions */ #include "taddr.h" /* tree-parsing definitions */ #include "textdemo.h" /* Definitions for this appl */ #include "txdemo.h" /* Resource defs for this appl */ #if I8086 extern long dos_alloc(); #define malloc(x) dos_alloc(x) #define free(x) dos_free(x) #endif #if ALCYON extern long gemdos(); #define malloc(x) gemdos(0x48, x) #define free(x) gemdos(0x49, x) #endif #ifdef MEGAMAX extern long malloc(); #endif extern char *xprintf(); int gl_apid, gem_handle, vdi_handle, winHandle; int work_in[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 }; int contrl[11]; /* control inputs */ int intin[80]; /* max string length */ int ptsin[256]; /* polygon fill points */ int intout[45]; /* open workstation output */ int ptsout[12]; int work_out[57]; /* open virt workstation values */ int xfull, yfull, wfull, hfull; long gl_menu, save_buf, save_size; MFDB save_mfdb; /* Save buffer form defn blk */ MFDB scrn_mfdb; /* screen memory form defn blk */ GRECT scrn_area; /* whole screen area */ GRECT win_area; /* Interior of text window */ GRECT save_area; /* area for saving screen img */ char justCodes[] = "NCWB"; /* Justification codes */ char horizCodes[] = "LCR"; /* Horizontal alignment codes */ char vertCodes[] = "BHAFDT"; /* Vertical alignment codes */ char pixelCodes[] = "NY"; /* Absolute height (no/yes) */ char text[40] = "Here is your line of text"; char nullString[] = ""; struct textBlock textLine = { text, 8, 100, 300, 20, CHARJUST, LEFT, BASELINE, 0, SYSFONT, 10, TRUE, EFF_NONE, BLACK, WHITE }; #if I8086 GEMAIN() #else main(argc, argv) int argc; /* Number of command line arguments */ char *argv[]; /* Command line arguments */ #endif { int termType; termType = gemInit(); /* Initialize application */ if (! termType) mainLoop(); /* Handle messages */ terminate(termType); } terminate(termType) /* Exit application cleanly */ int termType; { switch (termType) { case 0 : default : wind_close(winHandle); wind_delete(winHandle); case 5 : #if I8086 vst_unload_fonts(vdi_handle, 0); #endif menu_bar(0x0L, FALSE); case 4 : free(save_buf); case 3 : v_clsvwk(vdi_handle); case 2 : wind_update(END_UPDATE); appl_exit(); case 1 : break; } } gemInit() /* Initialize GEM & window */ { int scrn_width, scrn_height, scrn_planes; int tempw, temph; #if I8086 gl_apid = #endif appl_init(); /* Start up application */ if (gl_apid == -1) /* Startup failed (bankrupt?) */ return (1); gem_handle = graf_handle(&tempw, &temph, &tempw, &temph); vdi_handle = gem_handle; v_opnvwk(work_in, &vdi_handle, work_out); if (vdi_handle == 0) /* Open virt. wkstn failed */ return (2); scrn_width = work_out[0] + 1; scrn_height = work_out[1] + 1; vqt_attributes(vdi_handle, work_out); /* Get dft text attrs */ textLine.pointSize = work_out[7]; /* Default text height */ textLine.pixelFlag = TRUE; vq_extnd(vdi_handle, 1, work_out); scrn_planes = work_out[4]; save_mfdb.fwp = scrn_width; save_mfdb.fww = scrn_width >> 4; save_mfdb.fh = scrn_height; save_mfdb.np = scrn_planes; save_mfdb.ff = 0; save_size = (long) (save_mfdb.fwp >> 3) * (long) save_mfdb.fh * (long) save_mfdb.np; save_buf = save_mfdb.mp = malloc(save_size); if (save_buf == 0L) return(3); scrn_area.g_x = 0; scrn_area.g_y = 0; scrn_area.g_w = scrn_width; scrn_area.g_h = scrn_height; scrn_mfdb.mp = 0x0L; wind_update(BEG_UPDATE); /* Lock the screen for a bit */ graf_mouse(HOUR_GLASS, 0x0L); /* Display the busy bee */ if ( ! rsrc_load( "TXDEMO.RSC" ) ) { graf_mouse(ARROW, 0x0L); form_alert(1, (long) "[3][Fatal Error !|TXDEMO.RSC|File Not Found][ Abort ]"); wind_update(END_UPDATE); return(4); } #if I8086 vst_load_fonts(vdi_handle, 0); /* Will crash 520ST */ #endif /* * Now we find out the full size of the desktop, and create a * window to display our text. The window will have a title * and a close box (to allow the user a way to terminate * this program). For simplicity, we will not allow the * window to be moved or resized. However, note that all * position calculations are made relative to the window * offset, so that the code would still work if the window * were moved. */ wind_get(DESK, WF_WXYWH, &xfull, &yfull, &wfull, &hfull); /* Find and display menu  T */ rsrc_gaddr(R_TREE, TEXTMENU, &gl_menu); menu_bar(gl_menu, TRUE);  /* Create display window, using full desktop */ winHandle = wind_create(0, xfull, yfull, wfull, hfull); if (winHandle == -1) { /* Couldn't create window */ wind_update(END_UPDATE); return (5); } wind_open(winHandle, xfull, yfull, wfull, hfull); wind_get(winHandle, WF_WXYWH, &win_area.g_x, &win_area.g_y, &win_area.g_w, &win_area.g_h); textLine.vertPos = win_area.g_h / 2; textLine.lineWidth = win_area.g_w - 16; /* Fill most of window */ LWCOPY(&save_area, &win_area, sizeof(GRECT) / 2); rast_op(0, &save_area, &scrn_mfdb, &save_area, &save_mfdb); graf_mouse(ARROW, 0x0L); wind_update(END_UPDATE); return (0); /* Completed initialization o.k. */ } mainLoop() /* Handle messages to display text and exit */ { unsigned int msgType, evType, temp, kstate, kreturn; int msgPipe[8]; for ( ; ; ) /* Repeat until user closes window */ { evType = evnt_multi( MU_MESAG | MU_KEYBD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &msgPipe, 0, 0, &temp, &temp, &temp, &kstate, &kreturn, &temp); wind_update(BEG_UPDATE); if (evType & MU_KEYBD) { /* Key pressed */ hndlMenu(0, DISPLINE); if (! (evType & MU_MESAG) ) { wind_update(END_UPDATE); continue; } } msgType = msgPipe[0]; /* Message type */ switch (msgType) { /* Handle incoming message */ case MN_SELECTED: if (hndlMenu(msgPipe[3], msgPipe[4])) { (return; /* "Quit" menu item */ } break; case WM_REDRAW : /* Redraw the window */ restWork(); break; } wind_update(END_UPDATE); } } /* * hndlMenu deals with a menu selection by the user. It returns TRUE * if the selection happens to be "Quit", otherwise FALSE. */ hndlMenu(title, item) int title, item; { long tree, stringAddr(); GRECT box; int exitobj; rsrc_gaddr(R_TREE, TEXTMENU, &tree); switch (item) { /* Which menu item */ case TEXTDEMO : /* Display TextDemo info */ objc_xywh(gl_menu, TEXTDEMO, &box); rsrc_gaddr(R_TREE, ABOUTDMO, &tree); exitobj = hndlDial(tree, -1, box.g_x, box.g_y, box.g_w, box.g_h); deselObj(tree, exitobj); break; case TEXTQUIT : /* Quit program */ menu_tnormal(gl_menu, title, TRUE); return (TRUE); case ERASEWIN : /* Erase text window */ eraseWin(); break; case DISPLINE : /* Set line attrs and display */ lineDial(); break; case DISPCHAR : /* Set char attributes */ charDial(); break; } if (title) menu_tnormal(gl_menu, title, TRUE); return (FALSE); } /* * eraseWin -- Clears the text window. This is done (as in doodle) by * zeroing the save buffer, then doing a "restore window" from * the save buffer. */ eraseWin() /* Erase the text window */ { rast_op(0, &win_area, &scrn_mfdb, &win_area, &save_mfdb); restWork(); } lineDial() /* Bring up line attrs dialogue, then display line */ { GRECT box; long tree; int exitobj; objc_xywh(gl_menu, DISPLINE, &box); rsrc_gaddr(R_TREE, LINEATTR, &tree); initLnDial(tree, &textLine); exitobj = hndlDial(tree, TEXTLINE, box.g_x, box.g_y, box.g_w, box.g_h); deselObj(tree, exitobj); if (exitobj != LINEOK) return; /* Cancelled dialogue */ saveLnDial(tree, &textLine); /* Get new line values */ restWork(); /* Restore screen image */ wind_get(winHandle, WF_WXYWH, &win_area.g_x, &win_area.g_y, &win_area.g_w, &win_area.g_h); graf_mouse(M_OFF, 0x0L); drawLine(&textLine, &win_area); /* Draw new line */ graf_mouse(M_ON, 0x0L); saveWork(); /* Save screen image */ } charDial() /* Bring up char attribute dialogue */ { GRECT box; long tree; int exitobj; objc_xywh(gl_menu, DISPCHAR, &box); rsrc_gaddr(R_TREE, CHARATTR, &tree); initChDial(tree, &textLine); exitobj = hndlDial(tree, POINTSIZ, box.g_x, box.g_y, box.g_w, box.g_h); deselObj(tree, exitobj); if (exitobj != CHAROK) return; /* Cancelled dialogue */ saveChDial(tree, &textLine); /* Get new line values */ } initLnDial(tree, lp) /* Initialize line attribute dialogue */ register long tree; register struct textBlock *lp; { char codeChar[2]; setName(tree, TEXTLINE, lp->textString, 0); setNum(tree, DISPXPOS, lp->horPos, 3); setNum(tree, DISPYPOS, lp->vertPos, 3); setNum(tree, LINWIDTH, lp->lineWidth, 3); setNum(tree, LINELEAD, lp->lineHeight, 3); codeChar[1] = '\0'; *codeChar = justCodes[lp->justFlag]; setName(tree, JUSTFLAG, codeChar, 1); *codeChar = horizCodes[lp->horAlign]; setName(tree, HORALIGN, codeChar, 1); *codeChar = vertCodes[lp->vertAlign]; setName(tree, VRTALIGN, codeChar, 1); setNum(tree, ROTATION, lp->rotation, 4); } initChDial(tree, lp) /* Initialize char attribute dialogue */ register long tree; register struct textBlock *lp; { char codeChar[2]; setNum(tree, FONTID, lp->fontId, 2); setNum(tree, POINTSIZ, lp->pointSize, 2); codeChar[1] = '\0'; *codeChar = pixelCodes[lp->pixelFlag]; setName(tree, PIXFLAG, codeChar, 1); setNum(tree, EFFECTS, lp->effects, 2); setNum(tree, COLOR, lp->color, 2); setNum(tree, BACKCOLR, lp->backColor, 2); } saveLnDial(tree, lp) /* Set textBlock from line attrs dialogue */ register long tree; register struct textBlock *lp; { char codeChar[2]; getName(tree, TEXTLINE, lp->textString, 0); lp->horPos = getNum(tree, DISPXPOS, 3); lp->vertPos = getNum(tree, DISPYPOS, 3); lp->lineWidth = getNum(tree, LINWIDTH, 3); lp->lineHeight = getNum(tree, LINELEAD, 3); getName(tree, JUSTFLAG, codeChar, 1); lp->justFlag = decode(*codeChar, justCodes, NOJUST); getName(tree, HORALIGN, codeChar, 1); lp->horAlign = decode(*codeChar, horizCodes, LEFT); getName(tree, VRTALIGN, codeChar, 1); lp->vertAlign = decode(*codeChar, vertCodes, BASELINE); lp->rotation = getNum(tree, ROTATION, 4); } saveChDial(tree, lp) /* Set textBlock from char attrs dialogue */ register long tree; register struct textBlock *lp; { char codeChar[2]; lp->fontId = getNum(tree, FONTID, 2); lp->pointSize = getNum(tree, POINTSIZ, 2); getName(tree, PIXFLAG, codeChar, 1); lp->pixelFlag = decode(*codeChar, pixelCodes, YES); lp->effects = getNum(tree, EFFECTS, 2); lp->color = getNum(tree, COLOR, 2); lp->backColor = getNum(tree, BACKCOLR, 2); } /* * decode -- Compares a character against codes in a string, ignoring * case of the character (code string must be all upper case). * Returns position in string, or specified default if no match. */ decode(code, string, defValue) /* Decode a character value */ char code; /* Character to decode */ register char *string; /* Allowed codes in num. order */ int defValue; /* Default code if no match */ { int value; code &= 0x5f; /* Convert lower case to upper */ for (value = 0; *string; ++value) { if (code == *string++) return (value); } return (defValue); /* Didn't match any letter */ } setName(tree, obj, name, len) /* Change value of text field in rsrc */ long tree; /* Tree in which to look */ int obj; /* Object to change within tree */ char *name; /* Name to place in field */ int len; /* Length of field (characters) */ { char *nameptr; int actlen; nameptr = (char *) LLGET(TE_PTEXT(LLGET(OB_SPEC(obj)))); actlen = LSTRLEN(name); LBCOPY(nameptr, name, actlen); for (nameptr += actlen; actlen < len; ++actlen) *nameptr++ = ' '; *nameptr = '\0'; } getName(tree, obj, name, len) /* Get value of text field in rsrc */ long tree; /* Tree in which to look */ int obj; /* Object to change within tree */ char *name; /* Place to put name from field */ int len; /* Length of field (characters) */ { char *nameptr; int actlen; nameptr = (char *) LLGET(TE_PTEXT(LLGET(OB_SPEC(obj)))); actlen = LSTRLEN(nameptr); if (actlen) LBCOPY(name, nameptr, actlen); for (nameptr = &name[actlen]; actlen < len; ++actlen) *nameptr++ = ' '; *nameptr = '\0'; } setNum(tree, obj, num, len) /* Change value of numeric rsrc field */ long tree; /* Tree in which to look */ int obj; /* Object to change within tree */ int num; /* Number to place in field */ int len; /* Length of field (digits) */ { char *numptr, *xprintf(); int actlen, j; numptr = xprintf("%d", num); actlen = LSTRLEN(numptr); if (actlen < len) { LBCOPY(&numptr[len - actlen], numptr, actlen + 1); for (j = len - actlen - 1; j >= 0; --j) numptr[j] = ' '; } else if (actlen > len) numptr += (actlen - len); /* Cut off left part of num */ setName(tree, obj, numptr, len); } getNum(tree, obj, len) /* Get value of numeric rsrc field */ long tree; /* Tree in which to look */ int obj; /* Object to change within tree */ int len; /* Length of field (digits) */ { char numptr[8], *digit; int numlen, num, tens, haveNum; getName(tree, obj, numptr, len); num = 0; tens = 1; numlen = LSTRLEN(numptr); haveNum = FALSE; for (digit = &numptr[numlen - 1]; digit >= numptr; --digit) { *digit -= '0'; if ((*digit >= 0) && (*digit <= 9)) { num += (*digit * tens); haveNum = TRUE; } else if (! haveNum) continue; tens *= 10; } return (num); } hndlDial(tree, def, x, y, w, h) long tree; int def; int x, y, w, h; { int xdial, ydial, wdial, hdial, exitobj; form_center(tree, &xdial, &ydial, &wdial, &hdial); form_dial(0, x, y, w, h, xdial, ydial, wdial, hdial); form_dial(1, x, y, w, h, xdial, ydial, wdial, hdial); objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial); exitobj = form_do(tree, def) & 0x7FFF; /* * Close dialogue box, and cause redraw of that area to be sent. */ form_dial(2, x, y, w, h, xdial, ydial, wdial, hdial); form_dial(3, x, y, w, h, xdial, ydial, wdial, hdial); return (exitobj); } drawLine(lp, clip) /* Display a line, if in cliprect */ struct textBlock *lp; /* Description of line */ GRECT *clip; /* Clipping rectangle E */ { GRECT textBox; int baseLine, cellHt, center, horiz, vert, wordJust, charJust; int clipCorners[4], baseBox[4], corners[4], perim[10]; boxCorners(clip, clipCorners); vs_clip(vdi_handle, TRUE, clipCorners); horiz = win_area.g_x + lp->horPos; vert = win_area.g_y + lp->vertPos; baseLine = textStyle(lp, &cellHt); center = baseLine + ((lp->lineHeight - cellHt) / 2); textBox.g_x = horiz; textBox.g_y = vert - center; textBox.g_w = lp->lineWidth; textBox.g_h = lp->lineHeight; baseBox[0] = textBox.g_x; /* Where baseline will end up */ baseBox[2] = textBox.g_x + textBox.g_w - 1; baseBox[1] = baseBox[3] = vert; if (lp->horAlign == RIGHT) /* Right-aligned text */ horiz += lp->lineWidth; else if (lp->horAlign == CENTER) /* Centered */ horiz += lp->lineWidth / 2; /* * If any significant rotation is in effect, the "line box" will * obviously have to change position. Fortunately, GEM only * rotates at 90 degree angles, so a modest amount of kludgery * should give us approximately the right orientation. */ if (lp->rotation >= 450) { /* Rotating the text */ if ((lp->rotation < 1350) || (lp->rotation >= 2250)) { if (lp->horAlign == RIGHT) { horiz -= lp->lineWidth; vert += lp->lineWidth; } else if (lp->horAlign == CENTER) { horiz -= lp->lineWidth / 2; vert += lp->lineWidth / 2; } baseBox[0] = baseBox[2] = horiz; textBox.g_w = lp->lineHeight; textBox.g_h = lp->lineWidth; if (lp->rotation >= 2250) { /* Heading down */ textBox.g_x -= (lp->lineHeight - center); textBox.g_y = baseBox[1]; baseBox[3] += lp->lineHeight - 1; } else { /* Heading up */ if (lp->horAlign == RIGHT) (vert -= (lp->lineWidth * 2); else if (lp->horAlign == CENTER) (vert -= lp->lineWidth; textBox.g_x -= center; baseBox[3] -= (lp->lineWidth - 1); textBox.g_y = baseBox[3]; } } else { /* Heading to the left */ if (lp->horAlign == RIGHT) horiz -= (lp->lineWidth + lp->lineWidth); else if (lp->horAlign == CENTER) horiz -= lp->lineWidth; textBox.g_x -= textBox.g_w; textBox.g_y += (center + center - lp->lineHeight); --baseBox[0]; /* Reverse baseline */ baseBox[2] = textBox.g_x; } } /* * Now prepare to display the background color. */ intersect(clip, &textBox); /* Don't go off edge */ boxCorners(&textBox, corners); perim[0] = perim[6] = perim[8] = corners[0]; perim[1] = perim[3] = perim[9] = corners[1]; perim[2] = perim[4] = corners[2]; perim[5] = perim[7] = corners[3]; vsf_perimeter(vdi_handle, 0); /* No perimeter */ vsf_color(vdi_handle, lp->backColor); /* Clean up area */ vsf_interior(vdi_handle, 1); /* Interior is solid */ vswr_mode(vdi_handle, REPLACE); v_bar(vdi_handle, corners); /* Turn on background */ vswr_mode(vdi_handle, TRANSPARENT); if (lp->justFlag) { /* Actually time to display the text! */ wordJust = lp->justFlag & WORDJUST; charJust = lp->justFlag & CHARJUST; v_justified(vdi_handle, horiz, vert, lp->textString, lPp->lineWidth, wordJust, charJust); } else v_gtext(vdi_handle, horiz, vert, lp->textString); /* * Just for visual comparison, we draw a border around the * theoretical line box, and also draw the baseline. These * will be incorrect if rotation is in effect (since the * application can't, as far as I know, tell what rotation * angle will actually be used). */ vsl_width(vdi_handle, 2); /* One pixel thick */ vsl_ends( vdi_handle, 0, 0 ); vsl_type( vdi_handle, 3); /* Dotted line */ vsl_color(vdi_handle, GREEN); /* Baseline is green */ if ((vert >= clip->g_y) && (vert < clip->g_y + clip->g_h)) v_pline(vdi_handle, 2, baseBox); /* Draw baseline */ vsl_type( vdi_handle, 1); /* Solid border lines */ vsl_color(vdi_handle, RED); /* Border is red */ v_pline(vdi_handle, 5, perim); /* Solid box around text */ vs_clip(vdi_handle, FALSE, clipCorners); vswr_mode(vdi_handle, REPLACE); /* The normal default */ } textStyle(lp, cellHt) /* Set attributes into GEM */ register struct textBlock *lp; /* Line descriptor */ int *cellHt; /* We return cell height here */ { int temp, baseLine; vst_rotation (vdi_handle, lp->rotation); vst_alignment (vdi_handle, lp->horAlign, lp->vertAlign, &temp, &temp); vst_font (vdi_handle, lp->fontId); vst_effects (vdi_handle, lp->effects); vst_color (vdi_handle, lp->color); vsf_color (vdi_handle, lp->backColor); if (lp->pixelFlag) { /* Character size is in pixels */ /* * Important: Note that the character height (lp->pointSize) * is the number of pixels in the character above the * baseline, *not* the cell height of the character. * You may want to do a vqt_attributes call just after * opening the virtual workstation, in order to find * out the correct height value for the default system * font -- the value will not be at all obvious (it * turns out to be 13 in high-res mode, and 6 pixels * in either medium or low-resolution). */ vst_height(vdi_handle, lp->pointSize, &temp, &baseLine, &temp, cellHt); } else vst_point (vdi_handle, lp->pointSize, &temp, &baseLine, &temp, cellHt); /* Char size in Points */ return (baseLine); } intersect(srcbox, destbox) /* Find intersection of two boxes */ GRECT *srcbox, *destbox; /* WARNING: Changes *destbox */ { int left, top, right, bot; int srcRight, srcBot, destRight, destBot; srcRight = srcbox->g_x + srcbox->g_w; srcBot = srcbox->g_y + srcbox->g_h; destRight = destbox->g_x + destbox->g_w; destBot = destbox->g_y + destbox->g_h; left = MAX(srcbox->g_x, destbox->g_x); top = MAX(srcbox->g_y, destbox->g_y); right = MIN(srcRight, destRight); bot = MIN(srcBot, destBot); destbox->g_x = left; /* Set dest to intersection */ destbox->g_y = top; destbox->g_w = right - left; destbox->g_h = bot - top; return ((right > left) && (bot > top)); } boxCorners(grect, array) /* Convert GRECT to int array */ GRECT *grect; int *array; { array[0] = grect->g_x; array[1] = grect->g_y; array[2] = grect->g_x + grect->g_w - 1; array[3] = grect->g_y + grect->g_h - 1; } byteAlign(x) /* Finds nearest eight-pixel boundary to "x" */ int x; { return((x & 0xfff8) + ((x & 0x0004) ? 0x0008 : 0)); } long stringAddr(which) /* returns a tedinfo string addr */ int which; { long where; rsrc_gaddr(R_STRING, which, &where); return (where); } saveWork() /* Copy work_area to save buffer */ { GRECT tmp_area; LWCOPY(&tmp_area, &win_area, sizeof(GRECT) / 2); graf_mouse(M_OFF, 0x0L); rast_op(3, &tmp_area, &scrn_mfdb, &tmp_area, &save_mfdb); graf_mouse(M_ON, 0x0L); } restWork() /* restore work_area from save buffer */ { GRECT tmp_area; LWCOPY(&tmp_area, &win_area, sizeof(GRECT) / 2); graf_mouse(M_OFF, 0x0L); rast_op(3, &tmp_area, &save_mfdb, &tmp_area, &scrn_mfdb); graf_mouse(M_ON, 0x0L); } rast_op(mode, s_area, s_mfdb, d_area, d_mfdb) /* bit block level trns */ int mode; GRECT *s_area, *d_area; MFDB *s_mfdb, *d_mfdb; { int pxy[8]; grect_to_array(s_area, pxy); grect_to_array(d_area, &pxy[4]); vro_cpyfm(vdi_handle, mode, pxy, s_mfdb, d_mfdb); } grect_to_array(area, array) /* convert x,y,w,h to upr lt x,y and */ GRECT *area; /* lwr rt x,y */ int *array; { *array++ = area->g_x; *array++ = area->g_y; *array++ = area->g_x + area->g_w - 1; *array = area->g_y + area->g_h - 1; } objc_xywh(tree, obj, p) /* get x,y,w,h for specified object */ long tree; int obj; GRECT *p; { objc_offset(tree, obj, &p->g_x, &p->g_y); p->g_w = LWGET(OB_WIDTH(obj)); p->g_h = LWGET(OB_HEIGHT(obj)); } deselObj(tree, which) /* turn off selected bit of spcfd object*/ long tree; int which; { int state; state = LWGET(OB_STATE(which)); LWSET(OB_STATE(which), state & ~SELECTED); } J/* * textdemo.h -- Definitions file for textdemo.c * by Corey S. Cole * Copyright 1986 ANTIC Publishing */ struct textBlock { /* Describes attributes of text line */ char *textString; /* Pointer to text to display */ int horPos; /* Left edge of displayed line */ int vertPos; /* Top edge of displayed line */ int lineWidth; /* Max width (for justifying) */ int lineHeight; /* Max height (line leading) */ int justFlag; /* Method of justification: * )* 0 = unjustified, * )* 1 = word spacing only, * )* 2 = char spacing only, * )* 3 = word and char space */ int horAlign; /* Horizontal alignment */ int vertAlign; /* Vertical alignment */ int rotation; /* Baseline rotation */ int fontId; /* Which typestyle to use */ int pointSize; /* Point or Pixel Height */ int pixelFlag; /* TRUE = Height is in Pixels */ int effects; /* Special effects bit flags */ int color; /* Foreground color for text */ int backColor; /* Background color */ }; #define NULLBLOCK (struct textBlock *) 0L #define BI_PDATA(x) (x) #define BI_WB(x) (x + 4) #define BI_HL(x) (x + 6) #define TE_PTEXT(x) (x) #define TE_TXTLEN(x) (x + 24) #define MIN(a, b) ((a < b) ? a : b) #define MAX(a, b) ((a > b) ? a : b) #define ARROW 0 #define HOUR_GLASS 2 #define DESK 0 #define END_UPDATE 0 #define BEG_UPDATE 1 #define REPLACE 1 /* Replace mode in VDI */ #define TRANSPARENT 2 /* Transparent mode in VDI */ #define XOR_MODE 3 /* Exclusive OR mode in VDI */ /* * Here are the numbers for all of the typestyles described in the * GEM manual. The catch is that only "SYSFONT", #1, is available * on the Atari 520ST. These are included for IBM PC users, and * for later experim [entation with fonts. */ #define SYSFONT 1 /* System monospace font */ #define SWISSMED 2 /* Swiss medium Roman font */ #define SWISSFONT SWISSMED #define SWLTITAL 5 /* Swiss light italic font */ #define SWISSLIGHT 6 /* Swiss light Roman font */ #define SWISSITAL 7 /* Swiss medium italic font */ #define SWISSBOLD 8 /* Swiss bold Roman font */ #define SWBOLDITAL 9 /* Swiss bold italic font */ #define DUTCHMED 14 /* Dutch medium Roman font */ #define DUTCHFONT DUTCHMED #define DUTCHITAL 15 /* Dutch medium italic font */ #define DUTCHBOLD 16 /* Dutch bold Roman font */ #define DUBOLDITAL 17 /* Dutch bold italic font */ #define NOJUST 0 /* Don't justify strings */ #define CHARJUST 1 /* Justify with char-spacing */ #define WORDJUST 2 /* Justify with word-spacing */ #define FULLJUST 3 /* Use word and char-spacing */ #define LEFT 0 /* Left-align strings */ #define CENTER 1 /* Center-align strings */ #define RIGHT 2 /* Right-align strings */ #define BASELINE 0 /* Display on baseline */ #define HALFLINE 1 /* "Half-line" for superscript */ #define ASCENT 2 /* "Ascent line" (top of char) */ #define BOTTOM 3 /* "Bottom" of text line */ #define DESCENT 4 /* "Descent" for subscript */ #define TOPALIGN 5 /* Top-aligned */ #define EFF_NONE 0 /* No special effects used */ #define EFF_BOLD 1 /* "Thickened" special effect */ #define EFF_LIGHT 2 /* "Light intensity" effect */ #define EFF_SKEWED 4 /* "Skewed" italic effect */ #define EFF_UNDLIN 8 /* "Underlined" special effect */ #define EFF_OUTLINE 16 /* "Outlined" special effect */ #define EFF_SHADOW 32 /* "Shadowed" special effect */ #if MC68K typedef struct memform { long mp; int fwp; int fh; int fww; int ff; int np; int r1; int r2; int r3; } MFDB; #endif k`) *O.|0*m - ЭЭм// ??<JNA NJ/<NA"/0<NBNuNVa=@Jnfa>aN^NuNV0.`T>4pN(f>4pN(BWBN&X.1X?<INT>5"NBWN(N$``|b@0@* PNN^NuNVN$2 y5fp`./Q//QN&l 35355".3/<5"/<*bN PJy5"fp`093R@=@093R@=@.3?95"NRT34*3*.3?<?95"NX=y4300.@303030By0090H/0y0/090@H/N#tP/N#tP#1.1?<HNT#0#1XJ1Xfp`By1|By1~3131B1h>N(B?<N&T.+(N'J@f,BBgN&T.+3?<N&TBWN(p`X.5$/<1/<1/<1?<BgN(.1dBgBgN'X>/91dN&X>5$?91?91?91BgN'P34p y4pfBWN(p`>5$?91?91?91?94pN(,P.1b/<1`/<1^/<1\?<?94pN(091bH3*091`|3*>/<1\/<0N4P.0/<0/<1h/<0BgaBBgN&TBWN(B@N^NuNV.]//Q/]/]/]BgBg/BgBgBgBgBgBgBgBgBgBgBgBgBg?<N$8=@>N(.g>BgaZT.f BWN(`>=nB@0.`>?.a.TJ@g`"`a`` | gް|gBWN(`?.?.?.?/.alX`B>?./91dN&\p`FaH`$at`a```Q@| b@0@* PNJng>?./91dN&\B@N^NuNV.0/<1\/<1h/<1\BgaazN^NuNV.Q?</91da`\.?<BgN'X.*/.aFX>?.?.?.?</.a8 =@>/.adX n ft.*/.aXa.1b/<1`/<1^/<1\?<?94pN(B?<N&T.1\/<*aXB?<N&Ta.N^NuNV.Q?</91dan\.?<BgN'X.*/.a\X>?.?.?.?</.aF =@>/.arX n f.*/.aXN^NuNVH..*n BW/?</a >?-?</a~P>?-?</ajP>?-?</aVP>?- ?</aBPB.0m *xP>/U?< /a0 0m*~P>/U?< /a 0m*P>/U?< /a >?-?< /aPJL N^NuNVH..*n >?-?</aP>?-?</avPB.0m*P>/U?</ad >?-?</a8P>?-?</a$P>?-?< /aPJL N^NuNVH..*n BW/?</aj >?</a\;@>?</ar\;@>?</a^\;@>?</aJ\;@ >/U?< /a BW/<*x.H?a:\;@ >/U?< /a BW/<*~.H?a\;@>/U?< /a BW/<*.H?a\;@>?< /a\;@JL N^NuNVH..*n >?</ar\;@>?</a^\;@>/U?</a >/<*.H?aL\;@>?</a\;@>?</a\;@>?< /a\;@JL N^NuNVH*n ._ Bn`H. f0.` RnJf0.JL N^NuNV | 2. Ү p-P.N=@>/./.NP0.HѮ` n RRn0.nm nBN^NuNV | 2. Ү p-P.N=@Jng>/./.NP .2.HЁ-@` n RRn0.nm nBN^NuNV>/<+iNX-@.N=@0.nlL>RW/.0.nHЮ/NP0.nS@=@` n2n SnJnl`0.no0.nHѮ>/.?. /.al N^NuNV>/Q?. /.a Bn=|.QN=@Bn 2.HЁм-@`H n0 nJm" n  n nHn=|`Jng 0. =@S Qc0.N^NuNV.Q/]/Y/U/.N&">?.?.?.?.?.?.?.BgN%>?.?.?.?.?.?.?.?<N%>?.?.?.?<Bg/.N'> /.N%X|=@>?.?.?.?.?.?.?.?<N%>?.?.?.?.?.?.?.?<N%0.N^NuNV./. aX.?<?95"N X n0(y1\=@ n0(y1^=@./.a\X=@ n0( nHn=@=n0.n=@ n=h n=h =n0.nS@=@0.=@=@ n hf n0(n` n hf n0(Hn n hmz n hFm n hm n hf n0(n n0(n`0 n hf$ n0(Hn n0(Hn0.=@=@ n=h n=h n hm& n0( nn=n n0( S@n`P n hf n0(@n` n hf n0(n0.n n0(S@n=n`d n hf n0("n2)An` n hf n0(n0.n0.n"n2) AnSn=n.Q/. aX./Qa(X0.=@=@=@0.=@=@=@0.=@=@0.=@=@BW?95"N T n>?95"N LT>?95"N T>?95"NtT.?95"NT>?95"NtT nJh gR n0( |=@ n0( |=@>?. n?( n/?.?.?95"N` n.?.?.?95"N\>?95"N!TBWBg?95"N!4X>?95"N!pT>?95"N T n 0(nn2 n 0("n 2)Ano.?<?95"NX>?95"N!pT>?95"N T.?<?95"NX.Bg?95"N X>?95"NtTN^NuNVH*n>?95"N:T.U/U?-?-?95"N! >?95"N"T>?95"N"tT>?95"N":T>?95"N LTJmg(. /U/Y/U?-?95"N"`&. /U/Y/U?-?95"N0.JL N^NuNV n0"n2)A=@ n0("n2)A=@ n 0"n 2)A=@ n 0("n 2)A=@ n0"n 2Ao n0` n 0=@ n0("n 2)Ao n0(` n 0(=@0.nl0.`0.=@0.nl0.`0.=@ n 0 n 1n0.n"n 3@0.n"n 3@0.no 0.nnB@`pN^NuNV n "n0 n "n1i n0"n2)AS@"n 3@ n0("n2)AS@"n 3@N^NuNV0.|. gr`BAAN^NuNV.Y?.?<N'X .N^NuNV>/<1\/QN4PB?<N&T.0/Q/<1h/Q?<arB?<N&TN^NuNV>/<1\/QN4PB?<N&T.1h/Q/<0/Q?<aB?<N&TN^NuNV./. a8X.Q/.a,X././?.?95"N N^NuNV n "n0T n "n0T n0"n2)AS@"n 2T n0("n2)AS@"n 2N^NuNV.T/.?. /.N'f n2. ҮҼ"A1Q n2. ҮҼ"A1QN^NuNV0. Юм @=P0.|2. ҮҼ "A2N^NuNV.a|=@ no=|-|+pBn` no>/./.aP`<-n` n R .мbJno>/./.apP npg n||nn nmr.+l?<N&TN^NuNVBn=n =n=n=n=n=n=n=n=n-|4r` n %g n"nR`lR n %f n"nR`N nH| |df0n>/.aJXHѮRn`0n>/.aXHѮRnR nJfn nB <4rN^NuNV=| n l=| .2.HЁS-@`^Jn f( .2.HЁSf n0` n `,0. H H@=@0. H =@ 0.|0"nS .d0.N^NuNV=| .2.HЁS-@`/.?. a&T _0. @=@ S .d0.N^NuNVn nm|-`" n m0.|7@` 0.|0@.HN^NuNVH (n*n >.g c `SGJGn``%SGJGnJL0N^NuNVH (n*n >.g,c `8SGJGn`0@H0@H`9%SGJGnJL0N^NuNVH*n`RJf JL N^Nu#0NN/90Nu#0NM/90Nu#0NA/90NuNV3 0*3k5By535 35N#^ n 03 n03 n03 n03090N^NuNV3 0*3 5By535 35N#^090N^NuNV3 0*3 5By535 35N#^090N^NuNV# 03 535By5 3535N#^#10N^NuNV3e5By5By5 35N#^N^NuNV3 13 1Bn nH|2n0*2RRnJ@f3535Sn35 35N#^N^NuNV3 13 131By130*30,-|0. nH"n2RTJ@f3 535 .0*HS@35 3 535N#^N^NuNV#0#0" .мZ#0&3d5By53 5 n 35N#^ n 05#0*0#00"#30&#10N^NuNV# 0353 5By5 35N#^#10N^NuNV#0*0#10# 0" . мZ#0&3 0*3f5By535 35N#^#00"#30&N^NuNV# 0" . м #0&3&5By5By5 35N#^#00"#30&N^NuNV3 0*.N#J.N#T# 03m53535 35N#^#10N^NuNV# 03 0*353535 35N#^#10N^NuNV3 0*35By535 35N#^090N^NuNV3 0*35By535 35N#^090N^NuNV3 0*3h5By535 35N#^090N^NuNV3 0*35By535 35N#^090N^NuNV3 0*3 0,3l5By535 35N#^N^NuNV3 0*35By535 35N#^090N^NuNV3 1By13535By5 35N#^093N^NuNV3 0*3 0,3'5By535 35N#^ n00 n00N^NuNV3 0*35By535 35N#^090N^NuNV3 0*3j5By535 35N#^090N^NuNV3 0*35By535 35N#^090N^NuNVBy13 13 535By5 35N#^ n 03 n03 n03 n03N^Nu#5Nu#5Nu#50"<0psNBNuNVBBJlDRBJ lD RB0. -@0.2. An=@ .gDN^NuNV330.|Hм)-@=|` nH2n32RRn nm.4lN>B@093N^NuNV#31@#31D#31H#31L#51P#5&1T#1@4l> aF335pN^NuNV>a*pN^NuNV333 33 33333333333333333333 33"3#$53(33*3>N# n,03 n003 n403 n803 n<03 n@03B@093N^NuNV#53 3>2N#N^NuNV333 33 3333333333333>3N#N^NuNV33# 5>4N#N^NuNV#5>6N# n 03 n03 n03 n03B@093N^NuNV>MN# n03 n 03 n03 n03B@093N^NuNV33# 5>NN#N^NuNV#53 3>N#N^NuNV#53 333>!N#N^NuNV#53 33333333333>*N#N^NuNV#53 3>,N# n03 n03B@093N^NuNV#5>nN#N^NuNV333 3>pN# n 5&B@093N^NuNV333 33 33333>dN#N^NuNV333 33 33333>eN#N^NuNV33>fN#N^NuNV33>gN#N^NuNV333 3>hN# n 03 n03 n03 n03B@093N^NuNV33>kN#N^Nu    -NCWBLCRBHAFDTNYHere is your line of text*d, tZ~xtTXDEMO.RSC[3][Fatal Error !|TXDEMO.RSC|File Not Found][ Abort ]%d[1][1234567890123456789012345678|1234567890123456789012345678|1234567890123456789012345678|1234567890123456789012345678|1234567890123456789012345678][ Continue ].D  &               V"@F*&L L&&22ZF..0&406   P    :      ""    @ J  $      f $                    U#define T0OBJ 0 #define T1OBJ 22 #define T2OBJ 37 #define T3OBJ 49 #define FREEBB 0 #define FREEIMG 0 #define FREESTR 84 BYTE *rs_strings[] = { " TextDemo ", " Exit ", " Display ", " About TEXTDEMO ", "-", "1", "2", "3", "4", "5", "6", " Quit ", " Char Attributes ", " Display Line ", " Erase Window ", "Line Attributes", "", "", "Here is your text line. ", "Text: _", "X", "010", "Display at (X-coordinate): ___", "999", "010", "Display at (Y-coordinate): ___", "999", "300", "Line Width (in pixels) : ___", "999", "020", "Line Height (in pixels) : ___", "999", "B", "Justification (None/Char/Word/Both): _", "X", "L", "Horiz. Align. (Left/Center/Right) : _", "X", "B", "Vert (Floor/Desc/Base/Half/Asc/Top): _", "X", "0000", "Baseline Rotation (degrees * 10): ____", "9999", " OK ", " Cancel ", "Character Attributes", "", "", " 1", "Font i.d. (always use 1 on ST) : __", "99", "10", "Char. Height (Points or Pixels): __", "99", "N", "Is \"Character Height\" in pixels? _", "X", " 0", "Special Effects Flags (Decimal): __", "99", " 1", "Foreground (Text) Color : __", "99", " 0", "Background (Line) Color : __", "99", " OK ", " Cancel ", "GEM Text Display Demo", "", "", "by Corey Cole", "", "", " OK ", "copyright 1986 by ANTIC Publishing", "", "", " This utility is intended", "to be used with the \"Displaying", "Text With GEM\" article in the", "premiere issue of STart."}; LONG rs_frstr[] = { 0}; BITBLK rs_bitblk[] = { 0}; LONG rs_frimg[] = { 0}; ICONBLK rs_iconblk[] = { 0}; TEDINFO rs_tedinfo[] = { 15L, 16L, 17L, 3, 6, 2, 0x1000, 0x0, -1, 16,1, 18L, 19L, 20L, 3, 6, 2, 0x1180, 0x0, -2, 31,37, 21L, 22L, 23L, 3, 6, 0, 0x1180, 0x0, -1, 4,31, 24L, 25L, 26L, 3, 6, 0, 0x1180, 0x0, -1, 4,31, 27L, 28L, 29L, 3, 6, 0, 0x1180, 0x0, -1, 4,31, 30L, 31L, 32L, 3, 6, 0, 0x1180, 0x0, -1, 4,31, 33L, 34L, 35L, 3, 6, 0, 0x1180, 0x0, -1, 2,39, 36L, 37L, 38L, 3, 6, 0, 0x1180, 0x0, -1, 2,39, 39L, 40L, 41L, 3, 6, 0, 0x1180, 0x0, -1, 2,39, 42L, 43L, 44L, 3, 6, 0, 0x1180, 0x0, -1, 5,39, 47L, 48L, 49L, 3, 6, 2, 0x1000, 0x0, -1, 21,1, 50L, 51L, 52L, 3, 6, 0, 0x1180, 0x0, -1, 3,36, 53L, 54L, 55L, 3, 6, 0, 0x1180, 0x0, -1, 3,36, 56L, 57L, 58L, 3, 6, 0, 0x1180, 0x0, -1, 2,36, 59L, 60L, 61L, 3, 6, 0, 0x1180, 0x0, -1, 3,36, 62L, 63L, 64L, 3, 6, 0, 0x1180, 0x0, -1, 3,36, 65L, 66L, 67L, 3, 6, 0, 0x1180, 0x0, -1, 3,36, 70L, 71L, 72L, 3, 6, 2, 0x1000, 0x0, -1, 22,1, 73L, 74L, 75L, 3, 6, 2, 0x1000, 0x0, -1, 14,1, 77L, 78L, 79L, 3, 6, 2, 0x1180, 0x0, -1, 35,1}; OBJECT rs_object[] = { -1, 1, 6, G_IBOX, NONE, NORMAL, 0x0L, 0,0, 80,25, 6, 2, 2, G_BOX, NONE, NORMAL, 0x1100L, 0,0, 80,513, 1, 3, 5, G_IBOX, NONE, NORMAL, 0x0L, 2,0, 28,769, 4, -1, -1, G_TITLE, NONE, NORMAL, 0x0L, 0,0, 11,769, 5, -1, -1, G_TITLE, NONE, NORMAL, 0x1L, 11,0, 7,769, 2, -1, -1, G_TITLE, NONE, NORMAL, 0x2L, 18,0, 10,769, 0, 7, 18, G_IBOX, NONE, NORMAL, 0x0L, 0,769, 80,19, 16, 8, 15, G_BOX, NONE, NORMAL, 0xFF1100L, 2,0, 20,8, 9, -1, -1, G_STRING, NONE, NORMAL, 0x3L, 0,0, 20,1, 10, -1, -1, G_STRING, NONE, DISABLED, 0x4L, 0,1, 20,1, 11, -1, -1, G_STRING, NONE, NORMAL, 0x5L, 0,2, 20,1, 12, -1, -1, G_STRING, NONE, NORMAL, 0x6L, 0,3, 20,1, 13, -1, -1, G_STRING, NONE, NORMAL, 0x7L, 0,4, 20,1, 14, -1, -1, G_STRING, NONE, NORMAL, 0x8L, 0,5, 20,1, 15, -1, -1, G_STRING, NONE, NORMAL, 0x9L, 0,6, 20,1, 7, -1, -1, G_STRING, NONE, NORMAL, 0xAL, 0,7, 20,1, 18, 17, 17, G_BOX, NONE, NORMAL, 0xFF1100L, 13,0, 13,1, 16, -1, -1, G_STRING, NONE, NORMAL, 0xBL, 0,0, 13,1, 6, 19, 21, G_BOX, NONE, NORMAL, 0xFF1100L, 20,0, 18,3, 20, -1, -1, G_STRING, NONE, NORMAL, 0xCL, 0,0, 18,1, 21, -1, -1, G_STRING, NONE, NORMAL, 0xDL, 0,1, 18,1, 18, -1, -1, G_STRING, LASTOB, NORMAL, 0xEL, 0,2, 18,1, -1, 1, 14, G_BOX, NONE, OUTLINED, 0x21100L, 0,0, 41,18, 3, 2, 2, G_BOX, NONE, NORMAL, 0xFF1171L, 1,1, 26,3, 1, -1, -1, G_TEXT, NONE, NORMAL, 0x0L, 0,0, 26,3, 4, -1, -1, G_FBOXTEXT, EDITABLE, NORMAL, 0x1L, 1,5, 38,2, 13, 5, 12, G_BOX, NONE, NORMAL, 0x1100L, 1,8, 39,9, 6, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x2L, 0,0, 39,1, 7, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x3L, 0,1, 39,1, 8, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x4L, 0,2, 39,1, 9, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x5L, 0,3, 39,1, 10, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x6L, 0,5, 39,1, 11, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x7L, 0,6, 39,1, 12, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x8L, 0,7, 39,1, 4, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x9L, 0,8, 39,1, 14, -1, -1, G_BUTTON, 0x7, NORMAL, 0x2DL, 31,1, 8,1, 0, -1, -1, G_BUTTON, 0x25, NORMAL, 0x2EL, 31,3, 8,1, -1, 1, 11, G_BOX, NONE, OUTLINED, 0x21100L, 0,0, 39,13, 3, 2, 2, G_BOX, NONE, NORMAL, 0xFF1171L, 2,1, 24,3, 1, -1, -1, G_TEXT, NONE, NORMAL, 0xAL, 0,0, 24,3, 10, 4, 9, G_BOX, NONE, NORMAL, 0x1100L, 2,5, 36,7, 5, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0xBL, 0,0, 36,1, 6, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0xCL, 0,1, 36,1, 7, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0xDL, 0,2, 36,1, 8, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0xEL, 0,4, 36,1, 9, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0xFL, 0,5, 36,1, 3, -1, -1, G_FTEXT, EDITABLE, NORMAL, 0x10L, 0,6, 36,1, 11, -1, -1, G_BUTTON, 0x7, NORMAL, 0x44L, 29,1, 8,1, 0, -1, -1, G_BUTTON, 0x25, NORMAL, 0x45L, 29,3, 8,1, -1, 1, 6, G_BOX, NONE, OUTLINED, 0x21100L, 0,0, 40,14, 4, 2, 3, G_BOX, NONE, NORMAL, 0xFD1171L, 3,1, 26,4, 3, -1, -1, G_TEXT, NONE, NORMAL, 0x11L, 0,0, 26,2, 1, -1, -1, G_TEXT, NONE, NORMAL, 0x12L, 0,2, 26,1, 5, -1, -1, G_BUTTON, 0x7, NORMAL, 0x4CL, 32,2, 6,1, 6, -1, -1, G_TEXT, NONE, NORMAL, 0x13L, 3,6, 34,1, 0, 7, 10, G_BOX, NONE, OUTLINED, 0xFF1100L, 3,8, 34,4, 8, -1, -1, G_STRING, NONE, NORMAL, 0x50L, 1,0, 28,1, 9, -1, -1, G_STRING, NONE, NORMAL, 0x51L, 1,1, 31,1, 10, -1, -1, G_STRING, NONE, NORMAL, 0x52L, 1,2, 29,1, 6, -1, -1, G_STRING, LASTOB, NORMAL, 0x53L, 1,3, 24,1}; LONG rs_trindex[] = { 0L, 22L, 37L, 49L}; struct foobar { WORD dummy; WORD *image; } rs_imdope[] = { 0}; #define NUM_STRINGS 84 #define NUM_FRSTR 0 #define NUM_IMAGES 0 #define NUM_BB 0 #define NUM_FRIMG 0 #define NUM_IB 0 #define NUM_TI 20 #define NUM_OBS 60 #define NUM_TREE 4 BYTE pname[] = "TXDEMO.RSC";2 rTEXTMENUTEXTDEMOTEXTQUITLINEATTRLINWIDTH LINEOKLINECANLINELEAD HORALIGN VRTALIGN ROTATIONERASEWINDISPXPOSDISPYPOS JUSTFLAGDISPCHARCHARATTRFONTID3POINTSIZPIXFLAGEFFECTSCOLORN3 BACKCOLR CHAROK CHARCANTEXTLINEDISPLINEABOUTDMOABOUTOK.#define TEXTMENU 0 /* TREE */ #define TEXTDEMO 8 /* OBJECT in TREE #0 */ #define TEXTQUIT 17 /* OBJECT in TREE #0 */ #define LINEATTR 1 /* TREE */ #define LINWIDTH 7 /* OBJECT in TREE #1 */ #define LINEOK 13 /* OBJECT in TREE #1 */ #define LINECAN 14 /* OBJECT in TREE #1 */ #define LINELEAD 8 /* OBJECT in TREE #1 */ #define HORALIGN 10 /* OBJECT in TREE #1 */ #define VRTALIGN 11 /* OBJECT in TREE #1 */ #define ROTATION 12 /* OBJECT in TREE #1 */ #define ERASEWIN 21 /* OBJECT in TREE #0 */ #define DISPXPOS 5 /* OBJECT in TREE #1 */ #define DISPYPOS 6 /* OBJECT in TREE #1 */ #define JUSTFLAG 9 /* OBJECT in TREE #1 */ #define DISPCHAR 19 /* OBJECT in TREE #0 */ #define CHARATTR 2 /* TREE */ #define FONTID 4 /* OBJECT in TREE #2 */ #define POINTSIZ 5 /* OBJECT in TREE #2 */ #define PIXFLAG 6 /* OBJECT in TREE #2 */ #define EFFECTS 7 /* OBJECT in TREE #2 */ #define COLOR 8 /* OBJECT in TREE #2 */ #define BACKCOLR 9 /* OBJECT in TREE #2 */ #define CHAROK 10 /* OBJECT in TREE #2 */ #define CHARCAN 11 /* OBJECT in TREE #2 */ #define TEXTLINE 3 /* OBJECT in TREE #1 */ #define DISPLINE 20 /* OBJECT in TREE #0 */ #define ABOUTDMO 3 /* TREE */ #define ABOUTOK 4 /* OBJECT in TREE #3 */ xxx4$w H< X TextDemo Exit Display About TEXTDEMO -123456 Quit  Char Attributes Display Line Erase Window Line AttributesHere is your text line. Text: _X010Display at (X-coordinate): ___999010Display at (Y-coordinate): ___999300Line Width (in pixels) : ___999020Line Height (in pixels) : ___999BJustification (None/Char/Word/Both): _XLHoriz. Align. (Left/Center/Right) : _XBVert (Floor/Desc/Base/Half/Asc/Top): _X0000Baseline Rotation (degrees * 10): ____9999 OK Cancel Character Attributes 1Font i.d. (always use 1 on ST) : __9910Char. Height (Points or Pixels): __99NIs "Character Height" in pixels? _X 0Special Effects Flags (Decimal): __99 1Foreground (Text) Color : __99 0Background (Line) Color : __99 OK Cancel GEM Text Display Demoby Corey Cole OK copyright 1986 by ANTIC Publishing This utility is intendedto be used with the "DisplayingText With GEM" article in thepremiere issue of STart.%26UY]|'"'$&M'OT{'$$!$ #&J$MPt$wz$# PP  $  0  8  P C U j l nprt v  )qx&  ' ''' '  ' <' X't'% ' q  $$$$$ $8$ %(qTp " "   @ ^ @To compile any of the programs included on this disk, you will need the following program files from the developer's toolkit: cp68.prg c068.prg c168.prg as68.prg link68.prg relmod.prg To use the batch files included in each folder, you will need these programs as well: batch.prg rm.prg wait.prg In each program's folder you will find one or possibly two .BAT files. If every necessary file is on the default drive, each program can be compiled and linked by running batch.prg with this .BAT file as the parameter. Although not every program requires these header files to compile, following is an exhaustive list of every system header file used by every program included on this disk. By "system header file" we mean header files provided with the developer's toolkit, and not any header files a programmer may have created for the specific program. portab.h - definitions intended to assist in writing portable code machine.h - intended to assist in porting between 8086 and 68000 gembind.h - GEM procedure bindings and other likely GEM things gemdefs.h - just other likely GEM things obdefs.h - GEM object definitions osbind.h - definitions useful for using osbind.o vdibind.h - extern declarations for GEM VDI procedure calls taddr.h - another way to get to the GEM object structure See the particular program's listing to determine what specific system header files it will need on the compile disk. Although not every program requires these link files (by which we mean object and library files necessary to link) following is an exhaustive list of every link file necessary to produce any program included on this disk: accstart.o - accessory program startup apstart.o - application program startup osbind.o - calls for Atari TOS and bios traps libf - floating point library vdibind - GEM VDI call bindings aesbind - GEM AES call bindings See the batch files for a list of the specific link Zfiles necessary for a particular program. Note that some of these programs use separate resource files. In some cases, the resource file C sources are included. In all cases, at least the .RSC file itself is included. Creating a .RSC file from the sources is a difficult thing to do. We suggest you use DRI's resource editor (on the sources, of course) if you want to change any of these separate resources. All of these programs work with Alcyon C, the compiler provided with the programmer's toolkit. Many of them were developed using Megamax C. Most if not all of them will port directly to Megamax. as68 -l -u karate.s as68 -l -u coeutil.s cp68 newmouse.c newmouse.i c068 newmouse.i newmouse.1 newmouse.2 newmouse.3 -f rm newmouse.i c168 newmouse.1 newmouse.2 newmouse.s rm newmouse.1 rm newmouse.2 as68 -l -u newmouse.s rm newmouse.s link68 newmouse.68k=apstart,newmouse,coeutil,karate,osbind,vdibind,aesbind rm newmouse.o rm karate.o rm coeutil.o relmod newmouse rm newmouse.68k wait j4J|BK|CJg&|kB|kR4(TQAIK,6fj`8¼4(TIK6f6`F4(TIK6f(P2(HhJ|g`<JgJ(Rk (d!@$(d!BdJf!|dtGa,kBRhJ(RShLfB@NuKNu- -+ --) --+) ---++ --++++ ---+++) 6$,- -+) --+) ---+) ---++) ----++) 6246$$$$$ ,,-) ----) -) -) 662622446$$$,,,) ----) ----+) -) 6622666266624466$$$$,,,-- ---++) ----++) 6666266662666624466244462$,,,,-) ,,,-+)) 66662266662246662244462244666246$,- 6666222666622266662226666222444462246246$0`Q>` Efv*oM& m HPHUBg?<JNA(m)m -:gS)@ -OK1PC#HN*Hx?<HNA@)@l/?<HNA)@h&@)@XЬl)@d)@`ARCpr Ѝ"QHNFALNNHz2?< NA\pdAxr0XQ)K\NN~JrBjNuHz?<&NN\NCAp$L Qp N9lrBlJpNNpMN9@pdAr 0Q0tr N9lNupealp`NuaNJHz?<&NNBWNANC2A@p222NrҌ0<NB0,rNurA9Ar`v C9Cr`rt9@9A9BNrrҌpsNB0,Nu9@N`rDҌpsNBNuC2 @ e @}bA@p222Nr,Ҍ0<NBNu    -pa4|a@:>< |a60Gg RGj`a(0GVfA1G<ap??<?<NM\Nu??< NMXNuvN)@p `H@)@prtNAHplrtNB 2pNpNpapaprapalpalpalpaTpaTpaTBp'a?<NNT@B){L9|0<rtNpapap9@p`pvNv`v`vj`v `v`v`v`?H ld$l`"Hg: k&@0+R`g k#&@0+S@H3 Q&f)I`LNup`pNu)H9@Jp4NP'J&f H LNu P&NuQ'` J,'fJ,&gHA#ȇeC! B,&LNu-W)K20, 8k8&@ gJl&f"Nu , 8g"P 8 @/, 8NX  8fQ 8J,'gNupB <``L@ H)l26)z @W , Jf`CfSHj-D@Hd0H@H 0H@0`fSC\fS , @a"C\fApNNNHP?< NA\NuH@aa/a a Nu@0 9c^Nu| PC>$Error # ][Abort]\f.B &lX)K\)ld` lp ,BQjNup(NV"l`Yd&-KNN"l`YepNpp@pWBg?<NN\pp@pW?<?<NN\pp@pW?<?<NN\pp@pW?<?<NN\N