Alexander Podkolzin ABC GROUP EXTRACTOR APP@nw.sbank.e-burg.su 11-12-96 (11:34) PB 138 3650 ABCXTRAC.BAS'-------------------------------------------------------------------------π' ABC group extractor. Extracts all "*.BAS" files from a group (*.ABC).π' I cann't explain all details about ABC structures, as (1) - I am notπ' the author of ABCREAD programme and (2) - it is copyrighted byπ' the ABC programmer - William Yu !π' I'd recommend to use ABC extractor separately from your main ABC archive,π' in a "temp" directory. Copy to it ABC extractor and a group file you'vπ' chosen.π' I do not give you any warranty, use it on your own risc!π'-------------------------------------------------------------------------π DEFINT a-zπ'π s$ = LTRIM$(RTRIM$(COMMAND$))π'π IF NOT FileHere(s$) OR s$ = "" THENπ PRINT "File not found !"π ENDπ END IFπ'π d = INSTR(s$,".")π'π IF MID$(s$,d+1,3) <> "abc" OR d = 0 THENπ PRINT "It's not ABC file!"π ENDπ END IFπ'π NameFile$ = s$π'π'π ABCD$ = CHR$(227)π %FALSE = 0π %TRUE = NOT %FALSEπ %MaxLen = 1024π'π CLSπ PRINT "Extracting :"π Position& = 0π source = FREEFILEπ OPEN NameFile$ FOR BINARY AS sourceπ DOπ Buffer$ = space$(%MaxLen)π SEEK #source, Position&π GET$ #source, %MaxLen, Buffer$π d = INSTR(Buffer$,ABCD$)π'π IF d = 0 THENπ EXIT LOOPπ ELSEIF d = 1 THENπ Buffer$ = ""π ELSEπ Buffer$ = LEFT$(Buffer$,d-1)π END IFπ'π INCR Position&,dπ'π IF LEN(Buffer$) > 165 THENπ'π' There are in ABC packets chars with code=0 (<32) sometimes, soπ' we have to remove them...π'π Buffer$ = RemoveRubbish$(Buffer$)π'π IF OnlyDigits(MID$(Buffer$,140,11)) THENπ CLOSE dest 'π DestName$ = MID$(Buffer$,154,12)π PRINT destname$π dest = FREEFILEπ OPEN DestName$ FOR output AS destπ'π' Header:π'π PRINT #dest,CHR$(39)+STRING$(75,45)π PRINT #dest,CHR$(39)+" Author : "+MID$(Buffer$, 1,31)π PRINT #dest,CHR$(39)+" Subject : "+MID$(Buffer$,32,30)π PRINT #dest,CHR$(39)+" Origin : "+MID$(Buffer$,63,30)π PRINT #dest,CHR$(39)+" Date : "+MID$(Buffer$,94,22)π PRINT #dest,CHR$(39)+" System : "+MID$(Buffer$,117,22)π PRINT #dest,CHR$(39)+STRING$(75,45)π'π PRINT #dest,CHR$(39)π PRINT #dest,MID$(Buffer$,166)π END IFπ ELSEπ PRINT #dest,Buffer$π END IFπ'π LOOPπ CLOSE ' All filesπ'π PRINT "Thank you for using this program!"π'π ENDπ'π'--------------------------------------------------------------------------π FUNCTION FileHere%(FileNAME$)π s$=DIR$(FileNAME$)π IF LEN(s$)=0 THENπ FUNCTION = %FALSEπ ELSEπ FUNCTION = %TRUEπ END IFπ END FUNCTIONπ'--------------------------------------------------------------------------π FUNCTION OnlyDigits%(s$) ' Checks if s$ contains only digitsπ'π IF LEN(s$) = 0 THENπ FUNCTION = 0π EXIT FUNCTIONπ END IFπ'π s$ = REMOVE$(s$,ANY " 0123456789")π'π IF LEN(s$) = 0 THENπ FUNCTION = %TRUEπ ELSEπ FUNCTION = %FALSEπ END IFπ'π END FUNCTIONπ'---------------------------------------------------------------------------π FUNCTION RemoveRubbish$(s$)π'π DIM PTR AS BYTE PTRπ DIM ptr0 AS BYTE PTRπ'π ptr0 = STRPTR32(s$)π'π FOR i%=0 TO LEN(s$)-1π PTR = ptr0+i%π IF @ptr < 32 THENπ @ptr = 32π END IFπ NEXTπ'π FUNCTION = s$π'π END FUNCTIONπ'--------------------------------------------------------------------------πTyler Barnes UPDATE OF BASE CONVERSION comp.lang.basic.misc 11-14-96 (16:16) QB, QBasic, PDS 32 1381 BASE.BAS 'Here's an update to my base conversion thing. This version is smaller,π'faster, and neater. (I simplified a part at the end and removed some ofπ'the exponent stuff I was doing.)ππDECLARE SUB Base2Base (Number1$, Digits1$, Number2$, Digits2$)πCONST Bin = "01", Oct = "01234567", Dec = "0123456789", Hex = "0123456789ABCDEFππSUB Base2Base (Number1$, Digits1$, Number2$, Digits2$)πNumber1$ = UCASE$(Number1$): Digits1$ = UCASE$(Digits1$)πDigits2$ = UCASE$(Digits2$): Number2$ = ""πIF Digits1$ <> "0123456789" THENπFOR I% = LEN(Number1$) TO 1 STEP -1πIF Digits1$ = "01234567" THEN FinalNum& = VAL("&O" + Number1$): EXIT FORπIF Digits1$="0123456789ABCDEF" THEN FinalNum&=VAL("&H"+Number1$):EXIT FORπCD$ = MID$(Number1$, I%, 1)πCV% = INSTR(Digits1$, CD$) - 1πFinalNum& = FinalNum& + (CV% * (LEN(Digits1$) ^ ABS(I% - LEN(Number1$))))πNEXT I%πELSEπFinalNum& = VAL(Number1$)πEND IFπIF FinalNum& < 0 THEN FinalNum& = FinalNum& + 65536πIF Digits2$ = "0123456789" THEN Number2$ = LTRIM$(STR$(FinalNum&)): EXIT SUBπIF Digits2$ = "0123456789ABCDEF" THEN Number2$ = HEX$(FinalNum&): EXIT SUBπIF Digits2$ = "01234567" THEN Number2$ = OCT$(FinalNum&): EXIT SUBπDestBase% = LEN(Digits2$)πDOπRemainder% = FinalNum& MOD DestBase%πFinalNum& = (FinalNum& - Remainder%) / DestBase%πNumber2$ = MID$(Digits2$, Remainder% + 1, 1) + Number2$πLOOP UNTIL FinalNum& = 0πEND SUBπToshihiro Horie GRAPH INTEGRALS www.ocf.berkeley.edu/~horie 11-13-95 (00:00) QB, QBasic, PDS 133 4476 NINT.BAS DEFDBL A-Zπ'#####################################################################π'//GRAPH (ALMOST) ANY INTEGRAL WITHOUT KNOWING ITS ANALYTIC SOLUTIONπ'//PROGRAMMED FOR CALCULUS STUDENTSπ'//BY TOSHIHIRO HORIE 11/13/95π'//BASED ON SIMPSON.BAS BY T. Horieπ'#####################################################################πDECLARE SUB GRID (XC%, YC%, XS%, YS%, XN%, YN%)πON ERROR GOTO erπCONST FALSE = 0, TRUE = NOT FALSEπCONST e = 2.7182818#πVARS:π OPTION BASE 1π DIM SHARED ISECT(3)π DIM XOLD(2), YOLD(2), YP(2)ππ iformat$ = "X=+##.# Integral=+#######.###"π XS% = 640: YS% = 480: 'dimensions of screen 12π XC% = XS% \ 2: YC% = YS% \ 2π XM% = 10: YM% = 5: 'X AND Y DIMENSIONS OF GRIDπ XN% = XS% \ XM%: YN% = INT(XS% \ YM% * 1.33333)π XI = .2: 'coarseness of the plotted lineππMAIN:π GRID XC%, YC%, XS%, YS%, XN%, YN%π 'GOSUB EQUATION: 'get endpoints a and bπ 'LINE (a * XN% + XC%, 0)-(a * XN% + XC%, YS%), 7, , &HAAAAπ 'LINE (b * XN% + XC%, 0)-(b * XN% + XC%, YS%), 7, , &HBBBBπ x = -XC% / XN% - 1: GOSUB EQUATIONππDOπx = x + XIπ FOR N = 1 TO 2π'TRANSLATE TO SCREEN COORDINATES....π GOSUB EQUATIONπ IF y(N) > YM% THEN y(N) = YM%π IF y(N) < -YM% THEN y(N) = -YM%ππ XP% = x * XN% + XC%π YP%(N) = -y(N) * YN% + YC%π LINE (XOLD%(N), YOLD%(N))-(XP%, YP%(N)), N + 9π XOLD%(N) = XP%: YOLD%(N) = YP%(N)π NEXT NπLOOP WHILE x < (XC% / XN%)ππa = -XC% / XN%: PSET (-XC% * XN - 1, YC%)π'A=0:PSET (xc%, yc%):'to start at originπLOCATE 5, 1: COLOR 7: PRINT "Calculating...": COLOR 15ππCONST b = 0 'from definition of integral?πDO: '------------------------------------------------------------------πastart = aπN% = 10 '50 subdivisions (N% must be even!)πh = (b - a) / N% 'dx for each subdivisionπintegral = 0 'init integral to 0πs = 0 'init sumπx = a + h: GOSUB EQUATION: s = s + y(1) * 4πx = a + h + h 'init x position to startπFOR lp% = 1 TO N% - 2π GOSUB EQUATIONπ IF ((lp% - 1) MOD 2) = 0 THENπ s = s + y(1) * 2π ELSEπ s = s + y(1) * 4π END IFπ x = x + hπNEXT lp%πx = a: GOSUB EQUATION: s = s + y(1)πx = b: GOSUB EQUATION: s = s + y(1)ππ integral = -h / 3 * sπ xpi% = INT(astart * XN% + XC%)π ypi% = INT((-integral) * YN% + YC%)π LINE -(xpi%, ypi%), 14π LOCATE 60, 1π PRINT USING iformat$; astart; integral;π PALETTE 7, RND * 64: 'flash the Calculating promptππa = a + XIπIF INKEY$ <> "" THEN STOPπLOOP WHILE a < (XC% / XN%): '---------------------------------------------πENDππer:πy(1) = 0πRESUME NEXTππEQUATION:π'WARNING: you MUST set b=1 by definition, to get correct graph for LOGs.πy(1) = 1 / (1 + x ^ 2) ' take the integral of this function (for x>0)πy(2) = ATN(x) ' analytic solution+C (0 if don't know)π ' If we're lucky, this is zero, andπ ' the yellow and blue lines will overlap.π'y(1) = 2 * x / (1 + x ^ 4)π'y(2) = ATN(x ^ 2)πRETURNππDEFINT A-ZπSUB GRID (XC%, YC%, XS%, YS%, XN%, YN%) STATICπSCREEN 12: CLS : COLOR 15πWIDTH 80, 60: LOCATE 1, 1πPRINT "Basic Integral Grapher v1.0"πPRINT "uses Simpson's Rule for fast calc"πPRINT "by Toshihiro Horie 11/13/95"πPRINT "Internal revision: 11/25/95"πLOCATE 1, 58: PRINT "Today's date:"; DATE$πLOCATE 24, 4: PRINT "Scale: 1 unit= 1"ππLINE (XC, 0)-(XC, YS), 15: LINE (0, YC)-(XS, YC), 15: REM CenterπCN = -1πFOR X1 = XC TO XS STEP XNπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (X1, YC)-(X1, YC + 3), CLπ LINE (X1 + 1, YC)-(X1 + 1, YC + 3), CLπNEXT X1πCN = -1πFOR X1 = XC TO 0 STEP -XNπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (X1, YC)-(X1, YC + 3), CLπ LINE (X1 + 1, YC)-(X1 + 1, YC + 3), CLπNEXT X1πCN = -1πFOR Y1 = YC TO YS STEP YNπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (XC, Y1)-(XC + 4, Y1), CLπNEXT Y1πCN = -1πFOR Y1 = YC TO 0 STEP -YNπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (XC, Y1)-(XC + 4, Y1), CLπNEXT Y1πEND SUBππToshihiro Horie FUNCTION GRAPHER www.ocf.berkley.edu/~horie/ 11-24-96 (00:00) QB, QBasic, PDS 355 10174 FGRAPH.BAS ' Improved Function Grapher 'π' Log, scaling, incr, and root bugs fixed. 'π' Copyright (c) 1996 Toshihiro Horie 'ππCONST version = 6.72πDEFSNG A-ZπDECLARE FUNCTION atan! (x!)πDECLARE FUNCTION asin! (x!)πDECLARE FUNCTION acos! (x!)πDECLARE FUNCTION csc! (x!)πDECLARE FUNCTION sec! (x!)πDECLARE FUNCTION cot! (x!)πDECLARE FUNCTION log10 (x) : DECLARE FUNCTION ln (x)πDECLARE FUNCTION sinh (x) : DECLARE FUNCTION csch (x)πDECLARE FUNCTION cosh (x) : DECLARE FUNCTION sech (x)πDECLARE FUNCTION tanh (x) : DECLARE FUNCTION coth (x)πDECLARE FUNCTION acosh! (x!) : DECLARE FUNCTION asech! (x!)πDECLARE FUNCTION asinh! (x!) : DECLARE FUNCTION acsch! (x!)πDECLARE FUNCTION acoth! (x!) : DECLARE FUNCTION atanh! (x!)πDECLARE SUB grid (x1!, y1!, XS!, ys!, XC!, YC!, XN!, yn!, xm!, ym!)πDECLARE SUB radianmarks (XC, YC, XS, ys, XN)ππCLEAR , , 32767: 'allocate more stack to error handlerπON ERROR GOTO 60ππ'ln(x) divided by LOG(10)/LOG(e) gives common logπ'Common LOG is defined in function LOG10π'LN natural log is defined in func LNπCONST l = 2.3025851#πCONST e = 2.7182818#πCONST pi = 3.14159265357989#πCONST DX = 1 / 1048576ππ'##########################################################π XS = 640: ys = 480: 'dimensions of the screenπ xm = 10: ym = 16: 'X AND Y DIMENSIONS OF GRIDπ'##########################################################πππSCREEN 12: CLS : COLOR 15: LOCATE 1, 1πPRINT "FUNCTION GRAPHER Version "; versionπPRINT "by Toshihiro Horie Rev 04/06/96"πCOLOR 7: LOCATE 24, 4: PRINT "Scale: 1 green unit= 1"πGOSUB VARSπXC = XS \ 2: YC = ys \ 2πXN = XS / xm: yn = INT(XS / ym * 4 / 3)πincr = xm / XC * 4: M1 = 0πCALL grid(x1, y1, XS, ys, XC, YC, XN, yn, xm, ym)πREM =======================START GRAPHING!!!=================================πxi = incrπDEF SEG = 0: ' if scroll lock is on, then double the speedπIF (PEEK(&H417) AND &H10) THEN incr = incr * 2: DEF SEGππ'DRAW FIRST POINT.......................πx = -XC / XN - 1πGOSUB equationπXP = x * XN + XCπYP = -Y * yn + YCπPSET (XP, YP), 15ππDOπLOCATE 1, 67: PRINT TIME$π'....................................................KEY CHECK....πin$ = INKEY$: xmode = 1π IF in$ = "*" THEN xmode = 16π IF in$ = "+" THEN xmode = 4π IF in$ = "-" THEN xmode = 1 / 4π IF in$ = "." THEN xmode = 8π IF in$ = " " THEN xmode = -4: 'reverseπ IF in$ = "," THEN xmode = 1 / 8πxi = incr * xmodeππIF UCASE$(in$) = "Q" THEN GOSUB ASKπIF in$ = CHR$(27) THEN ENDπ'INCREMENT THE X, FIND SLOPE............π'if flat curve then speed upπ'IF ABS(M1) < .1 THEN xmode = 1.5πx = x + xiπGOSUB equationπM1 = (Y - yold) / (x - xold)π'.................................................BOUNDARY CHECK..1πIF Y > (YC / yn) + 16 OR Y < (-YC / yn) - 16 THENπ Errflag2 = 1π xi = incr * 2π GOTO SKIPπ ELSEπ xi = incrπEND IFπ'TRANSLATE TO SCREEN COORDINATES..................................1.5πXP = x * XN + XCπYP = -Y * yn + YCπIF Errflag2 = 1 THEN PSET (XP, YP), 15: Errflag2 = 0πIF Errflag = 1 THEN PSET (XP, YP), 15: Errflag = 0π'DRAW LINE F(X)...................................SLOPE CHECK.....2πIF ABS(M1) > 64 THEN xi = incr / 8πIF ABS(M1) > 256 THENπ ' vert asymptote - probablyπ 'LINE (XP, 0)-(XP, 479), 7, , &HCCCCπ xi = incr / 16π PSET (XP, YP), 15πELSEπ xi = incrπ LINE -(XP, YP), 15πEND IFπ'CIRCLE (XP, YP), 3, 12π'PSET (XP - 1, YP), 14: PSET (XP + 1, YP), 14: PSET (XP, YP), 14π'FIND CRITICAL POINTS.............................................3πIF MOLD * M1 < 0 THEN '(Mean Value Theorem)π CIRCLE (xold * XN + XC, -yold * yn + YC), 4, 11π COLOR 11π LOCATE 28, 4: PRINT USING "(+###.###"; xold;π PRINT USING ",+#####.###) "; yoldπ COLOR 15π PSET (XP, YP), 15πEND IFπSKIP:π'SHOW SLOPE AND X,Y COORDINATE....................................4πLOCATE 25, 4: PRINT USING "(+###.##"; x;πPRINT USING ",+#####.##) "; YπIF SGN(Y) * SGN(yold) <= 0 THEN '...............x-roots (misses mins)π LOCATE 27, 4: PRINT USING "RootX=###.##"; xoldπEND IFπMOLD = (Y - yold) / (x - xold)πxold = x: yold = YπIF x <> 0 THEN LOCATE 26, 4: PRINT USING "slope=+####.## "; MOLDππskip2:πLOOP WHILE x < (XC / XN)πENDπ'======================================================================ππASK:πxold = xπLOCATE 1, 1: PRINT STRING$(80, 255);πLOCATE 1, 1: INPUT "X COORDINATE"; x: GOSUB equation: y0 = Yπx = x + DX: GOSUB equation: der1 = (Y - y0) / (DX)πLOCATE 1, 38: PRINT USING "Y COORDINATE IS +######.###"; y0πLOCATE 2, 35: PRINT USING "1st DERIVATIVE IS +######.####"; der1πY = 0: y0 = 0: der1 = 0: x = xoldπRETURNππ60 :πxi = .05πXPE = x * XN + XC: CIRCLE (XPE, YC), 8, 8πLOCATE 25, 5: PRINT USING "Error: ####.## "; xπErrflag = 1πRESUME skip2ππVARS:π'fill in the polynomial's coefficients hereπ'Don't forget to take out the apostropheπ'before the Y=C4*X^4+C3*X^3... equationπ'note:CA/X, CB/X^2, etc. causes overflows near x=0πC4 = .2πC3 = 0πC2 = -1πC1 = 0πC0 = 2πCA = 0πCB = 0πCC = 0πRETURNππequation:π'=================================================================================================π'Use LOG10(X) instead of LOG(X) for common logs!!!!πY = e ^ xπ' y = C4 * X ^ 4 + C3 * X ^ 3 + C2 * X ^ 2 + C1 * X + C0 + CA / X + CB / X ^ 2 + CC / X ^ 3π' 4th 3rd 2nd 1st 0th -1th -2nd -3rdπ'=================================================================================================πRETURNππFUNCTION acos (x)π'0<=y<=piπIF x < 0 THENπ acos = ATN(SQR(1 - x * x) / x) + piπELSEIF x = 0 THENπ acos = pi / 2πELSEπ acos = ATN(SQR(1 - x * x) / x) '(normal)πEND IFπEND FUNCTIONππFUNCTION acosh (x)π'x >= 1πacosh = ln(x + SQR(x ^ 2 - 1))πEND FUNCTIONππFUNCTION acoth (x)π'│x│ > 1πacoth = .5 * ln((x + 1) / (x - 1))πEND FUNCTIONππFUNCTION acsch (x)π'x <> 0πacsch = ln(1 / x + SQR(1 + x ^ 2) / ABS(x))πEND FUNCTIONππFUNCTION asech (x)π'0 < x ≤ 1πasech = ln((1 + SQR(1 - x ^ 2)) / x)πIF x > 1 THEN ENDπEND FUNCTIONππFUNCTION asin (x)πasin = ATN(x / SQR(1 - x * x))πEND FUNCTIONππFUNCTION asinh (x)πasinh = ln(x + SQR(x ^ 2 + 1))πEND FUNCTIONππFUNCTION atan (x)πatan = ATN(x)πEND FUNCTIONππFUNCTION atanh (x)π'│x│ < 1πIF x >= 1 THEN ENDπatanh = .5 * ln((1 + x) / (1 - x))πEND FUNCTIONππFUNCTION cosh (x)πcosh = (e ^ x + e ^ -x) / 2πEND FUNCTIONππFUNCTION cot (x)πcot = 1 / TAN(x)πEND FUNCTIONππFUNCTION coth (x)π'undefined at x=0πcoth = 1 / tanh(x)πEND FUNCTIONππFUNCTION csc (x)πcsc = 1 / SIN(x)πEND FUNCTIONππFUNCTION csch (x)π'undefined at x=0πcsch = 1 / sinh(x)πEND FUNCTIONππSUB eqsπ' y = (PI / 2 - X) * TAN(X)π' y = sinh(x)π' Y = atanh(x)π' Y = tanh(X)π' Y = (2 * x) / (SQR(x ^ 2 + x + 1)) 'AP CALC AB 1995 #1Bπ' Y = (X + 2) / (X ^ 2 + X + 1) ^ 1.5 '1st der #1Bπ' Y = e ^ (-X ^ 2) 'Bell curveπ' Y = -2 * X * e ^ (-X ^ 2) '1st derπ' Y = 2 * X * e ^ (-X ^ 2) * (2 * X ^ 2 - 1) '2nd derπ' Y = X * ln(X)π' --above are test questions from ch7π' Y = (1 / X ^ 2) ^ Xπ' Y = (2 ^ (COS(X) - 2)) / Xπ' Y = (3 ^ (SIN(X) - 1)) / Xπ' Y = X ^ (X + 1)π' Y = X ^ ln(X)π' Y = X ^ (-SQR(3))π' Y = X ^ (SQR(2))π' Y = (1 + 1 / X) ^ X 'e AS X->infinityπ' Y = X ^ (1 / X)π' Y = X ^ (1 / ln(X))π' Y = (ln(X)) ^ (-2)π' Y = 1 / x - 1 / SQR(x) '\________π' Y = X * (1 - COS(X)) / (X - SIN(X)) '\/~~~^~~~\/π' Y = (ln(X)) ^ 2π' Y = e ^ x - x + 3 * SIN(5 * x) - 2π' Y = 1 - 2 * COS(x) ^ 3ππEND SUBππSUB grid (x1, y1, XS, ys, XC, YC, XN, yn, xm, ym)ππFOR x1 = XC TO XS STEP XN: LINE (x1, 0)-(x1, ys), 10, , &HAAAA: NEXT x1: REM Vertical downπFOR x1 = XC TO 0 STEP -XN: LINE (x1, 0)-(x1, ys), 10, , &HAAAA: NEXT x1: REM Vertical upπFOR y1 = YC TO ys STEP yn: LINE (0, y1)-(XS, y1), 2, , &HAAAA: NEXT y1: REM Horizontal rightπFOR y1 = YC TO 0 STEP -yn: LINE (0, y1)-(XS, y1), 2, , &HAAAA: NEXT y1: REM Horizontal leftππCN = -1πFOR x1 = XC TO XS STEP XNπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (x1, YC)-(x1, YC + 3), CLπ LINE (x1 + 1, YC)-(x1 + 1, YC + 3), CLπNEXT x1πCN = -1πFOR x1 = XC TO 0 STEP -XNπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (x1, YC)-(x1, YC + 3), CLπ LINE (x1 + 1, YC)-(x1 + 1, YC + 3), CLπNEXT x1πCN = -1πFOR y1 = YC TO ys STEP ynπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (XC, y1)-(XC + 4, y1), CLπNEXT y1πCN = -1πFOR y1 = YC TO 0 STEP -ynπ CN = CN + 1: IF CN MOD 5 = 0 THEN CL = 12 ELSE CL = 14π LINE (XC, y1)-(XC + 4, y1), CLπNEXT y1πCOLOR 15: LOCATE 30, 1π'PRINT "▒ KEYBOARD GUIDE: [*] for WARP, [+] for FAST, [-] FOR SLOW, [Escape] to stop. ▒";πLOCATE 29, 60: PRINT "[" + LTRIM$(STR$(-xm \ 2)) + "," + LTRIM$(STR$(-ym \ 2)) + "]";πPRINT "x[" + LTRIM$(STR$(xm \ 2)) + "," + LTRIM$(STR$(ym \ 2)) + "]";ππLINE (XC, 0)-(XC, ys), 15: LINE (0, YC)-(XS, YC), 15: REM Centerππradianmarks XC, YC, XS, ys, XNππEND SUBππFUNCTION ln (x)π'the LOG function in QBASIC returns natural log for some odd reason...πln = LOG(x)πEND FUNCTIONππFUNCTION log10 (x)πlog10 = LOG(x) / lπEND FUNCTIONππSUB radianmarks (XC, YC, XS, ys, XN)πCL1 = 9: CL2 = 4πCN = -1: FOR x1 = XC TO XS STEP (XN * pi / 2)π CN = CN + 1: IF CN MOD 2 = 0 THEN CL = CL1 ELSE CL = CL2π LINE (x1, YC)-(x1, YC - 3), CLπ DRAW "D2R1L2R1"π 'LINE (X1 + 1, YC)-(X1 + 1, YC - 3), CLπNEXT x1πCN = -1: FOR x1 = XC TO 0 STEP (-XN * pi / 2)π CN = CN + 1: IF CN MOD 2 = 0 THEN CL = CL1 ELSE CL = CL2π LINE (x1, YC)-(x1, YC - 3), CLπ DRAW "D2R1L2R1"π 'LINE (X1 - 1, YC)-(X1 + 1, YC - 3), CLπNEXT x1πEND SUBππFUNCTION sec (x)πsec = 1 / COS(x)πEND FUNCTIONππFUNCTION sech (x)πsech = 1 / cosh(x)πEND FUNCTIONππFUNCTION sinh (x)πsinh = (e ^ x - e ^ -x) / 2πEND FUNCTIONππFUNCTION tanh (x)πtanh = sinh(x) / cosh(x)πEND FUNCTIONπMattias Andersson ANSI FIRE phobia2@hotmail.com 11-05-96 (15:55) QB, QBasic, PDS 270 6765 ANSIFIRE.BAS' Ok, I'm back again... (Phobia that is...)π' This time I've made a flame in textmode...π' Errr... Comment or something...π'π' phobia2@hotmail.comπ'π' Don't tell me how slow it is... I know how slow it is...π' QB is kinda limited when it comes to speed...π' And the source isn't in any way optimized... most of you canπ' probably make a flame that 1000 times faster...π' But I was first! :-)π' And I don't wanna comment this one... to mezzy source...π' Just love it or hate it...π'π' See ya later!π'πDECLARE SUB addcol ()πDECLARE SUB plot (x1!, y1!, c1!)πx = 1πy = 20πn = 1πWIDTH 80, 50πCLSπFOR a = 20 TO 40π plot a, 20, 9π plot a, 21, 9πNEXT aπRANDOMIZE TIMERππhej:πn = n + 1πIF n = 500 THENπ nn = 20π n = 0πnewline:π c2 = INT(RND * 3)π IF c2 = 2 THEN c2 = 9π IF c2 = 3 THEN c2 = 1π IF c2 = 1 THEN c2 = 1π plot 1 + nn, 20, c2π plot 1 + nn, 21, c2π nn = nn + 1π IF nn = 40 THEN GOTO newslutπ GOTO newlineπnewslut:πEND IFπcol = 0πcoll = SCREEN(y, x, 1)πteck = SCREEN(y, x)πIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπcoll = SCREEN(y + 1, x, 1)πteck = SCREEN(y + 1, x)πIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπcoll = SCREEN(y, x + 1, 1)πteck = SCREEN(y, x + 1)πIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπcoll = SCREEN(y + 1, x + 1, 1)πteck = SCREEN(y + 1, x + 1)πIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπIF y > 1 THENπ coll = SCREEN(y - 1, x, 1)π teck = SCREEN(y - 1, x)πEND IFπIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπIF x > 1 THEN coll = SCREEN(y, x - 1, 1)πIF x > 1 THEN teck = SCREEN(y, x - 1)πIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπIF x > 1 THENπ IF y > 1 THENπ coll = SCREEN(y - 1, x - 1, 1)π teck = SCREEN(y - 1, x - 1)π END IFπEND IFπIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπIF x > 1 THENπ coll = SCREEN(y + 1, x - 1, 1)π teck = SCREEN(y + 1, x - 1)πEND IFπIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπIF y > 1 THENπ coll = SCREEN(y - 1, x + 1, 1)π teck = SCREEN(y - 1, x + 1)πEND IFπIF coll = 15 THENπ col = col + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col = col + 8π IF teck = 178 THEN col = col + 7π IF teck = 177 THEN col = col + 6π IF teck = 176 THEN col = col + 5π IF teck = 32 THEN col = col + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col = col + 3π IF teck = 177 THEN col = col + 2π IF teck = 176 THEN col = col + 1π IF teck = 32 THEN col = col + 0πEND IFπcol = INT((col / 8) - .1)πIF y > 1 THEN plot x, y - 1, colππx = x + 1πIF x > 40 THENπ x = 20π y = y - 1π IF y < 1 THEN y = 20πEND IFπSELECT CASE INKEY$π CASE CHR$(27)π WIDTH 80, 25π CLSπ COLOR 7, 0π PRINT "Fire i textmode av Phobia 1996!"π ENDπEND SELECTπGOTO hejππSUB addcolπIF coll = 15 THENπ col! = col! + 9πEND IFπIF coll = 78 THENπ IF teck = 219 THEN col! = col! + 8π IF teck = 178 THEN col! = col! + 7π IF teck = 177 THEN col! = col! + 6π IF teck = 176 THEN col! = col! + 5π IF teck = 32 THEN col! = col! + 4πEND IFπIF coll = 4 THENπ IF teck = 178 THEN col! = col! + 3π IF teck = 177 THEN col! = col! + 2π IF teck = 176 THEN col! = col! + 1π IF teck = 32 THEN col! = col! + 0πEND IFπEND SUBππSUB plot (x1, y1, c1)πLOCATE y1, x1πIF c1 = 0 THEN COLOR 0, 0: PRINT " "πIF c1 = 1 THEN COLOR 4, 0: PRINT "░"πIF c1 = 2 THEN COLOR 4, 0: PRINT "▒"πIF c1 = 3 THEN COLOR 4, 0: PRINT "▓"πIF c1 = 4 THEN COLOR 14, 4: PRINT " "πIF c1 = 5 THEN COLOR 14, 4: PRINT "░"πIF c1 = 6 THEN COLOR 14, 4: PRINT "▒"πIF c1 = 7 THEN COLOR 14, 4: PRINT "▓"πIF c1 = 8 THEN COLOR 14, 4: PRINT "█"πIF c1 = 9 THEN COLOR 15, 0: PRINT "█"πEND SUBπMark Olson DISPLAY W/INT21H & ANSI.SYS FidoNet QUIK_BAS Echo 08-28-92 (12:55) QB, PDS 58 1986 ANSIWRIT.BAS'>> there any way to "redirect" them to ANSI.SYS instead of writing theπ'>> decoding routines myself?πππ'All Right I've read a couple of replies and most are correct as far asπ'displaying ANSI graphics, but just to throw in my two cents...ππ' ANSI graphis is the use of Escape codes to change Text Displayπ' Atributes and Display Related functions. There are several waysπ' of doing this. The one I have seen here is the use of CON: orπ' the Standard Output Device (Console). There is nothing wrongπ' with that aprroach BUT there is another avenue which accessπ' ANSI.SYS Directly Via Interrupt 21h sub-function 40h.ππ' ----------------------------- Ansi Routine ---------------------------π' QuickBasic 4.5 & PDS 7.X Modificationsπ' Use of Ansi.sys to display Ansi graphics at the current cursorπ' location. Using Int 21H Sub-Function 40H.ππDECLARE SUB AnsiWrite (Text$)ππ'Use QB.exe /L To load the quickbasic library QB.qblπ'Use QBX.exe /L To load the PDS 7.X Library QBX.qblππ'$INCLUDE: 'QB.BI'π' Use $include: QBX.bi for PDS 7.XππDIM SHARED RegsX AS RegTypeXππEsc$ = CHR$(27) ' Escape CharacterππTemp$ = ""ππWhite$ = Esc$ + "[0m" + Esc$ + "[37m"πBrYellow$ = Esc$ + "[1m" + Esc$ + "[33m"ππTemp$ = White$ + "This is a " + BrYellow$ + "Example " + White$ + "of ANSI!"ππCLSππAnsiWrite (Temp$)ππ' ---------------------------------------------------------------πSUB AnsiWrite (Text$)ππ RegsX.ax = &H4000 'AH = 40Hπ RegsX.bx = 1 'FILE HANDLEπ RegsX.cx = LEN(Text$) 'Number of Bytes to Writeπ RegsX.ds = VARSEG(Text$) 'Segment for the stringππ 'Use SSEG(Text$) Vice VARSEG(Text$) for PDS 7.1ππ RegsX.dx = SADD(Text$) 'Segment offset(address) of stringππ CALL InterruptX(&H21, RegsX, RegsX)ππEND SUBπ'------------------------------------------------------------------πB.S v/d Berg SECURE INPUT buzz@cyber-wizard.com 12-21-96 (13:13) ASIC 96 1884 INPUT.ASI sub "SecureINPUT" (a$,secure)ππrem *********************************************************πrem * yeah! *πrem * *πrem * i now it , you all waited for this. *πrem * a REALLY secure INPUT for asic *πrem * (you can't press ctrl-c) *πrem * *πrem * the secure parameter is 1 when you want to have '¿'s *πrem * (like passwords) *πrem * it is 0 when you want to see the input *πrem * *πrem *********************************************************πrem * *πrem * (c) buzz '96 *πrem * *πrem * http://ddsw.bos.nl/~buzz *πrem * buzz@cyber-wizard.com *πrem * *πrem *********************************************************ππback$=chr$(8)πenter$=chr$(13)πesc$=chr$(27)πa$=""πtemp$=""ππjoe:ππi$=inkey$πif i$="" then joe:ππif i$=back$ then backspace:πif i$=enter$ then enter:πif i$=esc$ then wis:ππtemp$=temp$+i$πif secure=1 thenπ print "¿";πelseπ print i$;πendifππgoto joe:πππbackspace:ππl=len(temp$)πa=pos(0)πb=csrlinππif l=0 thenπ sound 10000,1π goto joe:πendifππl=l-1πa=a-1ππlocate b,aπprint " ";ππlocate b,aππtemp$=left$(temp$,l)ππgoto joe:πππwis:ππl=len(temp$)πa=pos(0)πb=csrlinπc=a-lπt$=space$(l)ππlocate b,cπprint t$;πlocate b,cππtemp$=""ππgoto joe:πππenter:ππa$=temp$ππprintππendsub (a$,secure)ππRick Elbers ASSEMBLY IN QBASIC 2: DATASEG t030611@tip.nl 12-01-96 (05:37) QB, QBasic, PDS 124 4066 DATASEG.BAS 'ASSEMBLY IN QBASIC PART 2: USING DATASEGMENTSπ'----------------------------------------------π'Rick Elbers november 1996ππ'This short article is ment as a follow up on STEPHAN van Loendersloot'sπ'INTERRUPTS IN QBASIC in this directory. He described the very first stepπ'in calling CALL ABSOLUTE and this article will introduce the logicalπ'second step. It will very basically describe the way in which you canπ'use DATASEGMENTS in your assembler subs.ππ'The actual explanation will be done by working throught a very simpleπ'print string example. It is not ment to be anything fancy, but it isπ'designed to be evident.ππDECLARE SUB dosprstr (string2write$)πDECLARE FUNCTION int2str$ (sword%)πDECLARE SUB Pokestring (SEGJE%, OFFJE%, MAIN$)ππdosprstr "What are we going to do ?"πENDππSUB dosprstr (string2write$)π'-------------------------------------------------------------------------π'DATAπa% = LEN(string2write$) + 1: DIM datas%(a% \ 2 + 1)π'-----------------------------π'INTRODUCTION ON DATASEGMENTS:π'------------------------------π'DATAS will be our datasegment. Take good care that we declare it as anπ'array since arrays start at segment bounderies. That way we will not beπ'surprised by segment changes. This might be trivial but when you useπ'a simple variable which is number Xth in the row of variables it just mightπ'be that your starting adress is at seg:&hfffe. Same holds for stringvariables.π'They do not start at segmentbounderies too. Another feature of stringsπ'is that they walk around in memory due to garbage collection, making aπ'string very unsuited for adressability purposes. So: we use DATAS% and pokeπ'our variables and strings just inside it!ππ'The length of the datasegment in this example is designed to keep onlyπ'the string.ππb$ = string2write$ + "$" 'This is the way DOS processes stringprintπ'--------------------------------π'MAKE THE DATASEGMENT ADRESSABLE:π'--------------------------------π'Here is the basic upset of an adressable datasegment:ππdataseg% = VARSEG(datas%(0)): dataoff% = VARPTR(datas%(0))πdataseg$ = int2str$(dataseg%): dataoff$ = int2str$(dataoff%)ππ'Next we poke our string into the datasegment.πPokestring dataseg%, dataoff%, b$ππ'-----------------------------------π'CODEπ'push axπ'push dxπ'push dsππ'mov ax,dataseg$π'mov ds,axπ'mov dx,dataoff$π'mov ah,09 'printstring with ending $π'int 21π'pop dsπ'pop dxπ'pop axπ'retfπ'-----------------------------------π'pushaπasm$ = asm$ + CHR$(&H50)πasm$ = asm$ + CHR$(&H52)πasm$ = asm$ + CHR$(&H1E)ππasm$ = asm$ + CHR$(&HB8) + dataseg$ 'MOV AX,DATASEG$πasm$ = asm$ + CHR$(&H8E) + CHR$(&HD8) 'MOV DS,AXπasm$ = asm$ + CHR$(&HBA) + dataoff$ 'MOV DX,DATAOFF$πasm$ = asm$ + CHR$(&HB4) + CHR$(&H9) 'MOV AH,9πasm$ = asm$ + CHR$(&HCD) + CHR$(&H21) 'INT 21ππ'popaπasm$ = asm$ + CHR$(&H1F)πasm$ = asm$ + CHR$(&H5A)πasm$ = asm$ + CHR$(&H58)π'retfπasm$ = asm$ + CHR$(&HCB)π'________________________________________πCodeoff% = SADD(asm$)πDEF SEG = VARSEG(asm$)πCALL ABSOLUTE(Codeoff%)π'________________________________________πDEF SEGπππEND SUBππFUNCTION int2str$ (sword%)π'This function is translating SWORD Integers into a string. Its only useπ'is when you still use asm$ for assembler functions( like i do). In thatπ'case you can make your integer values usable ..π'THis function simply translates the hexa bytesπ'into stringbytes as is.π'----------------------------------------------------πDEF SEG = VARSEG(sword%)πptr% = VARPTR(sword%)πint2str$ = CHR$(PEEK(ptr%)) + CHR$(PEEK(ptr% + 1))πDEF SEGππEND FUNCTIONππSUB Pokestring (SEGJE%, OFFJE%, MAIN$)π'------------------------------------------------------π'This function pokes a string (might be ASCIIZ)intoπ'memory at a given location, making it possible toπ'access strings in byte formπ'------------------------------------------------------ππDEF SEG = SEGJE%πFOR i% = 0 TO LEN(MAIN$) - 1π POKE OFFJE% + i%, ASC(MID$(MAIN$, i% + 1, 1))πNEXTπDEF SEGππEND SUBπRick Elbers ASSEMBLY IN QBASIC 3: INT86QB t030611@tip.nl 12-01-96 (05:37) QB, QBasic, PDS 175 8442 INT86QB.BAS 'ASSEMBLY IN QBASIC 3: INT86QBπ'QBASIC ABOVE AND BEYOND PART...[ASSEMBLY LIBRARIE]π'---------------------------π'Rick Elbers november 1996π'--------------------------πDECLARE FUNCTION int2str$ (sword%)πDECLARE FUNCTION int86qb$ (intnr%, flag%, ax%, bx%, cx%, dx%, di%, si%, bp%, ds%, es%)ππ'INTRODUCTION π'-------------π'When i felt the desire to write a routine that make another break in theπ'wall of QBASIC opponents who maintain that QBASIC did not have a callπ'interrupt, i have choosen for the ASIC approach which distinguishesπ'itself from QUICK BASIC(compiler) in that it did not force upon youπ'the necessity of defining a REGSTYPE in your main.π'In my humble opinion you should hold things as modulair as possible,meaningπ'as much as possible defined in your subs and functions. So therefore, insteadπ'of INTERRUPT(int%,INREGS as REGStype,OUtregs as REGStype), you willπ'be confronted with INT86QB(int%,FLAG%,AX%,BX%,CX%,DX%,DI%,SI%,BP%,DS%,ES%)π'Since it is a function it returns. In fact it returns an array of all theπ'registers. For help in parsing this you might take a look at the functionπ'partstring$ i wrote( available on my homepage in Lstr.zip).ππ'First notice should be that int86qb returns also flags (unlike int86 of ASIC)π'----------------------------------------------------------------------------πCLSπa$ = int86qb$(&H21, 0, &H200, 0, 0, &H41, 0, 0, 0, 0, 0)πLOCATE 2, 1: PRINT a$ππ'----------------------------------------------------------------------------π'Although the setup of this function might have his advantages, optimal speedπ'or minimum length is not one of them. In an optimized CALL INTERRUPT theπ'assembly routine could be speeded up *a lot* AND narrowed down to 80 bytes,π'by the way of using STACK instead of DATAS% and XCHG reg, variable insteadπ'of PUSH reg /MOV reg,value/ MOV variable, reg/POP reg instructions. The onlyπ'advantage of the present int86qb routine might be that it is not as difficultπ'as the routine that uses the optimized method, since for the biggest partπ'int86qb is merely repetitive.π'----------------------------------------------------------------------------ππFUNCTION int2str$ (sword%)π'This function is translating SWORD Integers into a string. Its only useπ'is when you still use asm$ for assembler functions( like i do). In thatπ'case you can make your integer values usable ..π'THis function simply translates the hexa bytesπ'into stringbytes as is.π'----------------------------------------------------πDEF SEG = VARSEG(sword%)πptr% = VARPTR(sword%)πint2str$ = CHR$(PEEK(ptr%)) + CHR$(PEEK(ptr% + 1))πDEF SEGππEND FUNCTIONππFUNCTION int86qb$ (intnr%, flag%, ax%, bx%, cx%, dx%, di%, si%, bp%, ds%, es%)π'------------------------------------------------------------------------π'Conversion of all integers in stringsπflag$ = LEFT$(int2str$(flag%), 1): ax$ = int2str$(ax%):πbx$ = int2str$(bx%): cx$ = int2str$(cx%): dx$ = int2str$(dx%):πdi$ = int2str$(di%): si$ = int2str$(si%): bp$ = int2str$(bp%):πds$ = int2str$(ds%): es$ = int2str$(es%):π'Now all integersvalues are direct usable in asm$π'------------------------------------------------------------------------πDIM datas%(11) 'that is all we needπdataseg% = VARSEG(datas%(0)): flagoff% = VARPTR(datas%(0))πdataseg$ = int2str$(dataseg%): flagoff$ = int2str$(flagoff%)πaxoff$ = int2str$(flagoff% + 2): bxoff$ = int2str$(flagoff% + 4)πcxoff$ = int2str$(flagoff% + 6): dxoff$ = int2str$(flagoff% + 8)πdioff$ = int2str$(flagoff% + 10): sioff$ = int2str$(flagoff% + 12)πbpoff$ = int2str$(flagoff% + 14): dsoff$ = int2str$(flagoff% + 16)πesoff$ = int2str$(flagoff% + 18): intnroff$ = int2str$(flagoff% + 20)π'Now all integers are directly adressable in memory through asm$π'We could have used only this as pointers and leave the immediate valuesπ'but....we don't.π'------------------------------------------------------------------------πasm$ = ""πasm$ = asm$ + CHR$(&H9C) 'pushf πasm$ = asm$ + CHR$(&H50) 'push ax πasm$ = asm$ + CHR$(&H53) 'push bx πasm$ = asm$ + CHR$(&H51) 'push cx πasm$ = asm$ + CHR$(&H52) 'push dx πasm$ = asm$ + CHR$(&H57) 'push di πasm$ = asm$ + CHR$(&H56) 'push si πasm$ = asm$ + CHR$(&H55) 'push bp πasm$ = asm$ + CHR$(&H1E) 'push ds πasm$ = asm$ + CHR$(&H6) 'push es ππ'2)LOAD REGISTERSπ'First the flags( questionable if this ever happens):πasm$ = asm$ + CHR$(&HB4) + flag$ 'mov ax,flag$πasm$ = asm$ + CHR$(&H9E) 'sahf stores ah into flagsππ'Segment registers mbv ax : only when not (accidentally) 0πIF ds% <> 0 THEN 'safetyπ asm$ = asm$ + CHR$(&HB8) + ds$ 'mov ax,ds$π asm$ = asm$ + CHR$(&H8E) + CHR$(&HD8) 'mov ds,axπEND IFπIF es% <> 0 THEN 'safetyπ asm$ = asm$ + CHR$(&HB8) + es$ 'mov ax,es$π asm$ = asm$ + CHR$(&H8E) + CHR$(&HC0) 'mov es,axπEND IFπ'the rest of registers :πasm$ = asm$ + CHR$(&HB8) + ax$ 'mov ax,ax$πasm$ = asm$ + CHR$(&HBB) + bx$ 'mov bx,bx$ πasm$ = asm$ + CHR$(&HB9) + cx$ 'mov cx,cx$ πasm$ = asm$ + CHR$(&HBA) + dx$ 'mov dx,dx$ πasm$ = asm$ + CHR$(&HBF) + di$ 'mov di,di$ πasm$ = asm$ + CHR$(&HBE) + si$ 'mov si,si$ πasm$ = asm$ + CHR$(&HBD) + bp$ 'mov bp,bp$π'oke now the interrupt himselfπasm$ = asm$ + CHR$(&HCD) + CHR$(intnr%) 'interrupt nrππ'First make our DATAS% adressable:πasm$ = asm$ + CHR$(&H1E) 'push dsπasm$ = asm$ + CHR$(&HB8) + dataseg$ 'mov ax,DATASseg$πasm$ = asm$ + CHR$(&H8E) + CHR$(&HD8) 'mov ds,axπ π'We first pushed DS segment register since we want to adress our DATA_segmentπasm$ = asm$ + CHR$(&H8F) + CHR$(&H6) + dsoff$ 'pop dsoff$πasm$ = asm$ + CHR$(&H8C) + CHR$(&H6) + esoff$ 'mov esoff$,ESππasm$ = asm$ + CHR$(&H9F) 'lahfπasm$ = asm$ + CHR$(&H88) + CHR$(&H26) + flagoff$ 'mov flagoff$,ahπ π'The rest is more simple i think:πasm$ = asm$ + CHR$(&H89) + CHR$(&H2E) + bpoff$ 'mov bpoff$,bpπasm$ = asm$ + CHR$(&H89) + CHR$(&H36) + sioff$ 'mov sioff$,siπasm$ = asm$ + CHR$(&H89) + CHR$(&H3E) + dioff$ 'mov dioff$,diπasm$ = asm$ + CHR$(&H89) + CHR$(&H16) + dxoff$ 'mov dxoff$,dxπasm$ = asm$ + CHR$(&H89) + CHR$(&HE) + cxoff$ 'mov cxoff$,cxπasm$ = asm$ + CHR$(&H89) + CHR$(&H1E) + bxoff$ 'mov bxoff$,bxπasm$ = asm$ + CHR$(&HA3) + axoff$ 'mov axoff$,axπ π'Now let us neatly finish by just popping everything back in orderπasm$ = asm$ + CHR$(&H7) 'pop esπasm$ = asm$ + CHR$(&H1F) 'pop ds πasm$ = asm$ + CHR$(&H5D) 'pop bp πasm$ = asm$ + CHR$(&H5E) 'pop si πasm$ = asm$ + CHR$(&H5F) 'pop di πasm$ = asm$ + CHR$(&H5A) 'pop dx πasm$ = asm$ + CHR$(&H59) 'pop cx πasm$ = asm$ + CHR$(&H5B) 'pop bx πasm$ = asm$ + CHR$(&H58) 'pop ax πasm$ = asm$ + CHR$(&H9D) 'popf π'We are done?πasm$ = asm$ + CHR$(&HCB) 'retf ππDEF SEG = VARSEG(asm$)πoffcode% = SADD(asm$): CALL absolute(offcode%): DEF SEGππui$ = HEX$(intnr%)πFOR i% = 0 TO 9π hx$ = HEX$(datas%(i%))π hx$ = STRING$(4 - LEN(hx$), "0") + hx$π ui$ = ui$ + "," + hx$πNEXTππint86qb$ = ui$ππEND FUNCTIONππSUB Pokestring (SEGJE%, OFFJE%, MAIN$)π'------------------------------------------------------π'This function pokes a string (might be ASCIIZ)intoπ'memory at a given location, making it possible toπ'access strings in byte formπ'------------------------------------------------------ππDEF SEG = SEGJE%πFOR i% = 0 TO LEN(MAIN$) - 1π POKE OFFJE% + i%, ASC(MID$(MAIN$, i% + 1, 1))πNEXTπDEF SEGππEND SUBπRick Elbers ASSEMBLY IN QBASIC 4: INTERRUPTt030611@tip.nl 12-01-96 (05:37) QB, QBasic, PDS 424 18258 DHANDLER.TXT'ASSEMBLY IN QBASIC 4: INTERRUPT HANDLERSπ'QBASIC ABOVE AND BEYOND PART....[DISCUSSION INTERRUPTHANDLERS]π'--------------------------------------------------------------------------π'Rick Elbers november 1996π'-------------------------πDECLARE FUNCTION newvec& (segnewint%, offnewint%)πDECLARE FUNCTION oldvec& (nr%)πDECLARE SUB getvec (Svec%, Ovec%, nr%)πDECLARE SUB pokeW (pokeseg%, pokeoff%, word%)πDECLARE SUB pokeDW (pokeseg%, pokeoff%, dword&)π π'INTRODUCTIONπ'-------------π'When we are concerned with interrupthandlers, then our first goal has to beπ'to establish the current way interrupts are handled. When some interrupt isπ'processed the processor retrieves the place to jump to (among other things).π'This place he retrieves from 0:INTNR*4. That is to say, in the lower memoryπ'all interrupts are mapped with a far pointer to the code for that interrupt.π'Of course, since we spoke about FAR pointers every interrupt pointer isπ'a double word. That is were the INTNR*4 is coming from. The interrupt pointersπ'are commonly referred to as VECTORS.ππ'GETTING THE INTERRUPT VECTORSπ'-----------------------------π'From inside our QBASIC ide we can get all vectors, but we have to keepπ'in mind that we only retrieve vectors as QBASIC looks at them. That is toπ'say that some interrupts are handled by qbasic itself, instead of by DOS.π'For instance the values for INT 0 and INT 4 are not the same that youπ'get from dumping the lower memory in debug...(you are encouraged to do so..)π'But otherwise the program to execute now is very instructive...ππCLSπFOR nr% = 0 TO &HFFπgetvec Vecseg%, Vecoff%, nr%πPRINT " Int "; STRING$(2 - LEN(HEX$(nr%)), "0"); HEX$(nr%); "->";πIF Vecseg% = 0 AND Vecoff% = 0 THENπ PRINT "Not used ";πELSEπ PRINT STRING$(4 - LEN(HEX$(Vecseg%)), "0"); HEX$(Vecseg%); ":";π PRINT STRING$(4 - LEN(HEX$(Vecoff%)), "0"); HEX$(Vecoff%);πEND IFπIF nr% MOD 4 = 3 THEN PRINTπIF nr% MOD 80 = 79 THEN SLEEPπNEXTπCLS : PRINT "press a key for next demo part"πSLEEPππ'We have seen that a lot of INTERRUPT VECTORS are free, so we canπ'experiment with them. Even when after controlling the so called "FREEπ'VECTORS" with debug they appear indeed free. So it is sure and safeπ'to experiment with INT 83h for instance. So be it: we will start withπ'developing a testcode for our newinterrupt, so that there will be noπ'misunderstandings wether we execute int 83h or not. Afterwards we willπ'do what is necessary to make it possible to execute int 83h. Ourπ'handler will do nothing fancy. He will simply print the character 'a' .π'-------π'NEWINTπ'-------πDIM newint%(6)πnewint%(0) = &H5052 'PUSH AX,DXπnewint%(1) = &H41B2 'MOV DL,41πnewint%(2) = &H2B4 'MOV AH,02πnewint%(3) = &H21CD 'INT 21πnewint%(4) = &H5A58 'POP DX,AXπnewint%(5) = &HCB 'RETFππsegnewint% = VARSEG(newint%(0)): offnewint% = VARPTR(newint%(0))π'Agreed ? Well let us control him:πDEF SEG = segnewint%: CALL absolute(offnewint%)πSLEEPπ'Seems to be oke, not ?π'--------------------------π'SETTING INTERRUPT VECTORSπ'--------------------------π'Since we have a working handler by now, we might process with the part ofπ'resetting the interrupt 83h vector( currently 0:0 ) to the adress of ourπ'handler( currently segnewint%:offnewint%). As it turns out QBASICπ'enables our capacity to set a vector with the DOScall INT 21, 25h. At leastπ'on my PC this call bumps( when somebody show me otherwise i'll be delighted).π'But for know let us take the more direct route, which is: changing the adressπ'stored at 0:83h*4ππsetvec:πDEF SEG = 0πPOKE (&H83 * 4), offnewint% AND &HFFπPOKE (&H83 * 4 + 1), offnewint% \ &HFFπPOKE (&H83 * 4 + 2), segnewint% AND &HFFπPOKE (&H83 * 4 + 3), segnewint% \ &HFFπSLEEPππ'OKE What we did here was storing the adress of our handlerπ'in the interrupt vector table in the form:π' DW SEG:OFFππ'Interesting enough in assembler you won't risk such a move since thereπ'could and in fact will be an interrupt during the writing to the vectorπ'adress and the vector will be stored inadekwately. One other thing:π'The interrupts are all far return adresses, which is just difficultπ'language for that they are words in the form segment:offset. THIS ISπ'NOT THE STANDARD WAY OF STORING A WORD! but INTEL designed it so...π'About the formulas used: ANDING AN INTEGER WITH &HFF will give you theπ'High Byte since 0000 0000 1111 1111 AND .... .... .... .... will resultπ'in zeroing the higher byte(agreed ?). The other way around works theπ'division which returns the higher byte in the lower byte.ππ'[in fact it is not ! for signed integers, luckely i know the segment ofπ'QBASIC is not a signed value so everything will role smoothly....For codeπ'that is always okay for signed integers look at the POKEW and POKEDW routines]ππ'controleπFOR i% = 0 TO 3π PRINT HEX$(PEEK(&H20C + i%));πNEXTπDEF SEGπSLEEPππ'So far we seems to be oke: allright ? Well lets review a bit. It isπ'called SETVEC wat we have done. It should be easy for you to make thisπ'into a callable sub. In general you have to poke to INTNR*4+something.π'May be it is just ok to do this first right now before going further...ππ'Okay so far,so good. Now the miracle itself. Will it work ? It is easy toπ'be so eager to try that you overlook one major change you have to makeπ'to our handler. It ended so far with RETF, but an interrupt restores theπ'flags also so we have to return with an Interrupt-return(IRET):πnewint%(5) = &HCF 'IRET replaces RETFππ'Okay now we are ready for the miracle. Have we developed an INTERRUPT ?π'Let's just call INT 83h and look what happens. PFFF........πDIM test%(2)πtest%(0) = &H83CD 'INT 83πtest%(1) = &HCB 'RETFππCLS : DEF SEG = VARSEG(test%(0))πCALL absolute(VARPTR(test%(0)))πDEF SEGππ'I do not know what your machine is saying but mine is printing 'a' !π'Is that all ? Yes, that is all. We have passed our first exam!πππ'INTERRUPT HANDLERS:part oneπ'----------------------------π'When we want to intercept an important interrupt like DOS INT 21 thenπ'it is obvious that we first must have the ability to store the vectorπ'so that we can put the original vector back after we are done. Since ourπ'int 83 can serve further as example interrupt let us call getvec forπ'int 83 and then store the vector.πππgetvec segvec%, offvec%, &H83πSavevec:πoldint83& = segvec% * 65536 + offvec%ππ'We are going to store the vector in one WORDvalue since 1)It reduces ourπ'variables with one. Therefore adding to clarity. 2) In essence the vectorπ'is just one variable. And while we store him this way we can with just oneπ'instruction like JMP OLDint83 return to our former handler.π'For control again:πPRINT HEX$(oldint83&)ππ'Agreed ? No ? Well you are right. This long integer is not really a DWπ'since INTEL choosed to put the vectors in the form off(flipped):seg(flipped)π'and not in the expected seg(flipped):off(flipped) way. This might beπ'a little confusing at first. But look at it this way: Because we store itπ'this way oldint83& is stored in the form off:seg.When later getvec looks atπ'the vectors in the table it reads excactly the offset at INTnr*4 and theπ'segment at INTnr*4+2. So indeed excactly our OLDINT83&!πππ'A SHORT_LONGCUT :π'--------------------π'Well,okay say we want to interrupt int 21h because we do not like the wayπ'function 0ah handles function-KEYS like <F1>( it do'nt). We are capable ofπ'getting the vector already. Also we can store the vector in an adekwate wayπ'and set the vector to our code. At a certain point we want to restore theπ'vector table again(Agreed ?), because we do not want to write code for allπ'INt 21h functions. At least not for free.....<G>. So we have to practice oneπ'other thing. That is :resetting a vector from the one we stored.ππ'Now let us return to our practice. We are writing int 83h. Let us now try toπ'reset the vector first to 0000:0000 what it was before we were so arrogant toπ'take over. This should be simple. Use setvec with SEGnewint%=0 AND OFFnewint%=0πSLEEPπDEF SEG = 0: POKE (&H83 * 4), 0: POKE (&H83 * 4 + 1), 0πPOKE (&H83 * 4 + 2), 0: POKE (&H83 * 4 + 3), 0:ππ'CONTROL:πgetvec segvec%, offvec%, &H83πPRINT HEX$(segvec%), HEX$(offvec%)πDEF SEGπ'agreed again ?πSLEEPππ'What was again the question: Oh,yes after Hooking DOS we will reset theπ'vector. Since we not put an int handler which interrupted our int 83H atπ'0000:0000, which we should by the way never even try, and since the conceptπ'of interrupting ourselves never managed to come clear to me, we just haveπ'to imagine we just stored our vector 0:0 at int 83h adres. So what isπ'left is that we want to restore the vector after done..Since we haveπ'oldint83& this should be simple not ? But poke just only writes bytes!π'this means you should write your own pokeDW. Not so..?ππ'DEF SEG = 0: POKEDW &H83 * 4, oldint83&: DEF SEGπ'and thats it.ππ'Control is now important.By the way does everybody knows that doshelp.comπ'and edit.com are QBASIC programs started up with QBASIC/edcom andπ'QBASIC/qhelp respectively ( so much for not compiler QBASIC ?)ππgetvec segvec%, offvec%, &H83πPRINT HEX$(segvec%); HEX$(offvec%): DEF SEG = 0πFOR i% = 0 TO 3: PRINT HEX$(PEEK((&H83 * 4) + i%)): NEXTππ'Okay while this whole document might seem a little bit childish in natureπ'you must agree that we are advancing...At this moment we know we canπ'restore vectors after using them. A very important feature...π'Also you could have stored the two procedures SETVEC and GETVEC by now iπ'guess, making your code even more evident. vecRestore is just a specificπ'Setvec and Savevec& is a)evident and b) needs POKE_DWππ'To advance we have to know some basics of an Interrupthandlerπ'--------------------------------------------------------------π'What an interrupt does is a whole lot, so be aware: An interruptπ'does push first the flags, then pushes cs:ip(return adress),then calculatesπ'vector adress as we do INTnr*4 loads up ip: then cs of the INTvec. Afterπ'done there is an IRET executed: meaning that first cs then ip then theπ'flags are restored from the stack( minus the interrupt and trap flag, whichπ'are cleared on return).π'In CODE: 'PUSHFπ 'PUSH CSπ 'PUSH IPπ 'vectoradressing: leave the MUL etc for knowπ 'JMP VECTORADRESSπ '...................π 'DOES WHATEVER HERE IS DONEπ '...................π 'POP IPπ 'POP CSπ 'POPFπ'Although not entiraly true this is sufficient knowledge for know. Fromπ'above it could be concluded that when writing an interrupthandler we haveπ'to do one extra thing when we define our handler as a far procedure( meaningπ'that apart from IP also CS is pushed). We have to do manually PUSHFπ'before jumping to the OLDINT and PopF them again as the OLDINT returnsπ'since the IRET at the end has POPF 'ed . After that we simulated theπ'INT call.!ππ'Okay before actually going into writing a real interrupt-handler we justπ'have to do lots more in the sector of making procedures,using labelsπ'in our asm-subs. I can tell one thing on before hand : the string wayπ'of going does not seem to survive procedures,using Data_array,labels etc.π'At least i am returning to a better way of the old code%().It is notπ'necessary to use datastatements, and clearity could even be incrementedπ'using also ASM comments( necessary for bigger asmsubs) in a header likeπ'in normal assemblerprograms with some modifications. Furthermore, arraysπ'does not wander around in mem, so they are adressable as procedures,datasπ'etc. At last, since you can use datas directly in your assemblersubs,theπ'external use of stack is dropping down to zero. This diminished a lot ofπ'code_space. Making the code more visible. Okay, i will return on the subject of Hooking Interruptπ'later......ππ'Let's round the whole thing off with rewriting our RestoreVEC. We shouldπ'be possible to directly write the VEC back using OLDINT83& ,not?π'Okay let us try.πgetvec segvec%, offvec%, &H83: PRINT HEX$(segvec%), HEX$(offvec%)π'reset the vec to 0?πpokeDW 0, &H83 * 4, 0πgetvec segvec%, offvec%, &H83: PRINT HEX$(segvec%), HEX$(offvec%)π'we seems to have it done.π'Now restore our vector ?πpokeDW 0, &H83 * 4, oldint83&πgetvec segvec%, offvec%, &H83: PRINT HEX$(segvec%), HEX$(offvec%)ππ'Maybe you agree that we accurataly restored a vector. Since probablyπ'the only purpose for getting a vector is to restore him at some timeπ'we might even change Getvec so that it reads one long integer in theπ'format segvec:offvec in our variable OlDINT&πPRINT HEX$(oldvec&(&H83))'seems to be ok?ππ'Ok now to summarize we can do the whole thing with enlightening speedπ'and shortness:πCLSπpokeDW 0, &H83 * 4, 0 'restore situation to startπoldint83& = oldvec&(&H83) 'get the original int83πpokeDW 0, &H83 * 4, segnewint% * 65536 + offnewint%π 'set our int83 vectorπDEF SEG = VARSEG(test%(0))πCALL absolute(VARPTR(test%(0))) 'execute our handlerπDEF SEGπpokeDW 0, &H83 * 4, oldint83& 'restore the original vectorπππ'Seems to be oke, not ? Apart from doing the whole thing in an assemblerπ'procedure i can see only one thing to improve codeshortness being toπ'write a function newvec&(segnewint%,offnewint%) which is trivialπ'but in the long run it rules out the flip INTEL confusion. Note that weπ'prepared us already on using assembler for the whole thing by consequentlyπ'loading up registers first,before writing to a BASIC variable( which is,π'can be argued, bad code viewed solely from here and now QBASICcode)ππ'part 2 to be released on my homepage.some time later will handle theπ'actual INT 21 handler.πππSUB getvec (d%, v%, nr%)ππd% = 1: v% = 2'variabele initialisatieπdataseg% = VARSEG(d%): offset% = VARPTR(d%)πdatasg$ = CHR$(dataseg% AND &HFF) + CHR$(dataseg% \ 256)πoffset1$ = CHR$(offset% AND &HFF) + CHR$(offset% \ 256)πoffset2$ = CHR$((VARPTR(v%) AND &HFF)) + CHR$((VARPTR(v%) \ 256))ππ'CODE IN QBASICπ'**************************************πππASM$ = ""πASM$ = ASM$ + CHR$(&HB4) + CHR$(&H35) 'MOV AH,35 πASM$ = ASM$ + CHR$(&HB0) + CHR$(nr%) 'MOV AL,INTnr πASM$ = ASM$ + CHR$(&HCD) + CHR$(&H21) 'INT 21 πASM$ = ASM$ + CHR$(&HB8) + dataseg$ 'MOV AX,dataseg$ πASM$ = ASM$ + CHR$(&H8E) + CHR$(&HD8) 'MOV DS,AX πASM$ = ASM$ + CHR$(&H8C) + CHR$(&H6) + offset1$ 'MOV ptr[seg],ESπASM$ = ASM$ + CHR$(&H89) + CHR$(&H1E) + offset2$' 'mov ptr[off],BX πASM$ = ASM$ + CHR$(&HCB) 'RETF πππ'____________________________π Codeoff% = SADD(ASM$)π DEF SEG = VARSEG(ASM$)π CALL absolute(Codeoff%)π'____________________________πDEF SEGππEND SUBππFUNCTION newvec& (segnewint%, offnewint%)πnewvec& = segnewint% * 65536 + offnewint%πEND FUNCTIONππFUNCTION oldvec& (nr%)π'-------------------------------------------------------------------'π'This function is a replacement of GETVEC. It stores the old vectorπ'in INTEL format in an long integer. INTEL format means in the formatπ'segment:offset here.π'The procedure first stores the vector in ES[BX], before we access itπ'IN: INTnr%π'OUT: oldvec&π'-------------------------------------------------------------------'πs% = 1: o% = 2'variabele initialisatieπdataseg% = VARSEG(s%): offset% = VARPTR(s%)πdatasg$ = CHR$(dataseg% AND &HFF) + CHR$(dataseg% \ 256)πoffset1$ = CHR$(VARPTR(s%) AND &HFF) + CHR$(VARPTR(s%) \ 256)πoffset2$ = CHR$(VARPTR(o%) AND &HFF) + CHR$(VARPTR(o%) \ 256)πππ'CODE IN QBASICπ'**************************************πππASM$ = ""πASM$ = ASM$ + CHR$(&HB4) + CHR$(&H35) 'MOV AH,35 πASM$ = ASM$ + CHR$(&HB0) + CHR$(nr%) 'MOV AL,INTnr πASM$ = ASM$ + CHR$(&HCD) + CHR$(&H21) 'INT 21 πASM$ = ASM$ + CHR$(&HB8) + dataseg$ 'MOV AX,dataseg$ πASM$ = ASM$ + CHR$(&H8E) + CHR$(&HD8) 'MOV DS,AX πASM$ = ASM$ + CHR$(&H8C) + CHR$(&H6) + offset1$ 'MOV ptr[seg],ESπASM$ = ASM$ + CHR$(&H89) + CHR$(&H1E) + offset2$' 'mov ptr[off],BXπASM$ = ASM$ + CHR$(&HCB) 'RETF πππ'____________________________π Codeoff% = SADD(ASM$)π DEF SEG = VARSEG(ASM$)π CALL absolute(Codeoff%)π'____________________________πDEF SEGπoldvec& = s% * 65536 + o%πEND FUNCTIONππSUB pokeDW (pokeseg%, pokeoff%, dword&)π'This function will just poke a Dword into memory, just likeπ'the standard function Poke does it, with one enhancement.π'While poke needs a def seg before it we will transfer that toπ'the function also! So :π'DW segment to poke word toπ'DW offset to poke word toπ'DD Dwordvalue to pokeπ'---------------------------------------------------------------πDEF SEG = VARSEG(dword&)πptr% = VARPTR(dword&)πLowWlowbyte% = PEEK(ptr%): LowWhighbyte% = PEEK(ptr% + 1)πHighWlowbyte% = PEEK(ptr% + 2): HighWhighbyte% = PEEK(ptr% + 3)ππDEF SEG = pokeseg%π POKE pokeoff%, LowWlowbyte%π POKE pokeoff% + 1, LowWhighbyte%π POKE pokeoff% + 2, HighWlowbyte%π POKE pokeoff% + 3, HighWhighbyte%πDEF SEGπEND SUBππSUB pokeW (pokeseg%, pokeoff%, word%)π'This function will just poke a word into memory, just likeπ'the standard function Poke does it, with one enhancement.π'While poke needs a def seg before it we will transfer that toπ'the function also! So :π' DW segment to poke word toπ' DW offset to poke word toπ' DW wordvalue to pokeπ'Of course you should use this only for reasons of putting all yourπ'variables in one DATAsegment, since otherwise just defining a integerπ'is enough.π'---------------------------------------------------------------πDEF SEG = VARSEG(word%)πptr% = VARPTR(word%)πhighbyte% = PEEK(ptr% + 1): lowbyte% = PEEK(ptr%)πDEF SEG = pokeseg%π POKE pokeoff%, lowbyte%π POKE pokeoff% + 1, highbyte%πDEF SEGππEND SUBπRick Elbers ASSEMBLY IN QBASIC 5: PROCS t030611@tip.nl 12-01-96 (05:37) QB, QBasic, PDS 279 10103 PROCS.BAS 'ASSEMBLY IN QBASIC PART 5: USING A PROCEDURE SEGMENTπ'-------------------------------------------------------π'Rick Elbers november 1996 ππDECLARE SUB pokestring (SEGJE%, OFFJE%, MAIN$)πDECLARE SUB PokeW (pokeseg%, pokeoff%, word%)πDECLARE FUNCTION int2str$ (sword%)π'------------π'INTRODUCTIONπ'------------π'There are more ways to handle procedures in your assembler subs. This shortπ'article will discuss one of them. This one is especially done because weπ'need him in order to make an interrupthandler, which will be my nextπ'contribution. When we are discussing procedures we can separate theπ'called program( that one is named newint% here) and the caller(that one isπ'simply named callsub%).π'-----------------π'CALLED PROCEDURE:π'-----------------πDIM newint%(6)πnewint%(0) = &H5052 'PUSH AX,DXπnewint%(1) = &H41B2 'MOV DL,41πnewint%(2) = &H2B4 'MOV AH,02πnewint%(3) = &H21CD 'INT 21πnewint%(4) = &H5A58 'POP DX,AXπnewint%(5) = &HCB 'RETF (returns to the caller)ππ'CONTROL IF IT WORKS:πsegm% = VARSEG(newint%(0)): offs% = VARPTR(newint%(0))πCLS : DEF SEG = segm%: CALL ABSOLUTE(offs%)πDEF SEG : SLEEPπ'For me it worked...π'----------------π'CALLER PROCEDUREπ'-----------------πDIM callsub%(3): cdeseg% = VARSEG(callsub%(0)): i% = VARPTR(callsub%(0))πDEF SEG = cdeseg%ππPOKE i%, &H9A 'the opcode for CALLπPokeW cdeseg%, i% + 1, offs%πPokeW cdeseg%, i% + 3, segm%πDEF SEG = cdeseg% 'has to be restored since POKEW returned to def segπPOKE i% + 5, &HCB 'retf (return to QBASIC)ππ'This program does nothing but calling the newint% and thenπ'returning to QBASIC. Let us controle it:πLOCATE 2, 1: CALL ABSOLUTE(i%): DEF SEGπ'It does seems to work allright.....πSLEEPππ'-------π'NEWINT$π'-------π'Some off you might have noticed i used integers for storage of the assembler subsπ'here. That is for a few good reasons and in some follow up article on thisπ'i will resolve all mentioned problems with using integers for assembler codeπ'storage..But for this moment i will add, so to speak for backwardπ'compatibility, a way to handle procedures when you use strings for assemblerπ'subs storage.π'----------------π'CALLED PROCEDUREπ'----------------πnewint$ = ""πnewint$ = newint$ + CHR$(&H52) + CHR$(&H50) 'PUSH AX,DXπnewint$ = newint$ + CHR$(&HB2) + CHR$(&H41) 'MOV DL,41πnewint$ = newint$ + CHR$(&HB4) + CHR$(&H2) 'MOV AH,02πnewint$ = newint$ + CHR$(&HCD) + CHR$(&H21) 'INT 21πnewint$ = newint$ + CHR$(&H58) + CHR$(&H5A) 'POP DX,AXπnewint$ = newint$ + CHR$(&HCB) 'RETF (returns to the caller)ππ'CONTROL IF IT WORKS:πsegm% = VARSEG(newint$): offs% = SADD(newint$)πDEF SEG = segm%: LOCATE 3, 1: CALL ABSOLUTE(offs%): DEF SEG : SLEEPπ'seems okeπ'-----------------π'CALLING PROCEDUREπ'-----------------π'Okay now for the big surprise. We are going to use a PROC segment likewiseπ'we used a DATAS segment in some other article. In that PROC segment we willπ'poke every string_stored_assembler_routine that we want to call.π'After that is done we can call the routines from the calling program the sameπ'way we readed out data in other instances. Let us see how it works:ππ'First let us set up the PROCS segment:πDIM PROCS%(LEN(newint$) \ 2 + 1)πprocseg% = VARSEG(PROCS%(0)): procoff% = VARPTR(PROCS%(0))πprocseg$ = int2str$(procseg%)ππ'Now let us poke newint$ into it and make newint$ adressableπpokestring procseg%, procoff%, newint$: newintoff$ = int2str$(procoff%)ππ'-----------------------------------π'CODEπ'-----π'call procseg$[newintoff$]π'retfπ'-----------------------------------πasm$ = ""πasm$ = asm$ + CHR$(&H9A) + newintoff$ + procseg$π'retfπasm$ = asm$ + CHR$(&HCB)ππ'________________________________________πCodeoff% = SADD(asm$)πDEF SEG = VARSEG(asm$): LOCATE 4, 1:πCALL ABSOLUTE(Codeoff%): DEF SEG : SLEEPπ'________________________________________ππ'This was our first procedure....!!!ππ'--------------π'FINISHING....π'--------------π'I hope you will be realizing the tremendous opportunities of this approachπ'since you just can poke ANY routine inside the PROC segment and call himπ'in your main program. For the sake of demonstration i will just add oneπ'more program to it. Actually it is the printstring that i used in theπ'second part of ASSEMBLY IN QBASIC. Of course the actual procedures i usedπ'as calling procedures are very simple and does not seem to add anyπ'functionality whatsoever. However that is why they serve a great purpose inπ'outlining the CONCEPT of a PROCEDURE segment. Actual possibilities shouldπ'be very simple to fantasize and in fact to make when you have understoodπ'it all....π'--------------------------------------------------------------------------π'DATA:π'------πb$ = "Hello i have been printed indirectly$" 'This is the way DOS processes stringprintπDIM datas%(LEN(b$) \ 2 + 1)πdataseg% = VARSEG(datas%(0)): dataoff% = VARPTR(datas%(0))πdataseg$ = int2str$(dataseg%): dataoff$ = int2str$(dataoff%)πpokestring dataseg%, dataoff%, b$π'CODE:π'-----πprnstr$ = ""πprnstr$ = prnstr$ + CHR$(&H50) 'pushaπprnstr$ = prnstr$ + CHR$(&H52)πprnstr$ = prnstr$ + CHR$(&H1E)πprnstr$ = prnstr$ + CHR$(&HB8) + dataseg$ 'MOV AX,DATASEG$πprnstr$ = prnstr$ + CHR$(&H8E) + CHR$(&HD8) 'MOV DS,AXπprnstr$ = prnstr$ + CHR$(&HBA) + dataoff$ 'MOV DX,DATAOFF$πprnstr$ = prnstr$ + CHR$(&HB4) + CHR$(&H9) 'MOV AH,9πprnstr$ = prnstr$ + CHR$(&HCD) + CHR$(&H21) 'INT 21πprnstr$ = prnstr$ + CHR$(&H1F) 'popaπprnstr$ = prnstr$ + CHR$(&H5A)πprnstr$ = prnstr$ + CHR$(&H58)πprnstr$ = prnstr$ + CHR$(&HCB) 'retfπππ'PROCπ'-----π'We have to adjust our PROC segment to hold both routines now:πREDIM PROCS%(LEN(newint$) \ 2 + 1 + LEN(prnstr$) + 1)πprocseg% = VARSEG(PROCS%(0)): procoff% = VARPTR(PROCS%(0))πprocseg$ = int2str$(procseg%):ππ'Let us poke both routines in the PROC segment now and make the routinesπ'adressable:ππpokestring procseg%, procoff%, newint$: newintoff$ = int2str$(procoff%)πprnoff% = procoff% + LEN(newint$)πpokestring procseg%, prnoff%, prnstr$: prnstroff$ = int2str$(prnoff%)ππ'Okay we have a PROC segment now with:π'PROC:0 newint$π'PROC:LEN(newint$) prnstr$ππ'When we want to call both routines we have to adjust the callers CODE:π'----------------------------------------------------------------------π'CODEπ'-----π'call procseg$[newintoff$]π'call procseg$[prnstroff$]π'retfπ'-----------------------------------πasm$ = ""πasm$ = asm$ + CHR$(&H9A) + newintoff$ + procseg$πasm$ = asm$ + CHR$(&H9A) + prnstroff$ + procseg$π'retfπasm$ = asm$ + CHR$(&HCB)π'________________________________________πCodeoff% = SADD(asm$)πDEF SEG = VARSEG(asm$): LOCATE 5, 1πCALL ABSOLUTE(Codeoff%): DEF SEGπ'________________________________________ππ'There does not seem to be a limit to the possible chaining that you canπ'do. You can call procedures from procedures from procedures enz...π'But you might consider to store the heavy used procedures in one PROCπ'segment of course.....I hope that this article helps a bit in assembly-π'programming in QBASIC (still the most used BASIC). I hope i pointed outπ'in this article(s) that assembly programming in QBASIC is not necessaralyπ'very difficult, when you pay attention to the main principles.π'So do not go for quick solutions at an easy level, but instead try toπ'make clear choices at levels that still allow you to. I am sure that willπ'later on help you * a lot! Seeing the difficulties in simple things oftenπ'makes difficult things simple ......πππ'Bye.ππ'RickπENDππSUB hlpjeπ'-----------------------------------π'push axπ'push dsπ'mov ax,0000π'mov ds,axπ'call 1234:0000π'retfπ'-----------------------------------ππprnstr$ = asm$ + CHR$(&H50)πasm$ = asm$ + CHR$(&H1E)πasm$ = asm$ + CHR$(&HB8) + CHR$(&H0) + CHR$(&H0)πasm$ = asm$ + CHR$(&H8E) + CHR$(&HD8)πasm$ = asm$ + CHR$(&H9A) + CHR$(&H0) + CHR$(&H0) + CHR$(&H34) + CHR$(&H12)πasm$ = asm$ + CHR$(&HCB)π'________________________________________πCodeoff% = SADD(asm$)πDEF SEG = VARSEG(asm$)πCALL ABSOLUTE(Codeoff%)π'________________________________________πDEF SEGπππEND SUBππFUNCTION int2str$ (sword%)π'This function is translating SWORD Integers into a string. Its only useπ'is when you still use asm$ for assembler functions( like i do). In thatπ'case you can make your integer values usable ..π'THis function simply translates the hexa bytesπ'into stringbytes as is.π'----------------------------------------------------πDEF SEG = VARSEG(sword%)πptr% = VARPTR(sword%)πint2str$ = CHR$(PEEK(ptr%)) + CHR$(PEEK(ptr% + 1))πDEF SEGππEND FUNCTIONππSUB pokestring (SEGJE%, OFFJE%, MAIN$)π'------------------------------------------------------π'This function pokes a string (might be ASCIIZ)intoπ'memory at a given location, making it possible toπ'access strings in byte formπ'------------------------------------------------------ππDEF SEG = SEGJE%πFOR i% = 0 TO LEN(MAIN$) - 1π POKE OFFJE% + i%, ASC(MID$(MAIN$, i% + 1, 1))πNEXTπDEF SEGππEND SUBππSUB PokeW (pokeseg%, pokeoff%, word%)π'This function will just poke a word into memory, just likeπ'the standard function Poke does it, with one enhancement.π'While poke needs a def seg before it we will transfer that toπ'the function also! So :π' DW segment to poke word toπ' DW offset to poke word toπ' DW wordvalue to pokeπ'Of course you should use this only for reasons of putting all yourπ'variables in one DATAsegment, since otherwise just defining a integerπ'is enough.π'---------------------------------------------------------------πDEF SEG = VARSEG(word%)πptr% = VARPTR(word%)πhighbyte% = PEEK(ptr% + 1): lowbyte% = PEEK(ptr%)πDEF SEG = pokeseg%π POKE pokeoff%, lowbyte%π POKE pokeoff% + 1, highbyte%πDEF SEGππEND SUBπJoe Caverly BINARY SEARCH ROUTINE 74214.637@CompuServe.COM 11-02-96 (15:01) QB, QBasic, PDS 59 2091 BSEARCH.BAS ' I looked through the ABC Text for a binary search routine, but found none. Iπ'have this very large text file that is downloaded from the Mainframe each day,π'which is presently at 151,000 records, and growing. Each record is 328π'characters wide. The file is sorted by a 7-character customer number. I needed aπ'means of rapidly looking up a customer number. However, instead of reading thisπ'very large text file into a database, I figured there had to be a way to rapidlyπ'search the file as-is. The code below does just that.ππCLSπDIM RecordIn AS STRING * 9πLET RecLen = 9πLET TEST = FREEFILEπOPEN "C:\SETUP\ADANUM.TXT" FOR BINARY AS #TEST LEN = RecLenπLET wsmin = 0πLET wsmax = (LOF(TEST) / RecLen) + 1πLET wsmaxptr = (wsmax * RecLen) + 1πLET wsKey$ = "1218537"πDOπ LET wsmid = wsmin + ((wsmax - wsmin) \ 2)π LET wsptr = (wsmid * RecLen) + 1π IF wsmin > wsmax THENπ PRINT "Not Found!"π PRINT "Near Record Number "; wsmidπ EXIT DOπ END IFπ GET #TEST, wsptr, RecordInπ LET wsRecordIn$ = LEFT$(RecordIn, 7)π SELECT CASE wsRecordIn$π CASE IS = wsKey$π PRINT wsRecordIn$ + " equals " + wsKey$π EXIT DOπ CASE IS < wsKey$π 'What we want is in the upper halfπ PRINT wsRecordIn$ + " Less Than " + wsKey$π LET wsmin = wsmid + 1π CASE IS > wsKey$π 'What we want is in the lower halfπ PRINT wsRecordIn$ + " Greater Than " + wsKey$π LET wsmax = wsmid - 1π END SELECTπLOOPπCLOSE #TESTπPRINT "Done!"πENDππ'Please note that the above program works with a fixed-width file where eachπ'record is 9 characters wide (7 characters of data plus a carriage return andπ'line feed). If you want to generate a file to test this program with, here's aπ'small program that will do just that. The above program would need to beπ'modified to accept a record that is 13 characters wide (11 characters of dataπ'plus a carriage return and line feed).ππOPEN "c:\setup\test.dat" FOR OUTPUT AS #1πFOR cntr = 1 TO 151000π PRINT #1, USING "Line ######"; cntrπNEXT cntrπCLOSE #1πPRINT "Done!"πENDπKurt Kuzba FULL 16-BIT SHIFTING ROUTINE FidoNet QUIK_BAS Echo 12-08-96 (13:50) QB, QBasic, PDS 37 1251 SHIFT.BAS '> I would like to know if anyone knows a simple right bit-π'> shift routine for QBasic.π'>......π' I wrote one of those a while ago when someone posted a PBπ'program using SHIFT(). I recently stumbled across a means toπ'accurately convert bit patterns for INTEGER values to LONG whenπ'the value is negative, so I did an update to the process.π'It now allows a full 16-bit shift where it only allowed 15 before.ππ'_|_|_| SHIFT.BASπ'_|_|_| A simple bit-shifting routine for Qbasicπ'_|_|_| No warrantee or guarantee is given or implied.π'_|_|_| Released PUBLIC DOMAIN by Kurt Kuzba. (12/7/96)πDECLARE FUNCTION shift% (D%, V%, T%)πDOπ INPUT "number => ", N%π sh% = N%π PRINT shift%(0, sh%, 1), shift%(1, sh%, 1)πLOOP WHILE N% > 0πENDπFUNCTION shift% (D%, V%, T%)π '_|_|_| A simple bit-shifting routine for Qbasicπ '_|_|_| shift V% right or left T% placesπ '_|_|_| if D% = 0 then shift right, else shift leftπ S& = V%π IF S& < 0 THEN S& = 65536 + S&π FOR T% = T% TO 1 STEP -1π IF D% = 0 THENπ S& = S& \ 2π ELSEπ S& = (S& * 2) AND 65535π END IFπ NEXTπ IF S& > 32767 THEN S& = S& - 65536π shift% = S&πEND FUNCTIONπ'_|_|_| end SHIFT.BASπEgbert Zijlema PRINT COUNTRY SPECIFIC DATE E.Zijlema@uni4nn.iaf.nl 11-02-96 (16:40) PB 55 1766 DATES.BAS ' CTRYDATE.BAS - prints a date on the screen, using country specificπ' separator - e.g.: dot in Germany, slash in UK & Japan,π' hyphen in USA etc.ππ' Author : Egbert Zijlema (E.Zijlema@uni4nn.iaf.nl)π' (up)Date : November 22, 1996π' Language : Power Basic 3.2π' Copyright status: Public Domainππ' Notification : Result depends of correct COUNTRY settingπ' in your CONFIG.SYS file!ππ' ------------- begin code --------------πDEFINT A - ZππSUB GetCountryInfo(format, seperator$)π buffer$ = SPACE$(64) ' information bufferπ REG 8, STRSEG(buffer$) ' DS = segment of bufferπ REG 4, STRPTR(buffer$) ' DX = offset of bufferπ REG 1, &H3800 ' AX = serviceπ CALL INTERRUPT &H21ππ ' after the call buffer$ = filled:π format = ASC(buffer$) ' date format (1 out of 3) = 1st byteπ seperator$ = MID$(buffer$, 12, 1) ' delimiter = 12th byteπEND SUBππFUNCTION CountrySpecificDate(InputDate$) AS STRINGππ ' InputDate$ as MM-DD-YYYY (= default format)ππ IF InputDate$ = "" THEN InputDate$ = DATE$π MM$ = MID$(InputDate$, 1, 2)π DD$ = MID$(InputDate$, 4, 2)π YY$ = MID$(InputDate$, 7)ππ GetCountryInfo form, delim$π SELECT CASE formπ CASE 0π FUNCTION = InputDate$ ' USA (Basic's default)π CASE 1π FUNCTION = DD$ + delim$ + _π MM$ + delim$ + YY$ ' EURπ CASE 2π FUNCTION = YY$ + delim$ + _π MM$ + delim$ + DD$ ' JAPπ END SELECTπEND FUNCTIONππ' demo callπCLSπ PRINT "To-day's date is: "; CountrySpecificDate("") ' use actual dateπENDππ' ----- end code ------------------------------πAaron Finley DOSFS FILESYSTEM BROWSER V1.0 aaronx86@geocities.com 12-01-96 (18:01) QB, QBasic, PDS 903 28361 DOSFS.BAS DECLARE SUB license ()πDECLARE SUB dialog (A!, b!, c!, d!, shd!)πDECLARE SUB ANXStringHandle (prompt$, max%, winsiz%, S$, sequins%)πDECLARE FUNCTION GetString$ (prompt$, max%, winsiz%, S$, sequins%)π'DOSFS Filesystem Installer V1.0π'Copyright (C) Aaron Finley 1996π'All Rights Reservedππ CLSπ COLOR 0, 15π PRINT STRING$(80, " ") '------------License-------------------π LOCATE 1, 1: PRINT "DOSFS Filesystem Installer V1.0": CALL licenseπ CALL dialog(17, 8, 30, 10, 1) '--------------------------------------π COLOR 15, 3π LOCATE 8, 32: PRINT "DOSFS Installer": COLOR 0, 15π LOCATE 11, 26: PRINT "DOSFS Filesystem Version 1.0"π LOCATE 12, 24: PRINT " Copyright (c) Aaron Finley 1996"π LOCATE 13, 19: PRINT " All Rights Reserved"π COLOR 15, 1π LOCATE 15, 25: PRINT STRING$(32, " ")πππ OPEN "dosfs.bas" FOR INPUT AS #1πππ DO UNTIL EOF(1)π LINE INPUT #1, A$ππ IF A$ = "'[■FS_APP.ANX]" THEN GOTO gotit1:ππ LOOPππ CALL dialog(17, 8, 30, 10, 1)π COLOR 15, 3π LOCATE 8, 32: PRINT "DOSFS Installer"π COLOR 0, 15π LOCATE 12, 23: PRINT " Installer Object Incomplete"π LOCATE 13, 23: PRINT " Unexcepted End-Of-File"π SYSTEMπgotit1:πFsb = 1πqat = 1πdfc = 1ππOPEN "FS_app.anx" FOR OUTPUT AS #2πcc = 0ππ DO UNTIL EOF(1)π LINE INPUT #1, A$π FOR i% = 2 TO LEN(A$)π b$ = MID$(A$, i%, 1)π IF A$ = "'[■FS_APP.ANX]" THEN GOTO find2:π b = ASC(b$)π IF b = 254 THEN GOTO 4π cc = cc + 1π IF cc = 128 THEN cc = 1ππππ b = b - ccππ PRINT #2, CHR$(b);π '----Percent Formula V1----ππdone = done + 1πoutof = LOF(1)πlength = 40ππ numprint1 = done / outof * length + 1π COLOR 15, 3ππ LOCATE 15, 25: PRINT STRING$(numprint1, " ")πππ '---Done That---πππ4π NEXTππ cc = 0πππ PRINT #2,π LOOPππfind2:ππ CLOSE #1π OPEN "dosfs.bas" FOR INPUT AS #1ππ DO UNTIL EOF(1)π LINE INPUT #1, A$ππ IF A$ = "'[■FS_VIEW.BAS]" THEN GOTO gotit2:ππ LOOPππ CALL dialog(17, 8, 30, 10, 1)π COLOR 15, 3π LOCATE 8, 32: PRINT "DOSFS Installer"π COLOR 0, 15π LOCATE 12, 23: PRINT " Installer Object Incomplete"π LOCATE 13, 23: PRINT " Unexcepted End-Of-File"π SYSTEMπgotit2:πCLOSE #2πOPEN "FS_VIEW.BAS" FOR OUTPUT AS #2πcc = 0ππ DO UNTIL EOF(1)π LINE INPUT #1, A$π FOR i% = 2 TO LEN(A$)π b$ = MID$(A$, i%, 1)π IF A$ = "'[■FS_VIEW.BAS]" THEN GOTO endthat:π b = ASC(b$)πππππ IF b = 254 THEN GOTO 6π cc = cc + 1π IF cc = 128 THEN cc = 1ππ b = b - ccπ IF b = -4 THEN GOTO 889:ππ PRINT #2, CHR$(b);π '----Percent Formula V1----ππdone = done + 1πoutof = LOF(1)πlength = 54ππ numprint1 = done / outof * length + 1π COLOR 15, 3ππ LOCATE 15, 25: PRINT STRING$(numprint1, " ")πππ '---Done That---ππ6π NEXTππ cc = 0πππ PRINT #2,π LOOPππππendthat:ππCLOSE #2πOPEN "DOC.TXT" FOR OUTPUT AS #2πcc = 0ππ DO UNTIL EOF(1)π LINE INPUT #1, A$π FOR i% = 2 TO LEN(A$)π b$ = MID$(A$, i%, 1)π IF A$ = "'[■EMANUAL.TXT]" THEN GOTO endthat2:π b = ASC(b$)πππππ IF b = 254 THEN GOTO 889π cc = cc + 1π IF cc = 128 THEN cc = 1ππ b = b - ccπ IF b = -4 THEN GOTO 889:ππ PRINT #2, CHR$(b);π '----Percent Formula V1----ππdone = done + 1πoutof = LOF(1)πlength = 64ππ numprint1 = done / outof * length + 1π COLOR 15, 3ππ LOCATE 15, 25: PRINT STRING$(numprint1, " ")πππ '---Done That---ππ889π NEXTππ cc = 0πππ PRINT #2,π LOOPππendthat2:ππ100π VIEW PRINT 3 TO 24π CLOSEπCOLOR 0, 0ππ CALL dialog(20, 10, 20, 6, 1)π COLOR 15, 3π LOCATE 10, 32: PRINT "DOSFS Installer"π COLOR 0, 15π LOCATE 12, 24: PRINT " Enter installation path"πππPRINTπpath$ = "C:\DOSFS"πCOLOR 15, 1πLOCATE 13, 27:πTmp$ = GetString$(Out$, 256, 24, path$, 0)πON ERROR GOTO DirAExt:πMKDIR path$πDirAExt:πCOLOR 0, 0πCLSπCALL dialog(20, 8, 21, 10, 1)πCOLOR 15, 3πLOCATE 8, 32: PRINT "DOSFS Installer"πCOLOR 0, 15πLOCATE 10, 24: PRINT " Chose components to install."πLOCATE 12, 24: PRINT " [ ] 1. Filesystem Browser (REQ)"πLOCATE 13, 24: PRINT " [ ] 2. APP Loader C:\I...ANX (REQ)"πLOCATE 14, 24: PRINT " [ ] 3. FS Files and Manual (REQ)"πLOCATE 16, 21: PRINT "Press number to select, Enter to cont."π'------------Really Sloppy Code---------------------π'Excuse this crappy code. I almost ran out of time!π π DOπRerr:πIF Fsb = 1 THEN LOCATE 12, 27: PRINT "X"πIF Fsb = 0 THEN LOCATE 12, 27: PRINT " "πIF qat = 1 THEN LOCATE 13, 27: PRINT "X"πIF qat = 0 THEN LOCATE 13, 27: PRINT " "πIF dfc = 0 THEN LOCATE 14, 27: PRINT " "πIF dfc = 1 THEN LOCATE 14, 27: PRINT "X"ππA$ = INKEY$: IF A$ = "" THEN GOTO Rerr:π π IF A$ = CHR$(13) THEN GOTO donsel:π IF Fsb = 1 THEN IF A$ = "1" THEN Fsb = 0: GOTO Rerrπ IF qat = 1 THEN IF A$ = "2" THEN qat = 0: GOTO Rerrπ IF dfc = 1 THEN IF A$ = "3" THEN dfc = 0: GOTO Rerrπ π IF A$ = "1" THEN Fsb = 1π IF A$ = "2" THEN qat = 1π IF A$ = "3" THEN dfc = 1ππ LOOPππdonsel:πCOLOR 0, 0πCLSπ CALL dialog(20, 10, 20, 6, 1)π COLOR 15, 3π LOCATE 10, 32: PRINT "DOSFS Installer"π COLOR 0, 15π LOCATE 13, 30: PRINT " Please Wait..."π π IF Fsb = 1 THEN cmd$ = "copy fs_app.anx " + path$ + "\fs_app.anx > tmp.tmp": cmd2$ = "copy fs_view.bas " + path$ + "\fs_view.anx > tmp.tmp": SHELL cmd$: SHELL cmd2$: file = file + 2π IF qat = 1 THEN OPEN "c:\ifloader.anx" FOR OUTPUT AS #1: PRINT #1, "chdir " + path$: PRINT #1, "qbasic /run " + path$ + "\fs_app.anx": CLOSE #1: file = file + 1π IF Fsb = 1 OR qat = 1 OR dfc = 1 THENπ dd$ = "copy doc.txt " + path$ + "\MANUAL.TXT"π SHELL dd$π END IFπ IF dfc = 1 THENπ OPEN path$ + "\dosfs.bat" FOR OUTPUT AS #1π PRINT #1, "@echo off"π PRINT #1, "chdir " + path$π PRINT #1, "qbasic /run fs_view.anx"π CLOSE #1π file = file + 1π OPEN path$ + "\odc.anx" FOR OUTPUT AS #1π CLOSE #1π file = file + 1π OPEN path$ + "\odn.anx" FOR OUTPUT AS #1π PRINT #1, "0"π CLOSE #1π file = file + 1π OPEN path$ + "\odr.anx" FOR OUTPUT AS #1π PRINT #1, "2"π PRINT #1, "Aunix"π CLOSE #1π file = file + 1π ELSEπ END IFπ CALL dialog(20, 10, 20, 6, 1)π COLOR 15, 3π LOCATE 10, 32: PRINT "DOSFS Installer"π COLOR 0, 15π LOCATE 13, 24: PRINT "Installation Complete (" + RIGHT$(STR$(file + 1), LEN(STR$(file + 1)) - 1) + " files)"π π KILL "fs_app.anx"π KILL "Fs_view.bas"π KILL "Doc.txt"π IF Fsb = 1 OR dfc = 1 OR qat = 1 THENπ KILL "tmp.tmp"π ELSEπ END IFππππππππππππππππππππππON ERROR GOTO errhndl:ππππENDπππππππππππerrhndl:πSYSTEMππSUB ANXStringHandle (prompt$, max%, winsiz%, S$, sequins%)π S$ = LTRIM$(RTRIM$(S$)): Cursor% = LEN(S$) - (Cursor% < max%)π F$ = " ": IF sequins% <> 0 THEN F$ = " "π Fill$ = STRING$(max%, F$)π S$ = LEFT$(S$ + Fill$, max%): INS% = -1: PRINT prompt$; " ";π Ybase% = POS(0)π WHILE done$ <> "DONE"π Sbase% = Cursor% - winsiz% + 1: IF Sbase% < 1 THEN Sbase% = 1π LOCATE , Ybase%, 0: Hid$ = STRING$(LEN(RTRIM$(S$)), "*")π IF sequins% = 0 THENπ PRINT MID$(S$ + Fill$, Sbase%, winsiz%); " ";π ELSEπ PRINT MID$(Hid$ + Fill$, Sbase%, winsiz%); " ";π END IFπ LOCATE , Ybase% + Cursor% - Sbase%, 1π k$ = "": WHILE k$ = "": k$ = INKEY$: WENDπ k% = ASC(k$): IF k% = 0 THEN k% = -ASC(MID$(k$, 2))π SELECT CASE k%π CASE 32 TO 127π IF INS% AND Cursor% < max% THENπ MID$(S$, Cursor% + 1) = MID$(S$, Cursor%)π S$ = LEFT$(S$, max%)π END IFπ MID$(S$, Cursor%, 1) = k$π IF Cursor% = max% THEN SOUND 999, 1π Cursor% = Cursor% - (Cursor% < max%)π CASE 13: IF S$ = Fill$ THEN S$ = ""π IF INSTR(S$, F$) > 0 THEN S$ = LEFT$(S$, INSTR(S$, F$) - 1)π EXIT SUBπ CASE 8π IF Cursor% > 1 THENπ Cursor% = Cursor% - 1π MID$(S$, Cursor%) = MID$(S$, Cursor% + 1)π MID$(S$, max%) = F$π ELSEπ BEEPπ END IFπ CASE 27: S$ = "": EXIT SUBπ CASE -71: Cursor% = 1π CASE -79: Cursor% = INSTR(S$, F$)π IF Cursor% = 0 THEN Cursor% = max%π CASE -82: INS% = -(INS% + 1): SOUND 1500 + 800 * INS%, .5π CASE -83π IF Cursor% < max% THENπ MID$(S$, Cursor%) = MID$(S$, Cursor% + 1)π MID$(S$, max%) = F$π ELSEπ BEEPπ END IFπ CASE -75: Cursor% = Cursor% - 1π lim% = INSTR(S$, F$): lim% = lim% - max% * (lim% = 0)π IF Cursor% < 1 THEN Cursor% = lim%π CASE -77: Cursor% = Cursor% + 1π lim% = INSTR(S$, F$): lim% = lim% - max% * (lim% = 0)π IF Cursor% > lim% THEN Cursor% = 1π END SELECTπ WENDπEND SUBππSUB dialog (A, b, c, d, shd)ππ COLOR 15, 3π LOCATE b, A: PRINT STRING$(A + c, " ")π COLOR 0, 15π FOR i% = b + 1 TO b + d - 1π LOCATE i%, A: PRINT STRING$(A + c, " "); : IF shd = 1 THEN COLOR 8, 0: PRINT "█": COLOR 0, 15π NEXT i%π COLOR 8, 0π IF shd = 1 THEN LOCATE b + d, A + 1: PRINT STRING$(A + c, "█")πEND SUBππSUB formulaπCLSπDOπdone = 25πIF done = outof THEN ENDπoutof = 100πlength = 80πLOCATE 1, 1πCOLOR 15, 1πPRINT STRING$(length, " ")π numprint1 = done / outof * length + 1ππ LOCATE 1, 1:π COLOR 0, 15π PRINT STRING$(numprint1, " ")πLOOPπππEND SUBππFUNCTION GetString$ (prompt$, max%, winsiz%, S$, sequins%)π ANXStringHandle prompt$, max%, winsiz%, S$, sequins%: Elvis$ = S$πEND FUNCTIONππSUB licenseπ ππ CALL dialog(11, 3, 50, 20, 1)π COLOR 15, 3π LOCATE 3, 35: PRINT "License"π π COLOR 0, 15π LOCATE 5, 1:π LOCATE 5, 20: PRINT "DOSFS Installation v1.0"π π LOCATE 6, 20: PRINT "Copyright (C) Aaron Finley 1996"π LOCATE 7, 20: PRINT "All Rights Reserved"π LOCATE 8, 20: PRINTπ LOCATE 9, 20: PRINT "By pressing `A', you agree to the following:"π LOCATE 10, 20: PRINT "---------------------------------------------"π LOCATE 11, 20: PRINT " 1. You will not use any of the package's"π LOCATE 12, 20: PRINT " (which includes FS_APP.ANX, FS_VIEW.BAS)"π LOCATE 13, 20: PRINT " code from this version. In order to use"π LOCATE 14, 20: PRINT " the code, you must register."π LOCATE 15, 20: PRINTπ LOCATE 16, 20: PRINT " 2. You will not modify or copy in any way"π LOCATE 17, 20: PRINT " the code in this package, and will read"π LOCATE 18, 20: PRINT " Manual.txt once installed. "π LOCATE 19, 20: PRINTπ LOCATE 20, 20: PRINT "---------------------------------------------"π COLOR 15, 1π LOCATE 21, 20: PRINT "Press `A' to agree, `D' to disagree. "π π DOπ999 A$ = INKEY$: IF A$ = "" THEN GOTO 999:π IF UCASE$(A$) = "A" THEN GOTO 989π IF UCASE$(A$) = "D" THEN SYSTEMπ LOOPπ989ππEND SUBππSUB packageπ'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXπ'X Xπ'X File Area Xπ'X Xπ'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXπ'----------------------------------------------------------------------------π'"What the HELL is that?" Version 1.0π'Copyright (C) Aaron Finley 1996π'All Rights Reservedπ'----------------------------------------------------------------------------π'[■FS_APP.ANX]π'EGFPFXL(\_M,\<\UcYX4=zå{Gê|ëéBH■π'EGFPFXL(\_M,\<\[Taa4=YffGh|ëéBH■π'EGFPFXL(\_M,\<RXU[e4=YffGh|ëéBH■π'EGFPFXL(\_M,\<[c1:<■π'EGFPFXL(\_M,\<eYVi3<yàzFç{êüAG■π'EGFPFXL(\_M,\<fbZfX4=zå{Gê|ëéBH■π'EGFPFXL(\_M,\<rx|sâä5>ZggHdèAJ?aqrQi}zKQ■π'EGFPFXL(\_M,swçsu{à4=äîà:C■π'EGFPFXL(\_M,\<a]Taa4=YffGh|ëéBH■π'(FRWKY6[bXN,Sw{uäïåêzâ7ZïëÆÅéÉ■π'(Ert~xpoq~+4P7/Qräéé5\Çåàö<NWXV■π'(Cop%Xpoq~~,_séuâêxx■π'DQPQTT'[QK]QQ.rtzä7@5YffGcë@I>ÇÉæPîÆI■π'DQOSW&>4):■π'EQ■π'32#>■π'JH#Qfioqwo/,J.121f[Yc6^gmi;ST■π'QTLRY&Tilrtzr2/;14B65A7{}âì@=I?BDD^■π'JPSYY&)*5*nyq2■π'JH#MSY[Z1;7,p{s4=2547?7la_i■π'!"#$%&'()*+,-./0Wae4â6T8J:ok=jdnIàÉêIO■π'!"#$%&'()*+,-./0àâE96T8fc_@EüîäENCÆQFXQ■π'!"#$%&'()*+,-./0T2P4â■π'!"#$%&'()*+,-./0ZX3êéåH<9W;>=@?tigqDlu{wI]■π'!"#$%&'()*+,-./0■π'!"#$%&'()*+,-./0àâF96T8ìçïNA>J@òÅôUI■π'!"#$%&'()*+,-./0■π'!"#$%&'()*+,-./0_Wkh■π'4■π'!"#$%&'()*+,-./0Wae4w6T8\:ok=jdnIàÉêIO■π'!"#$%&'()*+,-./0àâE96T8fc_@EüîäENCåQFXQ■π'!"#$%&'()*+,-./0■π'!"#$%&'()*+,-./0àâG96T8ìçïOA>J@òÅôUI■π'!"#$%&'()*+,-./0_Wkh■π'5■π'!"#$%&'(■π'!"#$%&'(}w{>1.L0fUTgZ:?îåèM@F■π'!"#$%&'()*+,-./0■π'!"#$%&'()*+,-./08dXjO67Y}~ÇÇ=entpBUTÿFìù¢JÜÿôƪ£úúVúºÜ₧á«]íá░óѼ╕╛■π'!"#$%&'()*+,-./0dW_YXj7[Zm`<æïÅRE■π'!"#$%&'()*+,-./01234567[Zm`<?acB■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuUkqnt~UÇxwyåW\⌐úºk]f[êéîg┤«▓vhnfthzst■π'!"#$%&'()*+,-./01234567[Zm`<?agdjtE■π'!"#$%&'()*+,-./0123456789:;<=>?■π'!"#$%&'()*+,-./0123456789:;<=>?cbnoDtTjpms}TwvxàV[¿óªj\eZçüïf│¡▒ugmesgyrs■π'!"#$%&'()*+,-./01234567[Zm`<?kjdjtE■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuUutmzzUó£ádV\■π'!"#$%&'()*+,-./01234567[Zm`<?kcB■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuUutmzzUó£ádV\■π'!"#$%&'()*+,-./01234567[Zm`<?a`tC■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuU~roéTwvxàV[¿óªj\eZçüïf│¡▒ugmesgyrs■π'!"#$%&'()*+,-./01234567[Zm`<?uqiugE■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuU{sqUó£ádV\nU}åîêZml■π'!"#$%&'()*+,-./01234567[Zm`<?plB■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuUzvmzzUÇxwyåW\⌐úºk]f[êéîg┤«▓vhnfthzst■π'!"#$%&'()*+,-./01234567[Zm`<?pldjtE■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuUzvmzzUÇxwyåW\⌐úºk]f[êéîg┤«▓vhnfthzst■π'!"#$%&'()*+,-./01234567[Zm`<?kdrhgE■π'!"#$%&'()*+,-./0123456789:;<=>?■π'!"#$%&'()*+,-./0123456789:;<=>?@dcopEuUun|rqUÇxwyåW\⌐úºk]f[êéîg┤«▓vhnfthzst■π'!"#$%&'()*+,-./012345678■π'!"#$%&'()*+,-./0V`W4h[c]\n■π'!"#$%&'()*+,-./0TS_`5eE{üà|îìFôìæTGPExpoq~OTí¢ƒcU^SÇzä_¼ª¬n`f^l`rkl■π'!"#$%&'(}w{>1.L034M4ëâçK=:X<?@■π'!"#$%&'(NV^Q■π'!"#$%&'()*+,-./0ZX3wéz;8V:=êÉ@?tigqDtTs{■π'!"#$%&'()*+,-./0TS_`5eE{üà|îìFéìàFODôòòìMS■π'!"#$%&'(■π'!"#$%&'(NXO,VT■π'!"#$%&'■π'!"#$%&'()*+,-./0■π'!"#$%&'(0789:;<=>?@ABCDg]lI]kv?hbpgpjxTUVWXYZ[\]^_`abcd■π'89■π'!"#$%&'(XZPZ-0~tâ@téì87^hl;]mndneBdwEI\■π'!"#$%&'(Y\TZa.2E=25D7■π'!"#$%&'(LVZ_R.2E■π'!"#$%&'(XZPZ-0~tâ@téì87^hl;eknttAcvDH[■π'!"#$%&'(RX[aa.2E=2üëé■π'!"#$%&'(RP+zé{/M1D3h][e8bhkqq>BUMBpàêÄÉûÄN■π'!"#$%&'(LVZ_R.2E■π'JH#rzs'E);+`US]0tv|å96T8;<U<lndnADÆêùTêûíLKr|ÇOååâëëVxïY]pv]ÄæëÅûcgzrgjzlàlÉÜ₧úûrvëÅvñ╣╝┬─╩┬é¥üäº╔╦╟▄╘▌î■π'JH#rzs'E)<+`US]0tv|å96T8;<U<lndnADÆêùTêûíLKr|ÇOååâëëVxïY]pv]ÄæëÅûcgzrgj{làl¥áÿ₧Ñrvëüvñ╣╝┬─╩┬éÖÇñ«▓╖¬åè¥■π'JH#rzs'E):+`US]0\[_`58å|ïH|èò@Y@jhCçëÅÖLIgKNONâxvÇSùÖƒ⌐\Yw[^]`y`Äúª¼«┤¼liçknæ│╡▒╞╛╟v■π'!"#$%&'(0789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd■π'3■π'!"FPTYL(,?■π'QTLRY■π'MQRT■π'■π'99■π'HQWS%=>■π'■π'TWE$koiyz■π'■π'■π'FPG$X[I■π'■π'TWE$kokms},5|ä}:■π'■π'!"#$%&'(Y\TZa.1VZjVX^h7üî:àÉüîååCìôFî₧èûáìíù₧₧Qòóñ«dW`|é~ïï^òqorcëùÿxqk■π'FPG$X[I■π'■π'TWE$T4JPMS],5Q^^?`tüz:@■π'!"#$%&'(Y\TZa.1SYUbb5è8}âÄ}èääAïæDè£êö₧ïƒò££Oôáó¼bU^zÇ|ëë\ôompaçòûvoi■π'FPG$X[I■π'■π'TWE$T4jptk{|-6R__@aué{;D9[klKcwtEK■π'■π'!)Fss4uivo/G-0;2L2üëéQ7:E<V<?pvÿsy¢F`FITKeKN|\ƃƒT■π'!"#$%&'■π'!"#$%&■π'!"#$%&'(RP+oqwü41NQ4787la_i<fd?cppQråôîLIgKN[\QPàzxéUy|éî[^klazaàäÉæf¡▒┴¡»╡┐vÇyïrÿ¼₧¬w½«£■π'!"#$%&'()*+,-.■π'!"#$%&'(LVZ_R.2A■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(XZPZ-0~tt@téì87^hl;eknttAcvDHW■π'!"#$%&'■π'!"#$%&'(XZPZ-0~t@téì87^hl;eknttAcvDHX■π'!"#$%&'(RX[aa.2B=2üëé■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(OY],V3/M1C3hd6àìå■π'!"#$%&'(RX[aa.2A=2VccD`å=F;èÆïQLAcfgjyzLUJzZíºƒòU■π'!"#$%&■π'!"#$%&'(RP+[;éêÇv63Q58fFzèï>=rgeoBljEivvWxîÖÆROmQuéécÑ\YÄâüï^åÅòæcº¡▒u¡┴╛■π'■π'!"#$%&'(WOc`■π'■π'!"#$%&'()*+,-./0T^bgZ6:I■π'!"#$%&'(■π'!"#$%&'(NbT`-adR■π'djn2j~{B■π'!"#$%&'(XZPZ-`XWYf7<hji<AêÉëOGK@mgqLxzyLQÿáÖ_WXP^Rd]U|åèYâëîÆÆ_üöbfz■π'!"#$%&'(MY+a[bX\1WbZ=L@■π'!"#$%&'()*+,-./0][aY5_ehnn;?SJ?àÖûòàI■π'!"#$%&'()*+,-./0ZX3]cikjAKG<ra`sfFKë¥ÜÖëMSWLOÇä~QTS_Uyè]bnpf^j`cqîèæòêîÄ£y좪qp|rû£ºzïìâä|▒ªñ«■π'!"#$%&'()*+,-./012345678lipja>WPQNCU■π'!"#$%&'()*+,-./012345678\fjob>BV[BflfouH{srtüRWâàäW\ú½ñjbf[êéîgôòögl│╗┤zrskymxp|ruéw■π'!"#$%&'()*+,-./0V^fY■π'!"#$%&'()*+,-./0V`W4^\■π'!"#$%&'(UYZ\■π'!"#$%&'(Y\TZa.1Uâäéå5à8zèïêåüÇöèææDMiosjz{Lâ_]`QwàåUg`Z■π'!"#$%&'(Y\TZa.1UibM4bèïéêé<ÇìâàAûÆDù¢ÿKá£NúÿÜÑSòѪúí£¢»Ñ¼¼mb■π'FPG$X[I■π'■π'TWE$T4S[■π'!"#$%&'(LYW[_.F<1BM4eh`fm:=JK@■π'!"#$%&'(LVZ_R.2A■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(XZPZ-0~tt@téì87^hl;eknttAcvDHW■π'!"#$%&'(XZPZ-0~t@téì87^hl;eknttAcvDHX■π'!"#$%&'(RX[aa.2B=2üëé■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(OY],V3/M1C3hd6àìå■π'!"#$%&'(RX[aa.2A=2VccD`å=F;ÉèÄK@befixyKTIyYáª₧öT■π'■π'!"#$%&'()*+,-./0dW_YXj7[Zm`<lLôÖæçG■π'!"#$%&'()*+,-./012345678\[na=@nNàæåF■π'!"#$%&'()*+,-./012345678\igko>VLAR■π'!"#$%&'()*+,-./012345678ildjq>booPlÆI■π'!"#$%&'()*+,-./012345678\[na=@nNìÉÄF■π'!"#$%&'()*+,-./012345678\igko>RLAR■π'!"#$%&'()*+,-./012345678ildjq>booPlÆIFRHKjM■π'!"#$%&'()*+,-./012345678\[na=@nNéÆôF■π'!"#$%&'()*+,-./012345678\igko>QLAR■π'!"#$%&'()*+,-./012345678ildjq>booPlÆIFRHKTM■π'!"#$%&'()*+,-./U_V3gZb\[m■π'!"#$%&'(WOc`■π'!"#$%&'(LVZ_R.2A■π'!"#$%&'(LYW[_.F<1B■π'!"#$%&'(■π'■π'FPG$X[I■π'■π'TWE$T4TM[QP,5r~s?Çtüz:@■π'!"RR%KYZX\+S\b^0II■π'!"RTJT'lxm9zn{t41Xbf5_ehnn;]p>erfgimqk■π'!"#$%&'(LVZ_R.UbVWY]a[■π'!"#$%&'(RP+p|q=~rx85S7:GH=<qfdnArumszGJlÖÖáÄù¥òúRíòó¢Wí¼Zñ¬│ƒ½⌐ÑbkæÉëûûiá|z}nöóúrä}wÉw¥▒ú»|░│í■π'!"#$%&'(LVZ_R.2A■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(XZPZ-0^TT@Tbm87^hl;]mndneBdwEIX■π'!"#$%&'(XZPZ-0^T_@Tbm87^hl;eknttAcvDHX■π'!"#$%&'()*+,-./0■π'!"#$%&'()*+,-./0Z`cii6:JE:ëæèX?ÄûÅCaEö£òIUK]gNr|ÇàxTXhqXêèÇè]`ÄäÅpäÆ¥hgÄÿ£k¢óóƒÑÑröºuyëÆy¬¡Ñ½▓âôÄâ╥┌╙■π'!"#$%&'()*+,-./0ad\bi6:IE:ïÇLìüÄçG_EHSJdJÖíÜiOR]TnTWêÄÉïæô^x^alc}cföt½╖¼l■π'!"#$%&'()*+,-./0T^bgZ6:K■π'!"#$%&'()*+,-./0àå74R69{êèö<?>J@àæåRôçöìMJVLONQP\Rà}|~ï\aìÅÄaf¡╡«kodæïòp£₧¥pu╝─╜z{süuçÇxäz}|¢~╙═╤É╫╤╒ê■π'!"#$%&'(■π'!"#$%&'()*+,-./0dZX`a6ïî=■π'!"#$%&'()*+,-./0\[_`58kàëHÅëì@■π'!"#$%&'()*+,-./0T^bgZ6:JNN■π'■π'!"#$%&'()*+,-./0123456■π'■π'FPG$X[I■π'■π'TWE$T4TSLYY,5Q^^?`tüz:@■π'■π'!"#$%&'(Y\TZa.1]\Ubb5è8}âÄ}èääAïæDè£êö₧ïƒò££Oôáó¼bU^äâ|ëë\ôompaçòûvoi■π'FPG$X[I■π'■π'TWE$T4YULYY,5Q^^?`tüz:@■π'QTLRY&)ZVMZZ-wé0u{åuwé||9âë<éöÇîûâùìööGïÿÜñZMVü}tüüTïgehYìÄnga■π'■π'FPG$X[I■π'■π'TWE$T4]QNa+4q}r>sÇy9?■π'■π'!"#$%&'(RP+p|q=~rx85S7:GH=<qfdnArumszGJmÖÄíÜô¥ñQÇöíÜVá½Yú⌐▓₧¬¿ñajÖìè¥g₧zx{lÆáíézt■π'!"#$%&'(XZPZ-0~tt@téì87^hl;eknttAcvDHW■π'!"#$%&'(XZPZ-0~t@téì87^hl;eknttAcvDHX■π'!"#$%&'(RX[aa.2B=2üëé■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(OY],V3/M1C3hd6àìå■π'!"#$%&'(RX[aa.2A=2VccD`å=F;èÆïQLAcfgjyzLUJzZíºƒòU■π'!"#$%&'(RP+[;éêÇv63Q58fF}ë~>=rgeoBljEivvWsÖPMkOöáòaóûú£\YÄâüï^åÅòæc|■π'■π'!"#$%&'(WOc`■π'!"#$%&'()*+,-./0T^bgZ6:I■π'!"#$%&'(Y\TZa.1TÇuêüzäï8ç{êü=çìûéÄîêRSvèôÅÄáMÆ₧òñRíú⌐VƒºÑ₧[¥½╖_░⌐╗╢¡¿º│h╣╝║╝▓└├╣╢┼s|½ƒ£»y░îèì~ñ▓│ôîåƒå¼└▓╛ï┐┬░■π'9■π'!"#$%&'(LVZ_R.2C■π'!"#$%&'(XZPZ-`XWYf7<hji<AêÉëOGK@mgqLxzyLQÿáÖ_WXP^Rd]U|åèYâëîÆÆ_üöbfw■π'!"#$%&'(■π'!"#$%&'(MY+a[bX\1WbZ=I@■π'!"#$%&'()*+,-./0][aY5_ehnn;?PJ?öÄÆWH■π'!"#$%&'()*+,-./0ad\bi6ïàëN?■π'!"#$%&'(UYZ\■π'FPG$X[I■π'■π'TWE$T4^ZR^P,5r~s?Çtüz:@■π'■π'!"#$%&'(RP+p|q=~rx85S7:GH=<qfdnArumszGJlÖÖáÄù¥òúRíòó¢Wí¼Zñ¬│ƒ½⌐ÑbkæÉëûûiá|z}nöóúrä}wÉw¥▒ú»|░│í■π'!"#$%&'(LVZ_R.2A■π'!"#$%&'(LVZ_R.2B■π'!"#$%&'(XZPZ-0^TT@Tbm87^hl;]mndneBdwEIX■π'!"#$%&'(XZPZ-0^T_@Tbm87^hl;eknttAcvDHX■π'!"#$%&'()*+,-./0Z`cii6:JE:ëæèX?ÄûÅCaEö£òIUK]gNr|ÇàxTXhqXêèÇè]`ÄäÅpäÆ¥hgÄÿ£k¢óóƒÑÑröºuyëÆy¬¡Ñ½▓âôÄâ╥┌╙■π'!"#$%&'()*+,-./0ad\bi6:IE:ïÇLìüÄçG_EHSJdJÖíÜiOR]TnTWêÄ░ïæ│^x^alc}cföt½╖¼l■π'!"#$%&'()*+,-./0T^bgZ6:K■π'!"#$%&'()*+,-./0`bXb5h`_an?DprqDIÉÿæNRGtnxSüÇSXƒºá]^VdXjc[éîÉ_ÅûûôÖÖfê¢im~■π'!"#$%&'()*+,-./■π'!"#$%&'()*+,-./0Ua■π'!"#$%&'()*+,-./0][aY5_ehnn;ÉèÄSD■π'!"#$%&'()*+,-./0ZX3êéåK<9W;>bmeBAvkisFwzrxLPa[PtzàX]hmasZ~êîæä`du}dè₧É£i¥áÄ■π'!"#$%&'()*+,-./0ad\bi6:KE:ÅëìRC■π'!"#$%&'()*+,-./0]abd■π'■π'FPG$X[I■π'■π'[■FS_APP.ANX]π'[■FS_VIEW.BAS]π'EGFPFXL(\_M,\<rx|sâä5>ZggHäèAJ?aqrQi}zKQ■π'■π'EGFPFXL(\_M,swçsu{à4=äîà:C■π'■π'EGFPFXL(\_M,\<a]Taa4=YffGh|ëéBH■π'(FRWKY6[bXN,Sw{uäïåêzâ7ZïëÆÅéÉ■π'(Ert~xpoq~+4P7/Qräéé5\Çåàö<NWXV■π'(Cop%Xpoq~~,_séuâêxx■π'■π'(Vki%uyqpsymy.éyïw3zäê7îüâÄ<ìÉÄçôâÉD£çÜHë`abThOPrûù¥ú¥W½¿ºá\áªá▓┤b╖│e╣╗╖╣j┐┤«┬■π'(56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Çü■π'EGFPFXL(\_M,\<\[Taa4=YffGh|ëéBH■π'EGFPFXL(\_M,\<RXU[e4=YffGh|ëéBH■π'EGFPFXL(\_M,\<[c1:<■π'EGFPFXL(\_M,\<eYVi3<YeZFç{êüAG■π'EGFPFXL(\_M,\<fbZfX4=Zf[Gê|ëéBH■π'DQPQTT'[QK]QQ.rtzä7@5YffGâë@I>ÇÉæPîÆI■π'■π'■π'DNV■π'DQOSW&74);@■π'QTLRY&Z\[SYS16G@=2547?■π'MQFEYK'95*<F-^aY_f36Yej^lInuka?fèÄêù₧Ö¢ìûJm₧£ÑóòúT■π'DQOSW&>4):■π'WKH[%VYQW^+>-b^0CG■π'QTLRY■π'QTLRY&)LX]Q_<ah^T2Y}ü{èæîÄÇë=`æÅÿòêûG■π'QTLRY&)Kxzä~vuwä1:V=5Wxèêê;båîïàÜBT]^\I■π'QTLRY&)Iuv+^vuwää2eyê{ëÄ~~=■π'QTLRY■π'DJDMS&)n|il|}<p~ë4■π'■π'[■FS_VIEW.BAS]π'[■MANUAL.TXT]π'EQVJX&Mquo~àÇét}1Tàâîë|è9pLJM■π'Dqs}wonp}*3O6.Pqâüü4[àä~ô;MVWU■π'Bno$Wonp}}+^rütéçww■π'■π'10#[jrjwvo■π'./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy■π'■π'!Yhphutm)~z,üvt0êüàÇy6å~9^jocqM@AcCuççÜæîJæòÖôó⌐ñªÿíU¬ƒÖ¡Z₧¥½^íÑa½▒º▒╗½¡¡■π'!kq$~u|z)k{|ywrqà{éé5èå8îèèÄæ>àòìÄCèÄÆîH£ƒ¢££áú^QRüúUúª¬₧Z₧¿▓¼¬╣■π'!QSIS&hvm*NX\aT>12]ëêè7}å|ÇÇ=ÆçàAòÿåRÿû¥¥ôÖæáV₧ûQª¢ÖU¿£ƒó¡»í»úú`╖º╡╖«╡╡q■π'!kq$~u|z)z}{tÇp}=23uâz7üìì;ÇîîäNABrÆæƒGëIÉÉúMÜÿ₧ûÑSú¢Vܺ¥ƒ[¥»ú_«ªºº⌐⌐■π'!vr$xk{(r~+ü}</0dwx4ê{zîéëë<}PF@çæòDëï¢ëÆû₧Z■π'■π'!"0$Wkx}r|p-_QQd[V4ïGEI■π'!"0$F&oi{n+pwàu1üà4äè}ï:ÄïëçâMöûäÿèFÜ£ÿ£îôÆ■π'!"0$:6rj)P}qr■π'!"0$IUZ(>8;,|Ç/|råxå■π'■π'20#Gtstiwn~■π'./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy■π'■π'!"#$%&'(■π'!"#$%&'(i\X,h}qzvuçsâwä}vA■π'■π'!"#$%&'()7+^r{~åvà3uâ6åzâ~É■π'■π'!"#$%&'(iWVPV`/kÇt}yxèvåzçÇyD>ÄÆAéphEüûèôÅÄáî£É¥ûÅZ■π'■π'!"#$%&'()7+Ospävà3u5yååì{äèéÉ?HéPÄRåFmùòÄÉ₧V■π'!"#$%&'()7+[oxtsà2üué{è8å{ö<â?òæBùôEX\]IìôìƒÅÆñûñª`UùÑ▒■π'!"#$%&'()*+ouoüqtåxåê6|É|ïÉ=ÅöÅòâùìööGòè£ûƒ[■π'!"#$%&'(■π'!"#$%&'(iMSPV`/kÇt}yxèvåzçÇyD>?ÅôBâgiFéùïöÉÅíì¥æ₧ùÉ[■π'■π'!"#$%&'()7+Ouo}wvà3ê}{7{ÄîìüïÆ?âÉÉùàÄöîÜIRîZÿ\ÉPwíƒÿÜ¿`■π'■π'!"#$%&'(ia]UaS/kÇt}yxèvåzçÇC■π'■π'!"#$%&'()7+Ospävà3u5zå{ÄçÇèæ■π'!"#$%&'()7+[oxtsà2üué{è8å{ö<â?òæBùôEX\]IìôìƒÅÆñûñª`UVÿª▓■π'!"#$%&'()*+ouoüqtåxåê6|É|ïÉ=ÅÄòòâùìööGòè£ûƒ[■π'■π'!"#$%&'(iML`-i~r{wvêtäxà~wB■π'■π'!"#$%&'()7+bvså0r2év{zî9■π'!"#$%&'()7+O|rt0zà3z~ëæE:;àâ>ÿÅûBåàôöû£IáöæñNúÿûRûúú¬£ª¡¡[½ú■π'!"#$%&'()*+m{.~r{wvêA67îïô;}äêÄOBC■π'■π'!"#$%&'(iWP^TS/kUd\jZPshZncxâçïàÇÉäæèâN■π'■π'!"#$%&'()7+O|~ê0r2Wch6}üà;àïÆÄ@òèêDiuzn|JæòÖôó⌐ñªÿí■π'!"#$%&'()7+`us/~rx4Äàî8ìôïü=çì@èòCÿìïGûèùÉLª¥ñPÿùºT₧ñW¼íƒ[₧»¡╢│ª┤q■π'!"#$%&'()7+Rvztâ1uééï{ëî9Äè<ÉÆÇÄàâòêEèûï₧ùÉÜíí]■π'■π'!"#$%&'(iV^3■π'■π'!"#$%&'()7+bvså0àzx4xààî~êÅÅ=ìà@òèêDê¢ÖÜÄÿƒLÉ¥¥ñÆ¢íÖº■π'!"#$%&'()7+O|z~ézîxx5|åè9}èèôâìëåÉåë■π'■π'!"#$%&'(iel|}zxsrå|ââuàyåxC■π'■π'!"#$%&'()7+Us.êå2çìà{7îü;è~ïä@ÉêCàôFêÿÖûöÅÄóÿƒƒR£óU¬ƒ¥Y£¡½┤▒ñ▓■π'!"#$%&'()*+u{~ää1éàâéåïD9:Åäé>ÇÉæÄîçåÜÉùùJóòÖÜO£áôùbUVǪY⌐¡áó░■π'!"#$%&'()*+r|Ç/äy{å4ëà7ÅêîåH=ùÄòAÅÿùÖFÉû£₧îÿÖNúÿûRªÖÿÑÑ£■π'!"#$%&'()*+|nqzqxw3â{6ïÇ~:äèÉÆÇîìBôûöìÖëûXKLvöO⌐áºS£û¼£Xº⌐»\í¡¡Ñ■π'!"#$%&'()*+Çuwé09BAGÇxC89îÇÅåéäôAâùDh`âæÅûÜìæôí^Æá½]aVºñ₧¢«í]º¡│╡ú»░■π'!"#$%&'()*+uü.}ê@■π'■π'!"#$%&'()7+Z|.pÇü~|wvèÇççì;ÅàçÅ@ÿïùîEÜÅæ£Jíæƒíÿƒƒ^ST¿ÑWíƒZ┤½▓^╢í»╢■π'!"#$%&'()*+Ç|.révsçy5àà}E:;èî>ôÅÉÄûDåÿîHèáîòÖÅæ£û`STëÑW¢¿¿▒í»▓■π'!"#$%&'()*+m{.~r{wvê5èå8zê;}ìÄïëäâùìööSHI₧ôæMó¿áûR[¿¥¢WñÜ¡»■π'!"#$%&'()*+ny}r{1üy4v6åzâ~É=éäôäöîöÖÅûûIôÖLíûöPáö¥Öÿ¬Wñó¡»e]^«ªaú▒■π'!"#$%&'()*+m}~{ytsç}ää7üî:jJ~ÄÅNABuëÆïöèÄ£Ká£NÉöòRôw¥ùáªY\~vֺѼ░úº⌐╖t¿╢┴lr■π'!"#$%&'()*+Ç|.âxv2y}ü{7yì:|èû>dneNCDxz|nwWLM¥íPäåéäU⌐½Ö¡ƒ¿í½▓m■π'■π'30#$Qotq}ku||é0rÇw4g{~üîÄì}æçÄÄ■π'./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy■π'■π'!"#$%&'(iWVPV`6<1rV\Y_i?E:|èü>rnICêöFòù¥JÉñûíúPÜáS¿¥ƒ¬X¥ƒ¿½]┤ñ▓┤½▓▓s■π'!"#$%&'(Wy+o|rt0zÇ3ê}è8âçü=ïÇÖAäêDè₧¢ÜèìƒææN₧óQƒóÿ₧£á¥¥h■π'■π'!"#$%&'(]rp,sâ{|1êxåêååE:;ôàçéêAàÆùÖÖGLZZWLMæùòö¥SúºVñººƒ┤\¼░úÑ│b¼▓¿▓╝¼«╜à■π'■π'!"#$%&'()*+,></Vå~4Xàäàzê<pôÅÉÉöù■π'!"#$%&'()*+,?</Vååêåz6îêÇî|Çéæ?fsghDMÅòïòƒÅò¢òOæQyê}^■π'!"#$%&'()*+,@</dyw3uwâüìô;Éî>ôêèòCçöèîHáôƒöû£O⌐áºÑTûªºñó¥£░ª¡¡na■π'!"#$%&'()*+,A</Vâwx4ë{zÇçâ~}ë>ÆòæÆÆûÖFO₧ÆïKqZ¢ÉÖ¥[■π'!"#$%&'()*+,B</U>t}ü6îê}{ÅüÉ>ÇéÉùùDôï₧HÖ£ÜÉóæúú_■π'■π'!"#$%&'(]y+r|s0âwz}êèëyìâèèI>?ÉìçäùèFìæòûK¢óóOñÖ¢ªT¢Ñ⌐Ñs■π'!"#$%&'(J}+à|â/}r{4ë~ÇïE:;àïäÄÆÄBÉëE£ÉëIÅXÖÄù¢Pƪ■π'!"#$%&'(JPj^r~{ëQ|êéäDzçå■π'■π'!"#$%&'(6789:;<=>?@ABCDEFGHIJKLMpöçëùFmù¢ùXYZ[\]^_`abcdefghijklmnopqrs■π'■π'!"#$%&'(WkxqG.nopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñÑghijklmnopqrstuvwxyz{■π'!"#$%&'(JqpF-mno■π'!"#$%&'(X|tsv|/w2wâîäâçz~U<|}~Ç\RSäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñÑ■π'!"#$%&'(hijklmnopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñÑ■π'■π'!"#$%&'(]â{q-}u0üsîüzäïR9u;y=aÇôëBCEâGuÿÿÉÑM}íöûñ■π'!"#$%&'()*89-[p{v2v|zyé8êî;ëîîäÖAæòêèÿGù₧₧Ká£NÅqÆñóóU|áªÑƒ┤c]ñ«▓afttsfg■π'■π'!"#$%&'(Jno~rüéJ1qrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪ■π'!"#$%&'(Jno~rüé0CL3stuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪ■π'!"#$%&'(LsàG.nopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪ■π'!"#$%&'(\~lÇrH/o?qA4äê7wxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪ■π'!"#$%&'(LyÇzüÇêJ1qrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪ■π'!"#$%&'(YrzzrH/8pqr=5uvwFyz{|>ÄÆAüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪ■π'■π'!"#$%&'(6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs■π'■π'!"#$%&'(Y,v|/ÇrïÇyâè7yç~;ÉàçÆ@ÉöçëùFìù¢ùKò¢NÉ₧Qùí¬Üóª¿₧Z£¬í^áñÑ┤¿╖╕f╗╖â■π'■π'!"#$%&'(Jyuà.]uàëéåÇ■π'!"#$%&'(@?C,YoåâÇÇ3Uï{E■π'!"#$%&'(Qküqé~ç>3dvD7IRJSO■π'■π'!"#$%&'■π'■π'!"#$%&'(■π'■π'■π'!"#$%&'()*+,-./0■π'[■EMANUAL.TXT]πEND SUBπCharlie Quante AN ANIMATED LIFE SIMULATION charlie@charlie.seanet.com 12-08-96 (00:00) QB, PDS 123 8138 ALIFE.BAS DEFINT A-Z:DIM SHARED K,S,B&,Z&:V1 'Created by PostIt! 7.2πSUB V1:OPEN "O",1,"ANILIFE.ZIP",4^6:Z&=5834:?STRING$(50,177);πU"%up()%9%%%I-%k3/WFl0)ZvV4.%%:S%%%1%%%%fs%nRqn%kjSgRfx&)<xBT]Z'xπU"2llbxOBeETEPcj>sK9Vp0$\bTsds^PBRlG&LhK6D7Z0/Z$J[DJJj=rxql[%IjRYπU"AS2x)vboI(-QE-nK%ciOPUx3Gp=/1W*a$oJN<#GoM0$krF:Vt:txKUGX*BwH0NaπU"uk]4+&&by;B.<VW])+Xq+*i7kJ5BAe7e_#sZCO^iuqj8uv%_Ew\rw)G]\9O:urOπU"OOXuwowFe:rFmp(N=i2zm6Cf?75BD9tJK[9O9Lgmu)qO%KKynaaLvdNw.VkMrATπU"YVZ$Zaf$?7(IHOTolQL<pSUIf/^_n_SR+0^DFjK-rLjPPMlzm5=(<tpCRQ-oA%TπU"\aba/#8pI^+,qy7Ou8p[EiDevd>kDWTjf;5;nEUSvC^JrMVub2D,NZ)ThmCXw2LπU"&b<mA&p^J$9pu<f8mRx?hIn7#6UHml\i<0tNN48rgk<ZIdSjfcV<\(M.,F=r-)YπU"[Na.>-Wd\#efg<z^>=%]GajN2]k1-(Ds+U_Re%#gXS0\Gs+wr_PdX>cBu#iK(n/πU"W/kY+VoV[H=..J_>KS$LeJv\yZF[2TS;>)u_JEA/>Se.wfqE:ommhDkb:6>X_<dπU"IbO[67o/6JeiQ__L>^U'gJHkZ=fZ<h0#h^AA-2_lsc-Sml?TH5jPs&&'(U0jj9wπU"Vr<&_KS22ssAh1^-;ij88Q[uT1baxe[#CY40gKCU-OA58Y8nAt(Af)z::]a;Qh:πU"_A43/&Wu8(Tc7#HKEWX('1$4FD^Sj/E*jEPkHta&)DQoHSUBFK+Z=f6[mj9A6$9πU"4&id8:s*.otO+-Mz4\YboPm+tL#\/QesqTADUkt2<W0J(D9jE^?.WJ54+kP$i]kπU"^qn:k9>T&3Q:>dg(LK13tW\.5m$R*R4rhJtDjE]D,<vcdTTVhND/McvK>i8%pW-πU"Ptbbd%ZuXt,qmMA?rBF0(DpjOTjt,(d[[H?\ag=d6nbUu.>J'nU/6\[3'6[s&znπU"&C/Qq:STOQAS[Fg41(;(KzKes1>pmqUUL3/QQZZ?.MiVNgn9GMji6LqKvP\A2;tπU"H-HoA\\7O-RSy0aO\Kfshp?QH?1&bN35DsqHLgmYZJ5,W<6V&a#<6-?ci'a;frRπU"EHF]jiB;R4n(#oly0JI:8\&Zdh9^<6sXhLb.8R;v*etF(8mXC:DE'aNXn?'Xu7FπU"VfGA>JBiJCBX\9TB6^YT2de)HqaD?Qdo$du$=9lbR(vtwowM7a[Iak.n=(%SkB]πU"<J\&+pAbPgKbB=l?b#4&Ukgt0-0x.3=aDw.YN$7i?mt:,#MmcG&lDm16+s322HkπU"Tv508:JfLyuMG?I^O4,20dnA0pvFv0,ncWc2J:bG7m+&(qYS6X4/o)i\B<k#jN/πU")B*A4W,%pi*E^ndxqa,g,_1/nS>?aCQPy9a2HFEBA%Q^sOdP\&fG*>4Lr1.]*1<πU"DV8qATqvhQ)S$:jn<Qgat&Rj9cCw+hnjTmrI1qmYJ%6(W>;eo;q7etAL?EJfV:TπU"2IkMnSr-7YeaM(#8(IdS9\\:.A6abM1qQkh)n^gRplfZoxWhH5V\]<0sQ-e6[)PπU"t]>vNu>)l/lob<6AY*#'>onrEg\slge\Vy:j&4l:2LN:5HfrF*?^ZY5qVQC\$fgπU"heO>pZTL-26r?6TT$c/rvR?IRdD2EW4('K)h;r4B<B,IdD1KS4pn&3WbL]q3<)OπU"SG=gf;QXL^U_oD_f5-]$Z8NRD#j]f?Ev\:.IWT]WB_P[Vp+kwexwxxbeUvSo]>4πU"-eH/25N_h;l'NGgY*ih#a46j7*)pPwd/+XFAYya)5M92CCZ&;2=dc,GpTgBa\rMπU"IKx5SN_L,-/9>(aTv)%&3'Vdxni+0.Ae1IwXA$?)Ml3>GODMJ[D?%Gim$6=:d.9πU"0]_u]WUw5VI.?uTlhivp4aFc-+<DqP7dK1_I\c6dOMXJi<jfBXGG\l9ARXES%;VπU"If3YhUoSmw;(KM:H,)t4WHY>dPi(k^RPDRwuSqycBqHE3.VKGlWWkRC[)&aunCiπU"l(j^GY)UE=YC'i(Tiyp#'6Tc2YJiU$ESgv85p#=SQuB((;<eq8blBPG5Y+$;k6UπU"EL6=95DJUs48carH+:gnx-hHv0-;1=6'?f]87>KJ=RE/6pcMasmE+iJ'T#SxWnRπU"88uRgvWP%[3CCc>Qw5a?B9,N-i\?f\_+mH(rBhkrG,E4ePEN=FF.3^vv4ZSIlT=πU"XhRVrZXfX])oU8>cWTU)TG32>N;v=BA^kqU&&3cV];fXwe7U4B%oosBuN4.h2^%πU"pzQ'V.Z1j.f=B8up5<G2,5jt[b3mnN62l[=#,OUSnXe35;)T?jC6>PO+rJhRdcaπU"*5UW;asSKgjL)]-^DwWYs1[[/oE$IKxJ17O\%V/k%MG+aH;Z_jw>koE.5:T/JpiπU"Oayn$-*d?$Mc/q4&p$J)JV)'RMk5)d-KH2X-PdW+aM2l6I2T<>ljrW(/MZ^iSDhπU"?\6&,-4=c^LG-4-5]<(j/7wM;(Wbe>0#kI2F-pOOi4G)N8bGo;Z4(R\F3+Z\s/oπU")h#k;l2&/3/PeXL*E]*qIHqrv'BXX7,hBc^+_:Qnmy5?a_Li%<nlk+J2hW5=M[3πU"oH+#d54cAXJl%UKNKKiMq+V9hKK\Y>a^Kan;+faO^+e?B<)<J#KQbm;%.JqNeagπU"'&x=BK)g&U[T?yg&:kU\r*x1d]R:tgqZqx6%<6>2#SzqF/o&L(c,-B-pfI?/X^RπU"z,maHJe&j)ddaVv&l$9h%YBZU;_U?3#<R:vmad9T3MbA(Knw\Y1(&f\q<f[#tj=πU"C8:8]v2WhRTnY8ar%(j-O.d2&'SOA7g,b>smX^t9OeBCgT&m\QOjTiaB[3GKXcTπU"NZwB62%62<inlet-E3NcXAN?5oJ84_lXmiV'3K[KZ1k\ZbX(f$JHvponiD3;IYvπU";ed0x7Zhm#2[MnOUDHQENt.GW&Ed\UtsE/(bfpB*gb&3tcqa]9q?.1-il?Ze::pπU"6>ZHQHV-vmyjxvX4Ysuo^4^e,82H$5f5GY(0=3)73o[lkxuTt((xsJP16jC;o#6πU"R7)%1TGuEk't4+NXHs.nVtdV9'*pOEF'89#3SIC2_:/QiVU1sVq4BnZE:U]=QX%πU"&%59'7w<f&)#<d^>'Fn+L1_51B%7k2A16L16t4m##HP^-'6bK:7vndJOeCY?jHPπU".^?+(8-L1?FR%f:E4DRJcqD,X7eR(C7xv&N*P7-MHxm8kj(N2?UD/kp6Yj:f_N/πU"gQNx7yB#UxAn>RbfBlq<+luxZCB^E#tP_$gvsGo]OHYcEFb?1f?2E5(a=P3h],CπU"oG#Z[.,DU]O=uc)ojVnCqYM28DO$6j;<]Zm4,F?R-YWj;fXPVoJB&X3cTuB+u[RπU"S8liEe&v=)rjCh]8PbA(=#nS(^,k']CSJ=%(?EX6V^k93ojl)oBhxp=;t[>YeZ9πU"_7=NQR80r$gNR_W.s+HfiYP1Ur;cXcEmyH*iYd[pg:jL+1$5+#<[u<BI&^M(&0kπU"b\ja(hUl-$J9)'Y<jZ4AV$wnw1zY];9mDx\FFg$w#^]=AH6MdT,-bA0V;dtZ-2,πU")J+H5x/0UeF027*7Nt%_f;bA^'V03b-Kso,K/2EBFL-b;H+0o]#;B?^J,A$0DEEπU"uFk$A&jm1N\BWP$d%j^2yQh$(-UJ:c*+O:AhrWnEl(vaSx]b,8XU/MfF4bf:B7KπU"XO.L?COVc-H+Z_W7R\<K-B0;9R&*]h6?6eAOPY(wlEn2glrZ#ig:AXqd.wJ+;lGπU";d]-;YqiA$RlL8Tt1Kgjd.]ierHUUJQ=7GIfK'[4HH2Dqcp>)w%j/nQ].RD,;:NπU"+NZl4L7;,v%U'[6FPnhe1R6c0f\:PPF,]RgVz3>O-j()9Iry6d$>*e6p'rd#mWkπU"xZXe4v<bofsUVNP-zG^-,xe<&S*F7W_2h<JTgKKP;p)m<Sw79h&8e#</4qaB'riπU";<cZo*DRtoJ1hD?BEAQ)ZrVhN:t9Q_&nNVD+IT=oG/iZD2bDEG(m'+-R:=C4)SVπU"W5Amk.SedUli]-oK2x5PJPIdz?6]/VOpSG6=obWS7-]^=xW]xKBYO(qYVh)x$5VπU",Vp)$UX];<m:wLk:gV+6R;).W80iazla>qBGR4Q61EnMOC=/QQrsF*in<(]vuXXπU"+?MN7%8NAuG*,$Z#4?mEd\?cA%14s]>yq.Plq.Frl.8fXRn*8b_,MLXZDh-QcXbπU"S8ZLh^FY%:h;>fXRS'8RhN)L?y\6:<K'MU.>#Kxa^6ZWNB&j]?J+B[(:uX_[4PLπU"zm57%zf7p>Zr5eLQ1:Apr1NKc%aWG%%6/^+DZXg<Oqbia\jQWk4+mjjt5;),#u$πU"7k2F9Xq>N7E&nSZ*rs=OM5jP&<06CL)m[=UXh\9Nr;KAKU9X]24bj-cD?YR-\YvπU"HTb*\,Nxqp9\=$G>VFA%F=d:kWJ1)yugb:W-SK1XQ\b)h5$W5(:mb2,iP8V>/)FπU"3Y5FEC?\\%Ly[t[RjxNQtK.S1X4rcdrOZpg,>1Mn%%VqB2YqJM]wY+(=lE&a?g&πU":(otSuQ%SLnso?_,XJTnIkQj\)wRQiEq%aMhXps4j2^I%3*D;^Q;O6KKKq5fnK*πU"05Cy3:d=FGa6m4FD-NO$;z&V2B^9(l&HFIdccuk>RLxBXK9;-Ah6':/dfwVZ)\\πU"ut8eW9U%M0z1Pfv^eZJcC/&rU/U&+>6=u^HL$Uv+_/&QQpgP*'C1;iy/IM$Bd9IπU"N0sgOOgZ$RC^QH0Z7^]qGCqXkCF+\O^q?gO\n'#j3.MNlg>LW^2?$FBkrpj>b0=πU".WCz)2:71$=LED56ffu<(Bw-uKw;qkl;[Li2=lQcJdMJ1XG)2=BLTq%S&=x/E-&πU"u#bm1R6lpn:</,<izh3's,W7OgliFFaZ7oQ)GGg2g4Ij&]\MpZstE,30HGtk($=πU"65<\oG*gg.lky+VNMROi406]5wSdyKfRyb1oybRGyLoyfLRy,(oyXl-^P,a+jxdπU"u%p()9%%%%-I%/wUCFLo+-Ht%%%%T(%%%.%%%%ywj%jVSnRhsf_9*o=e:5U8r.sπU"\T=#$^u2M84JT=,?goK4YQQMtT)tp^Cf%f%QT,fm*Sd-U[Ci<)d<spf]q#.2?L'πU"U0NqF?_D)XW,hV^n/HgK'^x.dl.iZPf]sZ0H^>;nl0cD(rKLpUMbnKWPa2c.I49πU",/5Tq;B,BZ(taES_:9qu$/-eb#YlQJkmNvhHe*;VBlToU:i>#1x-6Rcc]F/nIVQπU"W1AX720oVaAGOPP^K5,3<:t_>BF;PD?KH:_o)1RkSdxeR>C:O^CuM^Pk:lrO5,*πU"1ipBYTVifZti9%-2JM*%vi>5-2T_Zhwt2f-ZtC]8kGNvRL%%up(%)9%%%%-%p)wπU"UFm4p?R9%&%%T%(%%.%%%%y%wjjW%Snhs*f_VpB<u9TH8Py.(+8),LRWDC)a=*NπU"\'\l0LQQRZ?YI:F+p9,S%/33B\T__37-S;8-=BD6)?fq?]IwtTjEN.YNYTbBZ7tπU";Ln^$1fE<)uvHG1gMHOUT-_$yx5jNNuq5GcKY:P#^qZr'et(H&[CJBOJ*i>kH)7πU">kfEFzhIj'iHy[Dig,lI,^kz2LCovO<[QyEgXcm)ht.0Yn)^7KU$;oA+pVhkGbXπU"9ZWb#cUu&0=*3Sv4.?*<1ut>I.n<IGnXq<t/ua;CE_g0>3)faC[m4NdI_JdabpFπU";L;W=XM0HtS6ZTRn)J4B[z6#TgC2MV-(zl9c:*s2(%.E1Ar=Vqw]wZh8lN?v&s'πU"%up()%9%%%I-%jw/UF4f%l.6&%%%T(%%%.%%%%yw%jjXS[nhsf&_Vp(df9S8<FlπU"0N'=pL&LVex;KL)A%Su74:%)*p0cfK),MQT'(As9G%ow&:k>YMw+afeiK:JT$_eπU"f)\w#'0,5TX1tErW2lt4&MRO^zuMls8D8u]3=Sqte1+Y8J0pjP%#L6rgXHR9%/_πU"gIADwyCLacVEYC(BSer$g7lM.s#Uh\jJrr<>:'f>Aal1(*&NJ/P4=(m<FlF4X'/πU"CUDeIdaHZXYoY3Y,:a:f2[ND>V)Ye8KU<6U45N??APVP[6FDtem/Qe?2](Lj4&oπU"TDKmd?PHaC(fj+K$fW.f[$lOHS=,4nG_W9M[:kNO>6Ks/f%sZ&t4KS#uF8BF4=HπU"La?A7md'w;c&%up()%9%%%R-%Vw\UF,S)bY<&%%%T(%%%.%%%%yw%jjYS[nhsf,πU"_6o(df9T8?B?EEi[uZ:e\6;%%)#*0_bCNfB/ym8+649+E5T4/J0>WtITEsBI*0<πU"K%+fp.sNL=nrG=ih#.Qa?QoW^lp$B1,/jF;+Lzy3A?uMKT\-x<8n#h6E3P;>ci,πU"v]MXBBdhMI.Lf?]Nl%Fq$mz8/wfDYo),]\Hq-W:FGNX\zL)HmgUNxRtuSm,1m/$πU"9J=$5Gm7vaIWkhesu86#\i6Ps?%L2ok<E1ZhQi^L)S\vo_3ZY=T#U-5bxe<;dQsπU"su_au7*t_*l:K4(+&q?4a,L*f2Dagx=SWe1[mT3nt)_Wd^ae04j=)&mPUPX*8qiπU"6.\NZ(>Ob\;rs_q:bUZkk<0kZRxd>'b(up%()9%%%%-%1>xUF^sQ=6%7&%%%T(%πU"%%.%%%%ywjj%ZSnh4sf_V+p<u9bT8I>J&ia=r.R?*)b:,0_x*l0LQQQr/R_4N'sπU"/3s.sBT_Ks,S=*7pdiV?d[%#foa8pCQx9f:(Vhtm5Up:SFnaVT=MpE<)rMJBp=GπU"P%Sd2KHohkqI%3jW$h8r3)D>tRa;X+0F-Q$_HHOS0n#P5G,h6[QVsy/=3Z:JkP,πU"SNDVJU&qnSsHX1c2a*(F1Rqay^I>a7EnB?XwzW<&^lI*Kk7N=guI5I,ar=8L/>kπU"L.k&+oT4xpGjR'ck+Q>\g2W6'+2<49kR-?k[QVBggE[G/0m^EaT]&<mLp'E(vP^πU">e_d%2#2D^u;Cy./:ryBVnxx&nP'89*F$j^hW3ns.8NpXu%p&'9%%9%%#%-%kD3πU"WFl10ZvV#4%%:%S%%1%%%%%%%%%&%%E%%%%%%%%%fsn%Rqnk%jSgf%xup&%'9%9πU"%%%%-I%/wUCFLo+-Ht%%%%T(%%%.%%%%%%%%%%%E#%%%*%4%%y%wjjV%Snhs%upπU"&'%9%9%%%%-%1pwUFRmp?R%9&%%%T(%%%.%%%%%%%%%%%E%.%%L5%%%yw%jjWS%πU"nhsu%p&'9%%9%%#%-%jDwUF4%fl.6%&%%T%(%%.%%%%%%%%%%%%E%%+%16%%%ywπU"j%jXSn%hsup%&'9%%9%%%R-%Vw\UF,S)bY<&%%%T(%%%.%%%%%%%%%%%%E%%%'iπU"7%%%ywjj%YSnh%sup&%'9%9%%%%-I%>xU.FsQ='67&%%%T(%%%.%%%%%%%%%%%EπU"%%%%S%9%%y%wjjZ%Snhs%up*+%%%%%%+%+%%r&%%&6:%%%%%πEND SUBπCLOSE:IF S=146AND B&=Z&THEN?" :) Ok!"ELSE?" :( Bad!πSUB U(A$):FOR A=1TO LEN(A$):C=ASC(MID$(A$,A))-37:IF C<0THEN C=91+C*32πIF K<4THEN K=C+243ELSE?#1,CHR$(C+(K MOD 3)*86);:K=K\3:B&=B&+1πS=(S+C)AND 255:NEXT:LOCATE,1:?STRING$(B&*50\Z&,219);:END SUBπTika Carr COMMAND$ PARSER FidoNet QUIK_BAS Echo 11-01-96 (12:31) QB, PDS 120 4847 CMDPARSE.BAS'> Does anyone have an example of how to call SWITCHES from within QB?ππ'If you mean how to parse the COMMAND$, then here's a routine I addedπ'to my own QuickLibrary that may be of help:ππDECLARE SUB GetArg ()πDECLARE FUNCTION ExePath$ ()π'$INCLUDE: 'qb.bi'ππDIM SHARED arg$(0 TO 85)ππ'GETARG.BAS: COMMAND$ Parserπ'-----------------------------------------------------------------------π'Revision History:π'π' 1.0 10/28/96 Created tcπ'-----------------------------------------------------------------------π'Description/Instructions:π'π'Parses the COMMAND$ (which holds any parameters passed to the programπ'from the command line). Returns the full path and filename of theπ'program currently running in the global variable arg$(0). arg$(1) toπ'arg$(85) holds each the command line parameters passed. Simply look forπ'one of the arrays to be blank (ie. arg$(x)="") for the end of the list.π'if arg$(1)="" then there were no parameters passed to the program (hereπ'you would have it print a usage or help screen).π'-----------------------------------------------------------------------π'**** TEST Program ****π'Set COMMAND$ for something like: test /sw1 /er /x -s Macroπ'Then run the program below. After that, try passing no paramteres byπ'setting COMMAND$ to "" or nothing. This is done in the IDE from the RUNπ'menu, Modify COMMAND$ option.π'πCLSπGetArgπPRINT "The program running is: "; arg$(0)π'Note that the above line may give the full path and file name to theπ'QuickBasic 4.5 IDE program if you don't compile this. But when put inπ'A library and it is compiled, it will show the correct executable andπ'path.ππIF arg$(1) = "" THENπ PRINT "You didn't pass any parameters"πELSEπ i = 1π DO UNTIL arg$(i) = ""π PRINT "Parameter #"; i; " is: "; arg$(i)π i = i + 1π LOOPπEND IFπPRINT i - 1; " parameters were found, excluding the name of the program."π'-----------------------------------------------------------------------πDEFINT A-ZπSUB GetArgπarg$(0) = ExePath$πIF COMMAND$ = "" THEN EXIT SUBπi = 1: j = 1πDO UNTIL i >= LEN(COMMAND$)π WHILE MID$(COMMAND$, i, 1) <> " " AND MID$(COMMAND$, i, 1) <> ""π arg$(j) = arg$(j) + MID$(COMMAND$, i, 1)π i = i + 1π WENDπ i = i + 1: j = j + 1πLOOPπEND SUBπ'-----------------------------------------------------------------------πDECLARE FUNCTION ExePath$ ()πDEFINT A-Zπ'$INCLUDE: 'qb.bi'ππ'EXEPATH$.BAS: Gets the path and filename of the executable running.π' by Joe Negron. Function name changed by Tika Carr.π'-----------------------------------------------------------------------π'Function Description:π'π'"Uses DOS ISR 21H, Function 51H (Get PSP Address) to return theπ'name of the currently executing program. Note that this FUNCTIONπ'requires DOS 3.0 or >."π'-----------------------------------------------------------------------π'**** TEST Program ****π'E$ = ExePath$π'PRINT E$π'-----------------------------------------------------------------------πFUNCTION ExePath$ STATICπ DIM Regs AS RegType 'Allocate space for TYPEπ ' RegTypeπ Regs.ax = &H5100 'DOS function 51hπ Interrupt &H21, Regs, Regs ' Get PSP Addressππ DEF SEG = Regs.bx 'Regs.bx returns PSP sgmnt.π EnvSeg% = PEEK(&H2C) + PEEK(&H2D) * 256 'Get environment addressπ DEF SEG = EnvSeg% 'Set environment addressππ DOπ Byte% = PEEK(Offset%) 'Take a byteππ IF Byte% = 0 THEN 'Items are ASCIIZπ Count% = Count% + 1 ' terminatedππ IF Count% AND EXEFlag% THEN 'EXE also ASCIIZ terminatedπ EXIT DO 'Exit at the endπ ELSEIF Count% = 2 THEN 'Last entry in env. isπ EXEFlag% = -1 ' terminated with twoπ Offset% = Offset% + 2 ' NULs. Two bytes aheadπ END IF ' is the EXE file name.π ELSE 'If Byte% <> 0, resetπ Count% = 0 ' zero counterππ IF EXEFlag% THEN 'If EXE name found,π Temp$ = Temp$ + CHR$(Byte%) ' build stringπ END IFπ END IFππ Offset% = Offset% + 1 'To grab next byte...π LOOP 'Do it againππ DEF SEG 'Reset default segmentπ ExePath$ = Temp$ 'Return valueπ Temp$ = "" 'Clean upπEND FUNCTIONπChristy Gemmell PROGRAM ERRORLEVELS FidoNet QUIK_BAS Echo 06-16-96 (00:00) QB, PDS 65 2373 ERRLEVEL.BAS' ========================================================================ππ 'How about exiting your program with an ErrorLevel to give to DOS.π 'Useful for use in batch files using "IF ERRORLEVEL n GOTO label"ππ 'WARNING: Do not use this whilst in the QuickBASIC environment, asπ 'all hell will break loose. You will loose your program and maybeπ 'even lose other data too - You have been warned !!!πππ 'Here is the Declare...put it in your main module:π DECLARE SUB ExitWithErrLvl ALIAS "_exit" (BYVAL errorlevel%)ππ 'Now some sample code to show how to use it:π 'This example will exit setting ErrorLevel to 3.ππ VarE% = 3π PRINT "Exiting with errorlevel";VarE%π ExitWithErrLvl VarE%ππ' -----------------------------------------------------------------------ππ 'How about Shelling out to, and running, another program and thenπ 'obtaining the ErrorLevel returned from that SHELL'd program?ππ 'NEWSHELL.FUN an alternative to the shell command which returns an 'π 'ERRORLEVEL code. 'π 'Author: Dave Navarroπ 'For: PowerBASICπ 'Date: 16/6/1995ππ 'Adapted for QuickBASIC by Christy Gemmellππ 'You must $INCLUDE: 'QB.BI' at the top of your main program andπ 'LINK the executable with QB.LIB (or load QB.QLB into the IDE).πππ'$INCLUDE: 'QB.BI'ππDECLARE FUNCTION MyShell% (Program$, Parameters$)ππ' Enter the *full* Program Name here (eg. XCOPY.EXE)πProgram$ = "XCOPY.EXE"ππ' Enter any parameters (command line switches) hereπParameters$ = "*.* A:"πππPRINT MyShell%(Program$, Parameters$)ππFUNCTION MyShell% (Program$, Parameters$)π DIM Regs AS RegType ' For use with CALL INTERRUPTπ Path$ = ENVIRON$("PATH") ' Save PATHπ Comspec$ = ENVIRON$("COMSPEC") ' Save COMSPECπ ENVIRON "PATH=" ' Temporarily remove the pathπ ENVIRON "COMSPEC=" + Program$ ' Set COMSPEC to our programπ SHELL Parameters$ ' Execute the programπ ENVIRON "COMSPEC=" + Comspec$ ' Restore the comspecπ ENVIRON "PATH=" + Path$ ' Restore the pathπ Regs.ax = &H4D00 ' DOS service 77π INTERRUPT &H21, Regs, Regs ' - get ERRORLEVEL codeπ MyShell% = Regs.ax AND &HFF ' Return exit codeπEND FUNCTIONππ' ------------------------------------------------------------------------πBryan J. Kyle BATCH UTILITIES hakyle@OctoNet.com 11-15-96 (21:48) PB 154