Bryan Leggo XMODEM TRANSFER PROTOCOL XMODEM,TRANSFER,PROTOCOL Unknown Date (00:00) QB, PDS 718 31867 XMODEM.BAS ã' +-------------------------------------------------------------------+ã' | |ã' | XMODEM.BAS Author: Bryan Leggo |ã' | |ã' | Original XModem, XModem-CRC, and XModem-1K Transfer Protocols |ã' | |ã' | Uses standard QuickLibrary for "FileExists" function. Use /L |ã' | for QB.QLB in environment or the .LIB while compiling. |ã' | |ã' +-------------------------------------------------------------------+ããDECLARE FUNCTION CalcCheckSum% (Blk$)ãDECLARE FUNCTION CalcCRC& (X$, CRCHigh%, CRCLow%)ãDECLARE FUNCTION FileExists% (T$, Attrib%)ãDECLARE FUNCTION NoCarrier% ()ãDECLARE FUNCTION TimedGet$ (Limit&, Cancelled%)ãDECLARE FUNCTION Warn$ (Message$)ãDECLARE SUB ClrLn (Ln%, Spaces%)ãDECLARE SUB OpenCom (ComChan%, Param$)ãDECLARE SUB PurgeBuffer ()ãDECLARE SUB ReceiveXModem (BlkSize%, F$)ãDECLARE SUB SendXModem (BlkSize%, F$)ãDECLARE SUB SimpleTerminal ()ãDECLARE SUB Txt (Side$, T$)ãDECLARE SUB Transfer (WhichWay$)ãDECLARE SUB VidBar (BarOn%, Col%, Length%)ããTYPE RegTypeX 'Register Type forã ax AS INTEGER ' Interrupt Callsã bx AS INTEGERã cx AS INTEGER 'AX = AH ALã dx AS INTEGER 'BX = BH BL, etc.ã bp AS INTEGERã si AS INTEGERã di AS INTEGERã Flags AS INTEGERã ds AS INTEGERã es AS INTEGERãEND TYPEããCONST TRUE = -1, FALSE = 0 'Boolean ConstantsããDEFINT A-ZããDIM SHARED CR$, LF$, BS$, Escape$ 'Global String ConstantsãDIM SHARED Lft$, Rght$, Up$, Down$ãDIM SHARED PgUp$, PgDown$ãDIM SHARED XOn$, XOff$ãDIM SHARED Ack$, Nak$, Soh$, Stx$, Eot$, Can$ 'Protocol Pseudo-ConstantsãDIM SHARED ComBase, Baud&ãDIM SHARED Txt1st, TxtMax 'Used by Txt SubãDIM SHARED Kolor, BGKolor 'Screen ColorsãDIM SHARED ErrCode, ErrCt 'Error Number & Countãã'===========================================================================ã' I N I T I A L I Z E V A R I A B L E Sã'===========================================================================ããCR$ = CHR$(13): LF$ = CHR$(10): BS$ = CHR$(8): Escape$ = CHR$(27)ãUp$ = CHR$(0) + CHR$(72): Down$ = CHR$(0) + CHR$(80)ãLft$ = CHR$(0) + CHR$(75): Rght$ = CHR$(0) + CHR$(77)ãPgUp$ = CHR$(0) + CHR$(73): PgDown$ = CHR$(0) + CHR$(81)ãXOn$ = CHR$(17): XOff$ = CHR$(19): Ack$ = CHR$(6): Nak$ = CHR$(21)ãSoh$ = CHR$(1): Stx$ = CHR$(2): Eot$ = CHR$(4): Can$ = CHR$(24)ããBaud& = 2400 'Set the BaudRateãParam$ = STR$(Baud&) + ",N,8,1,RS,OP,CD0,DS0" ' and Com Parametersããã'===========================================================================ã' M A I N P R O G R A Mã'===========================================================================ããOpenCom 1, Param$ 'Open Port 1 with Parameters$ãSimpleTerminal 'Terminal ModeãENDããã'***************************************************************************ã' E R R O R H A N D L E Rã'***************************************************************************ããHandler:ãErrCode = ERR 'Copy Err # to Global VarãErrCt = ErrCt + 1 'Try Statement Causing the ErrorãIF ErrCt MOD 3 = 0 THEN ' Twice Before Giving Up andã RESUME NEXT: ErrCt = 0 ' Going to the Next StatementãELSEã RESUMEãEND IFããFUNCTION CalcCheckSum (Blk$) 'Returns CheckSum on Blk$ããC& = 0 'Use Long Int to Avoid OverflowãFOR Q = 1 TO LEN(Blk$)ã C& = C& + ASC(MID$(Blk$, Q, 1)) 'Add to Add Bits of Each ByteãNEXT QãC& = (C& AND 255) 'AND Out Hi Byte BitsãCalcCheckSum = C&ãEND FUNCTIONããFUNCTION CalcCRC& (B$, CRCHigh%, CRCLow%) 'Calculates CRC for Each BlockããDIM Power(0 TO 7) 'For the 8 Powers of 2ãDIM CRC AS LONGããFOR I = 0 TO 7 'Calculate Once Per Block toã Power(I) = 2 ^ I ' Increase Speed Within FOR JãNEXT I ' LoopãCRC = 0 'Reset for Each Text BlockãFOR I = 1 TO LEN(B$) 'Calculate for Length of Blockã ByteVal = ASC(MID$(B$, I, 1))ã FOR J = 7 TO 0 STEP -1ã TestBit = ((CRC AND 32768) = 32768) XOR ((ByteVal AND Power(J)) = Power(JCRC = ((CRC AND 32767&) * 2&)))ã IF TestBit THEN CRC = CRC XOR &H1021& ' <-- This for 16 Bit CRCã '*** IF TestBit THEN CRC = CRC XOR &H8005& ' <-- This for 32 Bit CRCã NEXT JãNEXT IãCRCHigh% = (CRC \ 256) 'Break Word Down into BytesãCRCLow% = (CRC MOD 256) ' for Comparison LaterãComputeCRC& = CRC 'Return the Word ValueãEND FUNCTIONããREM $DYNAMICãSUB ClrLn (Ln, Spaces) 'Clears Line from Left SideãLOCATE Ln, 1, 0: PRINT SPACE$(Spaces); ' for Number of DesignatedãLOCATE Ln, 1 ' Spaces. Returns Cursor toãEND SUB ' to First Column AfterwardsããFUNCTION FileExists (T$, Attrib) 'True if File T$ Exists else FalseããDIM F AS STRING * 64ãDIM Inx AS RegTypeXãDIM Outx AS RegTypeXããInx.ax = &H2F00 'Function 2FH Gets the DTA Address inãCALL INTERRUPTX(&H21, Inx, Outx) ' ES:BXãDTASeg = Outx.esãDTAAddr = Outx.bxãF$ = LTRIM$(RTRIM$(UCASE$(T$))) + CHR$(0)ããInx.ds = VARSEG(F$) 'Pass the File Specs by Giving AddressãInx.dx = VARPTR(F$) ' of String that Contains SpecificationãInx.ax = &H4E00 'Function 4EH for Find 1st Matching EntryãInx.cx = Attrib 'CX = Directory Attribute (0=Files Only)ãCALL INTERRUPTX(&H21, Inx, Outx) 'Use Interrupt 21HãIF Outx.Flags AND 1 THENã FileExists = FALSEãELSEã FileExists = TRUEãEND IFããEND FUNCTIONããFUNCTION NoCarrierããDEF SEG = &H40ãIF (INP(ComBase + 6) AND 128) = 0 THEN NoCarrier = TRUE ELSE NoCarrier = FALSEãDEF SEGããEND FUNCTIONããREM $STATICãSUB OpenCom (ComChan, Param$)ããCLOSE 1ãSELECT CASE ComChan 'Will Require Swapping at &H400, &H402ãCASE 1 ' Order to Support Com 3 and 4ã ComBase = &H3F8ã OPEN "R", 1, "COM1:" + Param$ãCASE 2ã ComBase = &H2F8ã OPEN "R", 1, "COM2:" + Param$ãEND SELECTããEND SUBããSUB PurgeBuffer 'Clear Comm Line of CharsããMark& = TIMER 'Mark Starting TimeãDOã IF NOT EOF(1) THEN 'Get More Chars While Someã JunkIt$ = INPUT$(1, 1): Mark& = TIMER ' In the Buffer and it'sã END IF ' Less Than 1/2 SecondãLOOP UNTIL EOF(1) AND (ABS(TIMER - Mark&) > .5) ' Since Last Char GottenãEND SUBããSUB ReceiveXModem (BlkSize, F$) '(Block Size and Filename)ãDIM B$(1 TO 4) 'Temp Storage of Block BytesããCLOSE 9: OPEN "O", #9, F$ 'Save File to Channel #9ãPRINT #1, XOff$; XOn$;ãCancels$ = STRING$(3, Can$)ãUnderway = FALSE 'True After 1st Pkt ConfirmedãBlocks = 1 'Block/Pkt Counter (1-Max)ãBlkNum = 1 'Packet Block Number (1-255)ãBad = 0 'Bad Packets/Error CountãBCt = 0 'RAM Block Ptr for B$()ãPurgeBuffer 'Get Rid of Extra CharsãCrcMode = TRUE: PktSize = BlkSize + 5 'Try CRC Mode FirstãPRINT #1, "C"; 'Send "C" to Signal ItãããGetPacket: 'Get Packet of Bytesã'IF NoCarrier THEN ErrType = 13: GOTO ShowErr 'Are We Still Online?ãPkt$ = ""ãFOR Tries = 1 TO 10 'Allow 10 Triesã W$ = TimedGet$(8, Cancelled) 'Get Response/1st Char of Pktã IF Cancelled THEN ErrType = 11: GOTO ShowErr 'Quit If User Cancelledã SELECT CASE W$ '1st Byte Is:ã CASE Soh$: BlkSize = 128: EXIT FOR 'Soh = 128 Byte Block Comingã CASE Stx$: BlkSize = 1024: EXIT FOR 'Stx = 1K Block Comingã CASE Eot$: GOTO ReceptionDone 'End of Xmission. Close Out.ã CASE Can$: EXIT FOR 'Cancelled by Senderã CASE "" 'No Char In Means Timed Outã Bad = Bad + 1: LOCATE 7, 40ã PRINT "Tries:"; Tries; TAB(80);ã CASE ELSE 'Else Didn't Get An Expectedã PurgeBuffer ' Response So Purge Charactersã END SELECTã IF NOT Underway THEN 'Handshaking Not Complete Yetã IF Tries < 4 THEN ' So Send Out Init Char Againã CrcMode = TRUE: PRINT #1, "C"; ' Send a "C" to Start CRC orã ELSE ' a for Standard Modeã CrcMode = FALSE: PRINT #1, Nak$;ã END IFã END IFã IF Bad >= 10 THEN 'Have Reached the Max of 10ã ErrType = 14: PurgeBuffer: GOTO ShowErr ' Errors from TimeOuts orã END IF ' Bad Packets so AbortãNEXT TriesãIF CrcMode THEN 'Blk Size Determined by ã PktSize = BlkSize + 5 ' or , PacketSize byãELSE ' BlockSize and Type of Checkã PktSize = BlkSize + 4 ' Used (1 Extra Byte for CRC)ãEND IFãPkt$ = W$ 'We've Got the First ByteãWHILE LEN(Pkt$) <= PktSize - 1 'Now Get Rest of Packetã W$ = TimedGet$(4, Cancelled)ã IF Cancelled THEN ErrType = 11: GOTO ShowErrã IF LEN(W$) THEN 'If There is a Byte then Addã Pkt$ = Pkt$ + W$ ' it to the Packetã IF LEFT$(Pkt$, 3) = Cancels$ THEN 'Packet Starting with Threeã PRINT #1, Cancels$; Ack$; ' s Is a Cancellation Soã ErrType = 12: GOTO ShowErr ' nowledge And Abortã END IFã ELSE 'Else Null Means We Timed Outã Bad = Bad + 1ã LOCATE 7, 40: PRINT TAB(80);ã LOCATE 7, 40: PRINT "Character Timeout. Errors:"; Bad;ã GOTO CheckPacketã END IFãWENDããCheckPacket: 'Check Packet ErrorsãIF LEN(Pkt$) = PktSize THEN 'If Packet Right Sizeã IF BlkNum = ASC(MID$(Pkt$, 2, 1)) + 1 AND (BlkNum XOR 255) = ASC(MID$(Pkt$, ErrType = 7)) THEN GOTO ShowErr 'Repeated Block #ã ELSEIF BlkNum <> ASC(MID$(Pkt$, 2, 1)) THEN 'Block Counts Don'tã ErrType = 5: GOTO ShowErr ' Match. Try New Pktã ELSEIF (BlkNum XOR 255) <> ASC(MID$(Pkt$, 3, 1)) THEN 'Block Ct Complementã ErrType = 6: GOTO ShowErr ' Mismatch. Try Newã END IF ' Packetã Blk$ = MID$(Pkt$, 4, BlkSize) 'Else Copy the Blockã IF CrcMode THEN 'Do CheckSum or CRCã J& = CalcCRC&(Blk$, Hi, Low)ã IF Hi <> ASC(MID$(Pkt$, PktSize - 1, 1)) THEN ErrType = 4: GOTO ShowErrã IF Low <> ASC(MID$(Pkt$, PktSize, 1)) THEN ErrType = 4: GOTO ShowErrã ELSEã ChkSum = CalcCheckSum(Blk$)ã IF ChkSum <> ASC(MID$(Pkt$, PktSize, 1)) THEN ErrType = 3: GOTO ShowErrã END IFã GOSUB ShowProgress 'Displays Xfer Statusã BlkNum = 255 AND (BlkNum + 1) 'Success Thru All CheckPtsã Blocks = Blocks + 1: Bad = 0 ' so Increment Block Ctsã Underway = TRUE ' Mark Handshake Completedã IF BlkSize = 1024 THEN 'For Xmodem-1k Write to Diskã PRINT #9, Blk$; ' Immediatelyã ELSEã BCt = BCt + 1: B$(BCt) = Blk$ 'Else Save 4 Blocks In RAMã IF BCt = 4 THEN ' Write them to Disk Everyã PRINT #9, B$(1); B$(2); B$(3); B$(4); ' 4th, i.e. After 512 Bytesã BCt = 0 ' Reset RAM Block Indexã END IFã END IF 'Acknowledge Good Block Readã PRINT #1, Ack$; ' And Go to Get Next Packetã GOTO GetPacketãIF LEN(Pkt$) < PktSize THEN ErrType = 1: GOTO ShowErr 'Err and Get New PacketãIF LEN(Pkt$) > PktSize THENã ErrType = 2: GOTO ShowErr ' And Get New PacketãELSE 'Else an Unexpected Errorã ErrType = 8: GOTO ShowErr ' So Warn and Try for NewãEND IF ' Packetã ' Last 2 Should NOT OccurããReceptionDone:ãIF BCt <> 0 THEN 'If Some Bytes Still Inã FOR I = 1 TO BCt: PRINT #9, B$(I); : NEXT I ' Memory Then Write ThemãEND IF ' to DiskãCLOSE 9: PRINT #1, Ack$; 'Xmit Complete so CloseãEXIT SUB ' File and Send Final Ackããã'---------------------------------------------------------------------------ããShowErr:ãResponse$ = Nak$ 'Send Nak After Most ErrorsãSELECT CASE ErrTypeãCASE 1: ErM$ = "Short Block in #" + STR$(Blocks)ãCASE 2: ErM$ = "Long Block in #" + STR$(Blocks)ãCASE 3: ErM$ = "Checksum Error in #" + STR$(Blocks)ãCASE 4: ErM$ = "CRC Error in #" + STR$(Blocks)ãCASE 5: ErM$ = "Block # Error in #" + STR$(Blocks)ãCASE 6: ErM$ = "Complement Error in #" + STR$(Blocks)ãCASE 7: ErM$ = "Block # Repeated in #" + STR$(Blocks - 1): Response$ = Ack$ãCASE 8: ErM$ = "Unexpected Error!"ãCASE 9:ãCASE 10: ErM$ = "Transfer Cancelled"ãCASE 11: ErM$ = "Transfer Aborted by User"ãCASE 12: ErM$ = "Transfer Aborted by Sender"ãCASE 13: ErM$ = "No Carrier"ãCASE 14: ErM$ = "Maximum Errors. Transfer Aborted."ãEND SELECTãLOCATE 7, 40: PRINT TAB(80); 'Show the ErrorMsgãLOCATE 7, 40: PRINT ErM$;ãIF ErrType < 10 THEN 'ErrType < 10 is Recoverableã Bad = Bad + 1 ' Count One More Errorã PRINT #1, Response$; ' Respond Nak (or Ack) andã Pkt$ = "": GOTO GetPacket ' Go to Get Packet AgainãELSEã J$ = Warn$(ErM$) 'Notify User of Cancelã SLEEP 2: PurgeBuffer 'Get Rid of Remaining Pktã PRINT #1, STRING$(5, 24); STRING$(5, 8); 'Send 5 s & 5 sã CLOSE 9: KILL F$ 'ErrType >= 10 is Fatal soã EXIT SUB ' Kill Off File and QuitãEND IFãã'---------------------------------------------------------------------------ããShowProgress: 'Show Byte Counts & BarãKBytes = INT(Blocks * (BlkSize / 1024))ãLOCATE 5, 40: PRINT "Received #"; Blocks; TAB(60); KBytes; "K Bytes";ãIF BarLength = 0 THENã LOCATE 9: VidBar FALSE, 1, 80ã FOR K = 1 TO 9ã LOCATE 10, K * 8 - 1ã PRINT LTRIM$(STR$(100 * (KBytes \ 100) + (K * 10))); "K ";ã NEXT KãEND IFãBarLength = INT(80 * ((KBytes MOD 100) / 100))ãLOCATE 9: VidBar TRUE, 1, BarLengthãRETURNãããã' Block refers to Block of Text from File (128 bytes, 1024 for Xmodem-1K)ã' Packet Refers to Block + Extra "Control" Characters, i.e. :ãã' XModem: SOH + BlockCt + Complement BlockCt + Block + CheckSumã' XModemCRC: SOH + BlockCt + Complement BlockCt + Block + CRC (Hi & Low)ã' XModem-1K: STX + BlockCt + Complement BlockCt + Block + CheckSumã' XModemCRC-1K: STX + BlockCt + Complement BlockCt + Block + CRC (Hi & Low)ããEND SUBããSUB SendXModem (BlkSize, F$) '(Bytes, FileName$)ããCLOSE 9: OPEN F$ FOR RANDOM AS 9 LEN = 128ãFIELD #9, 128 AS BlkOf128$ãFiLen& = LOF(9): TtlBlocks = FiLen& \ BlkSize 'Get File LengthãIF FiLen& MOD BlkSize > 0 THEN TtlBlocks = TtlBlocks + 1 ' in Bytes & BlocksãLOCATE 3, 40: PRINT "Blocks:"; TtlBlocks; TAB(60);ãSeconds = ((TtlBlocks * 6) + FiLen&) \ (Baud& \ 16)ãEst$ = STR$(Seconds \ 3600) + STR$(Seconds \ 60) + STR$(Seconds MOD 60)ãFOR I = 2 TO LEN(Est$)ã IF MID$(Est$, I, 1) = " " THEN MID$(Est$, I, 1) = ":"ãNEXT IãPRINT "Est. Time:"; Est$;ããErM$ = "Transfer Aborted" 'Generic Msg In Case of ErrorãBlocks = 0: BlkNum = 0 'Blocks (1-?), BlkNum (1-255)ãEoFile = FALSE: W$ = "" 'Initialize Block, Byte,ãCt& = 0 'To Count Bytes Used & SentãBad = 0 'Error CounterãPurgeBuffer 'Clear the Com LineããDO 'Shake Hands with Receiverã W$ = TimedGet$(20, Cancelled) 'Get Initial Characterãã IF Cancelled THEN GOTO AbortSend 'If User Pressed ã SELECT CASE W$ã CASE Can$: GOTO AbortSend 'Receiver is Cancellingã CASE Nak$: CrcMode = FALSE: EXIT DO 'Nak for Standard XModemã CASE "C": CrcMode = TRUE: EXIT DO 'C Indicates XModem-CRCã END SELECT 'Begin After or CãLOOPããMakePacket:ãIF NoCarrier THEN 'Still Online?ã ErM$ = "No Carrier!": GOTO AbortSendãEND IFãW$ = "": Blocks = Blocks + 1: Bad = 0 'Advance Block CounterãIF (BlkSize = 1024) AND ((Ct& + 896) > FiLen&) THEN 'If Doing 1k and at Endã BlkSize = 128 ' of File Then ShortenãEND IF ' to Avoid Extra NullsãIF BlkSize = 128 THEN MaxBCt = 1 ELSE MaxBCt = 8 '8 Groups of 128 = 1024ãBCt = 0: Blk$ = "" 'Build the Block$ãDOã Ct& = Ct& + 128: GET #9 'Advance File Ptr, Get Froã BCt = BCt + 1: Blk$ = Blk$ + BlkOf128$ã IF Ct& >= FiLen& THEN 'If It's Last Block We'reã EoFile = TRUE ' About Done Xmittingã Pad = Ct& - FiLen& ' Pad the End with Nullsã MID$(Blk$, BlkSize - Pad, Pad) = STRING$(Pad, CHR$(0))ã EXIT DOã END IFãLOOP UNTIL BCt = MaxBCt 'Done After 1 (8 for 1k)ãBlkNum = (255 AND Blocks) ' So Assemble the PacketãPkt$ = Soh$ + CHR$(BlkNum) + CHR$(BlkNum XOR 255) + Blk$ãIF BlkSize = 1024 THEN MID$(Pkt$, 1, 1) = Stx$ '1st Byte is Stx for 1KãIF CrcMode THEN 'End of Packet Variesã J& = CalcCRC&(Blk$, Hi%, Low%) ' with Check Method Usedã Pkt$ = Pkt$ + CHR$(Hi%) + CHR$(Low%) ' 2 Bytes for CRCãELSEã ChkSum = CalcCheckSum(Blk$) ' 1 Byte for CheckSumã Pkt$ = Pkt$ + CHR$(ChkSum)ãEND IFããSendPacket:ãPRINT #1, Pkt$; 'Send the Packet andãLOCATE 5, 40: PRINT "Sending #"; Blocks; ' Show Progress on ScreenãP = INT((Blocks / TtlBlocks) * 100) 'Calculate PercentageãIF P <= 100 THEN 'Percentage Can Be > 100ã LOCATE 5, 60: PRINT P; "% Complete": LOCATE 9 ' On Last Blocks of 1kã VidBar TRUE, 1, INT((Blocks / TtlBlocks) * 80) ' Mode Since Last 1024 isãEND IF ' Sent in 128 Byte BlocksããDO 'Packet Has Been Sent soã W$ = TimedGet$(10, Cancelled) 'Get Response/Confirmã IF Cancelled THEN GOTO AbortSend 'Quit If User apedã SELECT CASE W$ 'Interpret Responseã CASE Ack$ 'Block Acknowledged Soã Bad = 0 ' Send Next Packet Ifã IF EoFile THEN EXIT DO ELSE GOTO MakePacket ' More Dataã CASE ELSE 'Elseã Bad = Bad + 1 ' Count 1 More Errorã IF Bad > 9 THEN GOTO AbortSend ' Abort If Over Limitã IF W$ = Can$ THEN 'If a Then Lookã FOR I = 1 TO 2 ' For at Least 2 More toã W$ = W$ + TimedGet$(2, Cancelled) ' Be Sure (Or User Esc)ã IF Cancelled THEN GOTO AbortSendã IF W$ = STRING$(3, Can$) THEN GOTO AbortSendã NEXT Iã GOTO SendPacketã ELSEã PurgeBuffer 'Any Other Char Is anã GOTO SendPacket ' Error So ReSend Packetã END IF ' & Look for Againã END SELECTãLOOPããConcludeSend:ãErM$ = "End of Transmission": GOSUB ShowStatus 'Proper End of TransmitãCLOSE 9: PRINT #1, Eot$; 'Close File, Send the EOTãI$ = TimedGet$(10, Cancelled) 'Get Final CharãIF I$ = Ack$ THEN 'Should Be an butã ErM$ = "Acknowledged": GOSUB ShowStatusãELSEIF Cancelled THEN 'Allow User to Cancelã EXIT SUBãELSE 'If Not an Resendã GOTO ConcludeSend ' and Try AgainãEND IFãEXIT SUBãã'---------------------------------------------------------------------------ããAbortSend:ãJ$ = Warn$(ErM$) 'Show Error StatusãCLOSE 9 'Close FileãPRINT #1, STRING$(5, Can$); STRING$(5, BS$); 'Send Cancel to ReceiverãEXIT SUBãã'---------------------------------------------------------------------------ããShowStatus:ãLOCATE 7, 40: PRINT ErM$; TAB(80); 'Show the Status or ErrorMsgãRETURNããEND SUBããSUB SimpleTerminalãON ERROR GOTO HandlerãFF$ = CHR$(12): Hm$ = CHR$(11)ããCLS : GOSUB InfoBarãPRINT #1, "AT S0=1" 'Send Modem Initialization StringãDOã Out$ = INKEY$ 'Look for Key Pressã 'IF LEN(Out$) THEN 'If There IS One then Selectã SELECT CASE Out$ã CASE PgUp$, PgDown$ ' to Upload or Downloadã Transfer Out$: GOSUB InfoBarã CASE Escape$ ' Escape to End Programã EXIT DOã CASE CHR$(0) + CHR$(59)ã PRINT #1, "atdt 626-9456"ã CASE ELSEã PRINT #1, Out$; ' Else Send the Character Verbatimã END SELECTã 'END IFã IF LOC(1) THEN 'Is there Incoming Data from Com?ã DO ' If So then Get Chars Until Noã ComChr$ = INPUT$(1, 1) ' More or End of a Line ã SELECT CASE ComChr$ã CASE BS$: ComChr$ = CHR$(29) 'Replace BackSpaces with CHR$(29)ã CASE FF$, Hm$: ComChr$ = "" 'Filter these Outã CASE LF$: ComChr$ = "": EXIT DO 'Ignore Linefeeds But Exit Do Loopã END SELECTã PRINT ComChr$; 'Print the Char Received On Screenã LOOP UNTIL LOC(1) = 0 'No More Com Waitingã END IFãLOOPãEXIT SUBãã'---------------------------------------------------------------------------ããInfoBar:ãCLSãLOCATE 24, 1: COLOR 0, 7ãPRINT " to Upload, to Download, to End Program ": COLOR 7, 0: LOCATE 24, 1ãRETURNããEND SUBããFUNCTION TimedGet$ (Limit&, Cancelled) 'Timed Routine to Get Oneã 'Character from Comm PortãMark& = TIMER 'Mark Starting TimeãDOã IF NOT EOF(1) THEN 'If Chars Waiting Thenã TimedGet$ = INPUT$(1, 1): EXIT FUNCTION ' Return 1 Characterã END IFã IF INKEY$ = Escape$ THEN 'User Can Press toã Cancelled = TRUE: EXIT FUNCTION ' Quitã END IFãLOOP WHILE ABS(TIMER - Mark&) < Limit& 'Wait Up Until Past LimitãTimedGet$ = "" 'Return "" If Timing OutãEND FUNCTIONããREM $DYNAMICãSUB Transfer (WhichWay$) 'WhichWay = PgUp (U/L), PgDn (D/L)ãON ERROR GOTO HandlerããNumProtos = 4 'Number of Protocols HereãSendDir$ = "" 'Define Directories Where Files WillãRecvDir$ = "" ' Be DownLoaded To or Uploaded FromãSendExternal$ = "" 'DOS Command Line Used to ExecuteãRecvExternal$ = "" ' External Protocol (~ for Filename)ãKolor = 0: BGKolor = 7 'Transfer Area in Reverse Video forãCOLOR Kolor, BGKolor ' ContrastãVIEW PRINT 1 TO 11: CLS 2: VIEW PRINT 'Clear Top 11 LinesãLOCATE 11, 1: PRINT STRING$(80, "#");ããIF WhichWay$ = PgUp$ THEN 'Determine if Sending or Receivingã Way$ = "Sending": Sending = TRUE ' From Key PressedãELSEã Way$ = "Receiving": Sending = FALSEãEND IFãDOã ClrLn 9, 80: PRINT "File You Are "; Way$; ": ";ã F$ = "": LINE INPUT F$ã IF F$ = "" THEN GOTO ExitTransferã F$ = UCASE$(F$)ã IF Sending THENã IF LEN(SendDir$) THENã IF INSTR(F$, ":") = 0 THEN F$ = SendDir$ + "\" + F$ã END IFã IF FileExists(F$, 0) THEN Ok = TRUE ELSE J$ = Warn$("File Not Found")ã ELSEã IF LEN(ReceiveDir$) THENã IF INSTR(F$, ":") = 0 THEN F$ = ReceiveDir$ + "\" + F$ã END IFã IF FileExists(F$, 0) THENã ClrLn 9, 80ã PRINT F$; " Already Exists! Overwrite it? (Y/N)? ";ã DO: B$ = UCASE$(INKEY$)ã LOOP UNTIL LEN(B$) AND INSTR("YN", B$)ã IF B$ = "Y" THEN Ok = TRUEã ELSEã ErrCode = 0: F = FREEFILEã OPEN "O", F, F$ã IF ErrCode THEN J$ = Warn$("Bad Path/Filename?") ELSE Ok = TRUEã CLOSE Fã END IFã END IFãLOOP UNTIL OkããTxt1st = 1: TxtMax = 30 'And Draw a Box AroundãLOCATE 1, 1ãPRINT TAB(40); "Choose a Protocol"; TAB(80);ãTxt "T", ""ãTxt "C", " XModem "ãTxt "C", " XModem-1k (YModem) "ãTxt "C", " External Protocol "ãTxt "C", " Cancel "ãTxt "B", ""ãR = 1: C = 0ãDOã LOCATE R + 1, 2, 0ã VidBar TRUE, 2, 30ã DO: C$ = INKEY$: LOOP UNTIL LEN(C$)ã VidBar FALSE, 2, 30ã SELECT CASE C$ 'Based on Terminator:ã CASE Up$: R = R - 1: IF R < 1 THEN R = NumProtos ' Go to Line Aboveã CASE Down$: R = R + 1: IF R > NumProtos THEN R = 1 ' or Line Belowã CASE CR$: EXIT DOã CASE Escape$: EXIT DOã END SELECTãLOOPãIF C$ = Escape$ THEN GOTO ExitTransfer 'Cancelled by UserãVidBar TRUE, 2, 30ãLOCATE 9, 1: PRINT "+--+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+---+---+"ãLOCATE 1, 3: PRINT " Press to Cancel "ãLOCATE 1, 40: PRINT Way$; ": "; UCASE$(F$); TAB(80);ãIF Sending THENã LOCATE 10, 1: PRINT "0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%"ã SELECT CASE Rã CASE 1: SendXModem 128, F$ã CASE 2: SendXModem 1024, F$ã CASE 3: Ext$ = SendExternal$: GOSUB InsertFileName: SHELL Ext$ã CASE 4: GOTO ExitTransferã END SELECTãELSEã SELECT CASE Rã CASE 1: ReceiveXModem 128, F$ã CASE 2: ReceiveXModem 1024, F$ã CASE 3: Ext$ = RecvExternal$: GOSUB InsertFileName: SHELL Ext$ã CASE 4: GOTO ExitTransferã END SELECTãEND IFã'PLAY "T90 O3 L32 CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC" 'All Done Warning SoundããExitTransfer:ãCOLOR 7, 0 'Back to White on BlackãVIEW PRINT 1 TO 11: CLS 2: VIEW PRINT 'Clear Top 11 LinesãVIEW PRINT 1 TO 24: LOCATE 24, 1, 1ãEXIT SUBãã'----------------------------------------------------------------------------ããInsertFileName: 'Substitute FileName for ~ in Strings UsedãP = INSTR(Ext$, "~") ' to Call External Protocol (Send or Recv)ãIF P > 1 THENã Ext$ = LEFT$(Ext$, P - 1) + F$ + RIGHT$(Ext$, LEN(Ext$) - P)ãEND IFãRETURNããEND SUBããREM $STATICãSUB Txt (Side$, Text$) 'Put 1 Line of Text w/ Box DelimitersããIF LEN(Text$) > TxtMax THEN Text$ = LEFT$(Text$, TxtMax - 2)ãSpaceLeft = (TxtMax - LEN(Text$)) \ 2ãLOCATE , Txt1stãIF LEN(Text$) MOD 2 = 1 THEN Text$ = Text$ + " "ãIF Side$ = LCASE$(Side$) THEN Shadow$ = ""ãSELECT CASE UCASE$(Side$)ãCASE "T"ã Text$ = "+" + STRING$(TxtMax, "-") + "+" 'Top Borderã C = (TxtMax \ 2) - (LEN(T$) \ 2)ã MID$(Text$, C) = T$ãCASE "B"ã Text$ = "+" + STRING$(TxtMax, "-") + "+" 'Bottom Borderã C = (TxtMax \ 2) - (LEN(T$) \ 2)ã MID$(Text$, C) = T$ãCASE "C"ã Text$ = "|" + STRING$(SpaceLeft, " ") + Text$ + STRING$(SpaceLeft, " ") + "|"ãCASE "R"ã Text$ = "|" + STRING$(2 * SpaceLeft, " ") + Text$ + "|" 'Right-JustifyãCASE "L"ã Text$ = "|" + Text$ + STRING$(2 * SpaceLeft, " ") + "|" 'Left-JustifyãEND SELECTããPRINT Text$; Shadow$; 'Print Text, DeLimitsãIF CSRLIN < 24 THEN PRINT 'Go to Next LineãIF (Side$ = "B") AND LEN(Shadow$) THENã IF CSRLIN = 24 THEN LOCATE 25ã LOCATE , Txt1stã PRINT " "; STRING$(TxtMax + 1, Shadow$); Shadow$;ã Shadow$ = ""ãEND IFãEND SUBããSUB VidBar (BarOn, Col, Length)ãã113 LOCATE , Col 'Position at Paramter ColumnãIF BarOn THEN 'IF Hilighting (BarOn = True) thenã COLOR BGKolor, Kolor ' Use the BGKolor in the FGã FOR J = Col TO Col + Length - 1 'Across the Screen for the "Length"ã PRINT CHR$(SCREEN(CSRLIN, J)); ' Re-Print the Char That is Alreadyã NEXT J ' There in It's New ColorsãELSEã COLOR Kolor, BGKolor 'ELSE De-HiLiting So Return Colorsã FOR J = Col TO Col + Length - 1 ' to Normal and Re-Print each Charã PRINT CHR$(SCREEN(CSRLIN, J)); ' in the Row with the Regular Videoã NEXT JãEND IFãLOCATE , Col 'Return to 1st ColumnãCOLOR Kolor, BGKolor ' and Normal ColorsãEND SUBããFUNCTION Warn$ (Warning$)ãLOCATE 1, 40: COLOR 20ãPRINT " "; Warning$; TAB(80);ãCOLOR Kolor, BGKolorã'BEEP: BEEPãEND FUNCTIONããThe ABC Programmer ACCESSING COM 3/4 ACCESSING,COM3,COM4 05/02/95 (00:00) QB, QBasic, PDS 44 1296 COM3COM4.BAS'Port Addresses: COM1 -- 03F8hã' COM2 -- 02F8hã' COM3 -- 03E8hã' COM4 -- 02E8hãã'EXAMPLE: Accessing COM3ãã DEF SEG = 64 'move QuickBASIC segment pointer to BIOS data areaã POKE &H0, &HE8 'change com1: address in BIOS data area to com3:ã DEF SEG 'return to QB's DGROUPãã 'open com3: by issuing open "com1:" commandãã OPEN "COM1:9600,N,8,1" FOR OUTPUT AS #1ããã PRINT #1, "ATDT555-5555" 'print to comm portã ã CLOSE #1 'close comm portãã DEF SEG = 64 'point to BIOS data areaã POKE &H0, &HF8 'restore "com1:" address in BIOS data area to com1:ã DEF SEG 'return to DGROUPããã'EXAMPLE: Accessing COM4ãã DEF SEG = 64 'move QuickBASIC segment pointer to BIOS data areaã POKE &H2, &HE8 'change com2: address in BIOS data area to com4:ã DEF SEG 'return to DGROUPãã'open com4: by issuing open com2: commandãã OPEN "COM2:9600,N,8,1" FOR OUTPUT AS #1ããã PRINT #1, "ATDT555-5555" 'print to comm portãã CLOSE #1 'close comm portãã DEF SEG = 64 'point to BIOS data areaã POKE &H2, &HF8 'restore com2: address in BIOS data area to com2:ã DEF SEG 'return to DGROUPããJack Moffitt REFERENCE TO MODEM COMMUNICATIOREFERENCE,MODEM,COMMUNICATION Unknown Date (00:00) Text 421 19364 MODEM.REF Programmer's Reference to Modem Communicationsãã byãã Jack MoffittãããINTRODUCTIONã~~~~~~~~~~~~ã Direct UART programming is a subject that not many people areãfamiliar with. Since the advent of FOSSIL, many people advise that oneãshould use that for all communications, to make it more portable. Butãfor some instances, it is necessary to have internal modem routines toãgo on. Because no one seems to know or understand this subject, andãbecause I have found no other texts on the subject, I have decided toãput it all into one text, and maybe round off the edges on this subject.ãããTHE ASYNCRONOUS MODEMã~~~~~~~~~~~~~~~~~~~~~ã The asyncronous modem uses one (or more) specific ports on aãcomputer, as well as an IRQ (Interrupt Request). Every time a characterãof data is received in the device, an interrupt is processed. One mustãmake a interrupt service routine to handle this input, but where does itãgo? Since the IRQs are tied into interrupts, knowing the IRQ the deviceãis using, we can replace that interrupt. The port addresses and IRQãvectors are as follows:ããPort Addresses: COM1 -- 03F8h IRQ Vectors : 0 -- 08hã COM2 -- 02F8h 1 -- 09hã COM3 -- 03E8h 2 -- 0Ahã COM4 -- 02E8h 3 -- 0Bhã 4 -- 0Chã 5 -- 0DhãStandard Port IRQs: COM1 -- 4 6 -- 0Ehã COM2 -- 3 7 -- 0Fhã COM3 -- 4 8 -- 70hã COM4 -- 3 9 -- 71hã 10 -- 72hã 11 -- 73hã 12 -- 74hã 13 -- 75hã 14 -- 76hã 15 -- 77hããFor standard use, the IRQ for comm ports 1 and 3 is 4, and for 2 and 4ãit's 3. The 8250 UART has 10 registers available for getting, receivingãand interperating data. They are all located at offsets from the baseãaddress of the port. Here are the registers and their offsets:ããRegister Offsets: Transmitter Holding Register (THR) -- 00hã Receiver Data Register (RDR) -- 00hã Baud Rate Divisor Low Byte (BRDL) -- 00hã Baud Rate Divisor High Byte (BRDH) -- 01hã Interrupt Enable Register (IER) -- 01hã Interrupt Identification Register (IIR) -- 02hã Line Control Register (LCR) -- 03hã Modem Control Register (MCR) -- 04hã Line Status Register (LSR) -- 05hã Modem Status Register (MSR) -- 06hããWith this information one can address any register by adding the offsetãto the base address. Therefor, if one is using COM2 (base addressã02F8h) they would access the Modem Status Register with: port[$02F8 +ã$06].ãããTRANSMITTER HOLDING REGISTERã~~~~~~~~~~~~~~~~~~~~~~~~~~~~ã This register contains the data to be sent to the remote PC orãmodem. When bit 5 (THR empty) of the LSR is set, one can write to thisãport, thus sending data over the phone line or null modem cable.ãããRECEIVER DATA REGISTERã~~~~~~~~~~~~~~~~~~~~~~ã This register contains the incoming data. Read this registerãonly if bit 0 (Data Received) of the LSR is set, otherwise on will getãunpredictable characters.ãããBAUD RATE DIVISORã~~~~~~~~~~~~~~~~~ã The Baud Rate Divisor is used to set the BPS rate. To calculateãthe Baud Rate Divisor, one must use the formula: (UART ClockãSpeed)/(16*BPS). The UART Clock Speed is 1843200. To set the BRD oneãmust first set bit 7 (port toggle) of the Line Control Register to 1,ãand then write the low and high bytes to the correct offsets. Alwaysãremember to reset LCR bit 7 to 0 after one is finished setting the BPSãrate.ãããINTERRUPT ENABLE REGISTERã~~~~~~~~~~~~~~~~~~~~~~~~~ã The IER is used to simulate real interrupt calls. Write a byteãcontaining to interrupt information to enable any interrupts, allãinterrupts also have corresponding actions to clear the interrupts.ãHere's the list:ããInfo Byte:ããbit 7-6-5-4 3 2 1 0ã ~~~~~~~ ~ ~ ~ ~ã Always 0 MSR Change Data Error or Break THR empty Data ReceivedããTo Clear: Read MSR Read LSR Output to THR Read RDRãããINTERRUPT IDENTIFICATION REGISTERã~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ã This register is used to determine what kind of interrupts haveãoccured. Read one byte from this register, and use AND masks to findãout what has happened. The information in the byte is:ããInfo Byte:ããbit 7-6-5-4-3 2-1 0ã ~~~~~~~~~ ~~~ ~ã Unused 0-0 = Change in MSR If this bit is setã 0-1 = THR empty more than oneã 1-0 = Data Received interrupt hasã 1-1 = Data Error or Break occured.ãããLINE CONTROL REGISTERã~~~~~~~~~~~~~~~~~~~~~ã The Line Control Register (LCR) is used for changing the settingsãon the serial line. It is also used for initializing the modemãsettings. Write a byte to the port, containing the following info:ããLCR Byte.ã Port Toggle Break Condition Parity Stop Bits Data Bitsãbit 7 6 5-4-3 2 1-0ã ~ ~ ~~~~~ ~ ~~~ã 0 = Normal 0 = Off 0-0-0 = None 0 = 1 0-0 = 5ã 1 = Set BRD 1 = On 1-0-0 = Odd 1 = 2 0-1 = 6ã 1-1-0 = Even 1-0 = 7ã 1-0-1 = Mark 1-1 = 8ã 1-1-1 = SpaceããEverything is pretty clear except for the purpose of bits 6 and 7. Bitã6 controls the sending of the break signal. Bit 7 should always be 0,ãexcept if one is changing the baud rate. Then one must set it to one,ãwrite to the BRD and then set it back to zero. One can only write toãthe BRD if this bit is set.ãããMODEM STATUS REGISTERã~~~~~~~~~~~~~~~~~~~~~ã Just like the LSR returns the status of the RS232 line, the MSRãreturns the status of the modem. As with other registers, each bit inãthe byte one reads from this port contains a certain piece of info.ããMSR byte.ããbit 0 = Change in CTSã 1 = Change in DSRã 2 = Change in RIã 3 = Change in DCDã 4 = CTS onã 5 = DSR onã 6 = RI onã 7 = DCD onããCarrier Detect is achieved by testing bit 7, to see if the line isãringing test bit 6.ããããPUTTING IT ALL TOGETHERã~~~~~~~~~~~~~~~~~~~~~~~ã One can now use this information about the 8250 UART to startãprogramming their own modem routines. But before they can do that, theyãmust learn a little about interrupts and the 8259A PIC (ProgrammableãInterrupt Controller). This information is necessary to write modemãroutines that are not dependant on a slow BIOS.ãããINTERRUPTSã~~~~~~~~~~ã Interrupts are a broad subject, and this is not a reference forãthem. For for information on interrupts, one should look at DOSãProgrammer's Reference 4th Edition. Although there are two kinds ofãinterrupts - Non- Maskable and Maskable, maskable interrupts are theãonly ones that one should be concerned with. When an interruptãgenerates, the processor finishes the current command, and then saves aãfew variables (the address to return to) on the stack and jumps to theãvector of the interrupt. One can turn off maskable interrupts with theãSTI, and back on with CLI. One can not turn off non-maskableãinterrupts. Replacing interrupt routines in pascal is very easy.ãInclude the DOS unit in their program, and use the procedures GetIntVecãand SetIntVec. To replace the interrupt for COM2 (remember it's 0Bh)ãone would do this:ãã GetIntVec($0B, OldInt0Bh);ã SetIntVec($0B, NewInt0Bh);ããAt the end of the program, one MUST restore the interrupt using:ãã SetIntVec($0B, OldInt0Bh);ããFailing to do this will most likely result in a system crash after theãprogram terminates. Because another interrupt may be called insideãanother interrupt at any time, it is necessary to turn off interrupts,ãas mentioned above, every once in a while. Remember all this, andãprogramming for the modem will be much easier ( :) ).ããã8259 PROGRAMMABLE INTERRUPT CONTROLLERã~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ã The 8259A PIC is used by the processor as a gateway forãinterrupts. The 8259A decides which interrupts go first and whichãare currently active. The order interrupts are processed in inãthe order of their IRQ number. Thus, IRQ0 will always beãprocessed before IRQ1 if both are generated at the same time.ãSince asyncronous communication uses IRQs, we must instruct theã8259A PIC on when are interrupts should start interrupting, andãwhen they should stop. When initializing the modem, one mustã"turn on" the IRQ before one can start to use it. Turning backãoff is identical, but don't turn it off if one is writing doorãroutines! To do either requires one assign the value containedãat the port the value AND the mask. The masks for turning on andãoff the 8259A follows.ããTo Turn On:ã mask = (1 shl (IRQ number)) xor $00FFãTo Turn Off:ã mask = 1 shl (IRQ number)ããOne must also reset the PIC in the custom interrupt handler after one isãfinished with it. That will allow the PIC to process the nextãinterrupt.ããTo reset the PIC, write 20h to it. This is also refered to as the EndãOf Interrupt (EOI) signal. This must also be done after firstãinitializing the modem. There is another PIC on the 286, allowing theãlast 8 IRQs (7 - 15). The second PIC is called the cascade PIC. Theãaddresses for the PIC command and mask ports are listed next.ãã8259A PIC command address = 20hã8259A PIC mask address = 21hãCascade 8259A PIC command address = A0hãCascade 8259A PIC mask address = A1hããTo reset the PIC always write to the command, and for turning off withãthe masks always write to the mask. The masks for the cascade PIC areãthe same for the other PIC. So the mask for IRQ0 is equal to the maskãfor IRQ7. Also, one should write 20h to the cascade PIC as the EOIãsignal.ããããINPUT/OUTPUT CONTROLã~~~~~~~~~~~~~~~~~~~~ã To keep the text simple, only buffered input will be covered.ãBuffered output is a subject of more depth than one can provide in aãshort reference. Buffered input is relatively simple, but there are aãfew things one must consider. The size of the buffer is very import,ãmake the buffer to big and one will eat up the datasegment, make theãbuffer to small and one will get overruns. A good choice for a generalãbuffer would be in the range of 4 to 8k. This should allow plenty ofãroom for all incoming data. Another inportant factor is the type ofãbuffer. For simplicity and ease of use, a circular input buffer isãrecommended. A head and a tail point to the start and end of theãbuffer, and they will both wrap around when either go past the end ofãthe buffer, thus making the buffer a kind of circle. Getting data inãthe buffer is the primary job of the custom interrupt routine. Clearingãthe buffer and reading characters from the buffer is then as easy asãreading a character from an array, and advancing the head of the buffer.ãSending characters over the phone can be accomplished by waiting for theãflow control and then sending the character to the THR, repeating forãevery character.ããTHE INTERRUPT SERVICE ROUTINEã~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ã The ISR (Interrupt Service Routine) is the backbone forãasyncronous communication. The interrupt is called for everyãcharacter that comes through the modem. So in the interrupt oneãmust process these incoming characters or else they will be lost.ãSince the the interrupt got called, one must check the IIRã(Interrupt Identification Register) to see what actually cause theãinterrupt to be called. Since the interrupt is mainly dealingãwith handling the incoming data, and for reasons of simplicity,ãflow control will be ommited from the routine but will beãdiscussed later in this text. Since one is writing to the buffer,ãand since another character is likely to come in during this time,ãone must disable interrupts for the shortest time possible whileãwriting to the buffer, and then reenable them so no data is lost.ã(NOTE: If the ISR is to be contained in a unit, it must beãdeclared in the unit's interface section as an INTERRUPTãprocedure.) After disabling interrupts, checking for data,ãdiscarding data if no buffer space is available, putting the dataãin the buffer if there is room, and clearing the RDR if any dataãerror or break occured, one must turn on the interrupts and issueãthe EOI signal to the 8259A PIC or both the 8259A PIC and theãcascade PIC if IRQ7 - IRQ15 is used. Here is a sample rouãããconstã BaseAddr: array[1 .. 4] of word = ($03F8, $02F8, $03E8, $02E8);ã { Nice array to make finding the base address easy }ããvarã Buffer: array[1 .. 4096] of char; { A 4k buffer for input }ã Temp, { Varible to hold various modem statuses }ã CommPort: byte; { Comm Port in use }ã Head, { Start of the buffer }ã Tail, { End of the buffer }ã Size: word; { Size of the buffer }ã Cascade: boolean; { For IRQ7 - IRQ15 }ããprocedure Async_ISR; interrupt; { NOTE: must declare the procedureãinterrupt }ãbeginã inline($FB); { STI - Disable interrupts }ã Temp := port[BaseAddr[CommPort] + $02]; { Read a byte from the IIR }ã if Temp and $06 = $04 then { Character received }ã beginã if Head <> Tail then { Make sure there is room in the buffer }ã beginã Buffer[Tail] := Chr(port[BaseAddr[CommPort] + $00]); { Read char }ã inc(Tail); { Position the Tail for the next char }ã if Tail > 4096 then Tail := 0; { If Tail is greater, wrap the buffer }ã endã else temp := port[BaseAddr[CommPort] + $00]; { Throw away overruns }ã endã else if Temp and $06 = $06 then { Data error or break }ã Temp := port[BaseAddr[CommPort] + $00]; { Clear RDR }ã inline($FA); { CLI - Enable interrupts }ã port[$20] := $20; { Reset the 8259A PIC }ã if Cascade then port[$A0] := $20; { Reset the cascade PIC }ãend;ãããFirst the procedure disables interrupts, then it reads the IIR to findãout what kind of interrupt needs processing. The procedure then masksãout bits 2 and 1 and tests it to see if bit 4 is set. If data isãreceived it checks to make sure there is room in the buffer, and placesãthe character at the position marked by Tail, otherwise it disregardsãthe character as overrun. If a data error occured it clears the RDR toãmake sure no garbage is received. Finally it enables interrupts andãresets the 8259A (and the cascade if necessary).ããSENDING CHARACTERSã~~~~~~~~~~~~~~~~~~ã Sending character over the modem is much simpler than gettingãthem. First one must wait for the flow control and for the UART and thenãwrite the character to the THR. Here's an example:ããprocedure XmitChar(C: char); { Uses variable and constant declarations fromãbegin the previous example }ã while ((port[BaseAddr[CommPort] + $05] and $20 <> $20) and { Wait for THR }ã (port[BaseAddr[CommPort] + $06] and $10 <> $10)) { Wait for CTS }ã do ; { Do nothing until CTS and THR empty }ã port[BaseAddr[CommPort] + $00] := Ord(C); { Send character }ãend;ããThis waits for the CTS signal and for the THR to be clear and then sendsãthe character. To send strings just use this in a repeat loop such as:ããfor x := 1 to length(s) doã XmitChar(s[x]);ãããREADING CHARACTERSã~~~~~~~~~~~~~~~~~~ã The actual reading of character takes place in the ISR, but oneãstill has to get them from the buffer. Just read the character atãthe head of the buffer and pass it back. An example:ããfunction RemoteReadKey: char; { Uses var and const from above }ãbeginã RemoteReadKey := Buffer[Head]; { Get the character }ã inc(Head); { Move Head to the next character }ã if Head > 4096 then Head := 0; { Wrap Head around if necessary }ã dec(Size); { Remove the character }ãend;ããTo find out if a character is waiting is even easier:ããfunction RemoteKeyPressed: boolean; { Uses vars and consts from above }ãbeginã RemoteKeyPressed := Size > 0; { A key was pressed if there is dataãinãend; the buffer }ãããINITIALIZING MODEM PARAMETERS AND OTHER TOPICSã~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ã For most cases one can use interrupt 14h function 00h toãinitialize modem parameters, but if the baud rate is over 9600, thisãfunction will not work. One must change the BRD themselves. It is aãsimple matter of accessing the BRD by setting the LCR bit 7 to 1 andãwriting to the BRD and then reseting the LCR bit 7 back to 0.ãEverything else, clearing buffers, flushing buffers, formatting input,ãis all up to the programmer. I have provided one with enoughãinformation to grasp the basis of modem programming and the I/Oãinvolved.ããFLOW CONTROLã~~~~~~~~~~~~ã Flow control is mainly used to prevent overflow error on today'sãhigh speed modems. CTS/RTS was already covered earlier, but nothing hasãbeen said for XOn/XOff. XOn/XOff will send a certain character (usuallyãa ^S) when the input buffer has reached a certain percentage ofãcapacity. This signal is XOff. When the buffer has gone down to anotherãpercentage of capacity, XOn (usually a ^Q) will be sent. It is theãprogrammer's job to look for XOn/XOff codes and interperate them, asãthere are no standard ways to do it as with CTS/RTS. It is also his jobãto make sure he or she sends the signals at the appropriate time.ããCONCLUSIONã~~~~~~~~~~ã This text is general, and won't satisfy the needs of advancedãmodem programmers. It was written to help those just starting, orãthinking about starting, through the ordeal of finding a book, or readãthrough source not knowing what some of it does. If one finds anyãmistakes, please feel free to contact me via the Pascal FIDONet echo,ãand he will gladly correct them. Also, if one would like moreãinformation on other related topics, contact me via the Pascal echo, andãI will try to help.ãDonn Bly BEYOND 19200 BEYOND,19200 Unknown Date (00:00) QB, QBasic, PDS 30 982 HIGHBAUD.BASDECLARE SUB BaudLatch ()ã'Use the straight OPEN COM statement for 19200. To go higher you canã'use this code (originally from Donn Bly):ããBaudLatchããSUB BaudLatch 'enables 38400 baud want to put in com3 and com4 supportã'NewBaud$ = "38400"ã'BaudNum% = 3 'for 38.4ã'BaudNum% = 2 'for 56000ãBaudNum% = 1 'for 115KãPort$ = "COM4:"ã ãSELECT CASE Port$ã CASE "COM1:"ã BaseAddress% = &H3F8ã CASE "COM2:"ã BaseAddress% = &H2F8ã CASE "COM3:"ã BaseAddress% = &H3E8ã CASE "COM4:"ã BaseAddress% = &H2E8ãEND SELECTã OldLSR% = INP(BaseAddress% + 3)ã OUT (BaseAddress% + 3), (OldLSR% OR &H80) ' Enable the Divisor Latchã OUT (BaseAddress% + 0), (BaudNum% MOD &HFF) ' Lo Byte of Baud Rateã OUT (BaseAddress% + 1), (BaudNum% \ &H100) ' Hi Byte of baud Rateã OUT (BaseAddress% + 3), OldLSR% ' Disable Divisor LatchãEND SUBããRobert Benson DTR PATCH FOR QB DTR,PATCH,FOR,QB 01/17/91 (21:32) TEXT 156 2407 DTRPATCH.TXTTo the end that it is an ongoing struggle to get Microsoft to listenãto the needs of the programmer, the following patches are providedãto enable you to patch your copies of BRUN45.EXE and BCOM45.LIB.ããBefore beginning, make sure you have backup copies of BRUN45.EXEãand BCOM45.LIB.ããBCOM45.LIB DTR Patchã--------------------ããWith Debug in a DOS path, type :ãã debug bcom45.libããType :ãã s cs:0 ffff b0 00 e3 01ããDebug should show :ãã xxxx:1529ãã where xxxx can be any number depending upon where Debug loaded theã program into memory. In any case, the number is not important.ããType :ãã u 1529ããDebug should show :ãã MOV AL,00ã JCXZ 152Eã INC AXã ADD DX,+04ã OUT DX,ALããThis is where QB graciously resets the comm port to parameters it thinksãthe comm port should have.ããTo fix the problem, Type :ãã a 1529ãã mov al,01ã [Enter]ãã a 152dãã nopã [Enter]ãã where [Enter] is the Enter key (do not type the characters)!ãããTo verify that you typed everything correctly, Typeãã u 1529ããDebug should show :ãã MOV AL,01ã JCXZ 152Eã NOPã ADD DX,+04ã OUT DX,ALãããTo save the corrections Type :ãã wããDebug should show :ãã Writing 35EF7 bytesãããNow type Q and you are finished patching BCOM45.LIBããããBRUN45.EXE DTR Patchã--------------------ããFirst, rename BRUN45.EXE to BRUN45.XããWith Debug in a DOS path, type :ãã debug BRUN45.XããType :ãã s cs:0 ffff b0 00 e3 01ããDebug should show :ãã xxxx:9E78ãã where xxxx can be any number depending upon where Debug loaded theã program into memory. In any case, the number is not important.ããType :ãã u 9e78ããDebug should show :ãã MOV AL,00ã JCXZ 9E7Dã INC AXã ADD DX,+04ã OUT DX,ALããThis is where QB graciously resets the comm port to parameters it thinksãthe comm port should have.ããTo fix the problem, Type :ãã a 9e78ãã mov al,01ã [Enter]ãã a 9e7cãã nopã [Enter]ãã where [Enter] is the Enter key (do not type the characters)!ãããTo verify that you typed everything correctly, Typeãã u 9e78ããDebug should show :ãã MOV AL,01ã JCXZ 9E7Dã NOPã ADD DX,+04ã OUT DX,ALãããTo save the corrections Type :ãã wããDebug should show :ãã Writing 12E80 bytesãããNow type Q and you are finished patching BRUN45.XããRename BRUN45.X back to BRUN45.EXEãCoridon Henshaw ACCESSING FOSSIL IN BASIC QuickBASIC ScrapBook 02-14-93 (21:39) QB, PDS 146 3225 FOSSIL.BAS DECLARE FUNCTION FossInit% (Port%)ãDECLARE FUNCTION BlockRead$ (Port%)ãDECLARE FUNCTION BlockWrite% (Port%, Buffer$)ãDEFINT A-Zã ã'$INCLUDE: 'QB.BI' or use QBX.BI for PDSããDIM SHARED Regs AS RegTypeXããFUNCTION BlockRead$ (Port)ãBuffer$ = STRING$(32766, 0) 'Max 32766 bytes to readãRegs.cx = LEN(Buffer$)ãRegs.dx = PortãRegs.es = VARSEG(Buffer$) ' Change to SSEG for PDSãRegs.di = SADD(Buffer$)ãCALL INTERRUPTX(&H14, Regs, Regs)ãBlockRead$ = LEFT$(Buffer$, Regs.ax)ãEND FUNCTIONããFUNCTION BlockWrite (Port, Buffer$)ãRegs.cx = LEN(Buffer$)ãRegs.dx = PortãRegs.es = VARSEG(Buffer$) ' Change to SSEG for PDSãRegs.di = SADD(Buffer$)ãCALL INTERRUPTX(&H14, Regs, Regs)ãBlockWrite = Regs.ax 'Number of chars transferedãEND FUNCTIONããSUB FossDeInit (Port)ã' Release the FOSSIL device driverãRegs.ax = &H500ãRegs.dx = PortãINTERRUPTX &H14, Regs, RegsãEND SUBããFUNCTION FossInit (Port)ã ã' Initialize the FOSSIL device driverã'ã' dx = Communications port number (0-3)ã' ah = &H04 Fossil Function Number - Initialize FOSSIL driverã' (Raises DTR in the porcess)ã ãRegs.dx = PortãRegs.ax = &H400ãCALL INTERRUPTX(&H14, Regs, Regs)ã ãIF Regs.ax <> &H1954 THENã FossInit = False 'Fossil Not FoundãEND IFã ãFossInit = Trueã ãEND FUNCTIONããSUB SetDtr (Port, DtrStatus)ãRegs.dx = Port 'Set carrier detect low or highãSELECT CASE DtrStatusã CASE 0ã Regs.ax = &H600ã CASE 1ã Regs.ax = &H601ã CASE ELSEã Regs.ax = &H600ã BEEPãEND SELECTãINTERRUPTX &H14, Regs, RegsãEND SUBããSUB SetFlowControl (Port, Control)ãRegs.dx = PortãSELECT CASE Controlã CASE 1 'Xon/Xoff on transmitã Regs.ax = &H601ã CASE 2 'CTS/RTSã Regs.ax = &H602ã CASE 3 'Xon/Xoff on recieveã Regs.ax = &H608ãEND SELECTãCALL INTERRUPTX(&H14, Regs, Regs)ãEND SUBããSUB SetPortParams (Port, Bps AS LONG, Bits, Stops, Parity$)ãRegs.dx = PortãRegs.ax = 0ãSELECT CASE Bpsã CASE 300ã Regs.ax = (Regs.ax OR &H40)ã CASE 600ã Regs.ax = (Regs.ax OR &H60)ã CASE 1200ã Regs.ax = (Regs.ax OR &H80)ã CASE 2400ã Regs.ax = (Regs.ax OR &HA0)ã CASE 4800ã Regs.ax = (Regs.ax OR &HC0)ã CASE 9600ã Regs.ax = (Regs.ax OR &HE0)ã CASE 19200ã Regs.ax = (Regs.ax OR &H0)ã CASE 38400ã Regs.ax = (Regs.ax OR &H20)ã CASE ELSEã Regs.ax = (Regs.ax OR &HA0)ã 'Default to 2400 baudãEND SELECTã ãSELECT CASE Bitsã CASE 5ã Regs.ax = (Regs.ax OR &H0)ã CASE 6ã Regs.ax = (Regs.ax OR &H1)ã CASE 7ã Regs.ax = (Regs.ax OR &H2)ã CASE 8ã Regs.ax = (Regs.ax OR &H3)ã CASE ELSEã Regs.ax = (Regs.ax OR &H3)ã 'Default to 8 bitsãEND SELECTã ãSELECT CASE Stopsã CASE 1ã Regs.ax = (Regs.ax OR &H0)ã CASE 2ã Regs.ax = (Regs.ax OR &H4)ã CASE ELSEã Regs.ax = (Regs.ax OR &H0)ã 'Default to 1 stop bitãEND SELECTã ãSELECT CASE UCASE$(Parity$)ã CASE "N"ã Regs.ax = (Regs.ax OR &H0)ã CASE "O"ã Regs.ax = (Regs.ax OR &H8)ã CASE "E"ã Regs.ax = (Regs.ax OR &H18)ã CASE ELSEã Regs.ax = (Regs.ax OR &H0)ã ' Default to no parityãEND SELECTãRegs.dx = PortãINTERRUPTX &H14, Regs, RegsãEND SUBããUnknown Author(s) DETECTING CARRIER FidoNet QUIK_BAS Echo Unknown Date QB, QBasic, PDS 18 763 DETCARR.BAS '>Looking for and example of code to monitor carrier detect. Would like toã'>be able to have a local programer using Thorobred add carrier detect toã'>his program but he has never seen any code as to what to do. I know thereã'>has to be someone in the Quick Basic world that can do this and hopefullyã'>we can transfer this to another basic program. Any help appreciated.ã ã ã DEFINT A-Zã FUNCTION Carrier(Port) ' returns false (0) if no carrierã Select Case Portã CASE 1: BaseAddress = &H3F8ã case 2: BaseAddress = &H2F8ã CASE 3: BaseAddress = &H3E8ã CASE 4: BaseAddress = &H2E8ã CASE ELSE: BaseAddress = Portã 'For Those PS/2 types out there or Weird onesã End Selectã Carrier = (INP(BaseAddress + 6) AND &h80) > 0ãJames Vahn ALARM ON CONNECTION FidoNet QUIK_BAS Echo 10-18-92 (10:18) QB, QBasic, PDS 109 2703 CONNECT.BAS '> Does anyone have code that allows you to dial a number throughã'> the modem, and allow the user to pick up the phone when itã'> connects (and things to watch for, like how do you know whenã'> it's safe to pick up the phone)?ããã' This routine sends an alarm when a connection is made.ããã'modem.bas is an ASCII terminal to demo an autodialer. James VahnãDECLARE SUB Keyscan ()ãDECLARE SUB Delay (td!)ãDECLARE SUB Dial (num$)ãã' Put all modem response into a 10k buffer declared global.ãCOMMON SHARED ModemIn$ããON ERROR GOTO HandlerãON COM(2) GOSUB GetBufãCOM(2) ONããCALL Dial ("555-1212")ããDOã CALL Keyscan ' You're online now. Stay in this loop forever.ãLOOPããHandler:ãRESUME NEXTããGetBuf:ãInStr$ = INPUT$(LOC(1), #1)ãã ' swap a backspace char for a left cursor.ã DOã BackSpace = INSTR(InStr$, CHR$(8))ã IF BackSpace THENã MID$(InStr$, BackSpace) = CHR$(29)ã END IFã LOOP WHILE BackSpaceãã ' eliminate line feeds.ã DOã LineFeed = INSTR(InStr$, CHR$(10))ã IF LineFeed THENã InStr$ = LEFT$(InStr$, LineFeed - 1) + MID$(InStr$, LineFeed + 1)ã END IFã LOOP WHILE LineFeedãã ModemIn$ = RIGHT$(ModemIn$ + InStr$, 10240)ã PRINT (InStr$); 'print modem buffer to screen.ãRETURNããSUB Delay (td!)ã TimeDelay! = (TIMER + td!) mod 86400ã WHILE TimeDelay! > TIMER: WENDãEND SUBããSUB Dial (num$)ããOPEN "COM2:2400,N,8,1" FOR RANDOM AS #1ããCLSãLOCATE 25, 40: PRINT "ALT-X to exit.."ãLOCATE 1, 1, 1ã PRINT #1, "ATZ"ã CALL Delay(1.25)ã PRINT #1, "ATS7=45 S0=0 V1 M0" ' modem initialization stringã CALL Delay(1.25)ããDOã CALL Delay(1)ã PRINT "Dialing ....."ã PRINT #1, "atdt" + Num$ + CHR$(13)ãã TimeDelay! = TIMER + 40ãã DO UNTIL TIMER > TimeDelay!ã CALL Keyscanã test = INSTR(RIGHT$(ModemIn$, 20), "CONNECT")ã IF test THEN result = -1: EXIT DOã test = INSTR(RIGHT$(ModemIn$, 5), "BUSY")ã IF test THEN result = 0: EXIT DOã test = INSTR(RIGHT$(ModemIn$, 12), "NO DIALTONE")ã IF test THEN result = 0: CALL Delay(2): EXIT DOã test = INSTR(RIGHT$(ModemIn$, 11), "NO CARRIER")ã IF test THEN result = 0: CALL Delay(2): EXIT DOãã LOOPããLOOP UNTIL resultããFOR t = 1 TO 5 ' It answered! ring the alarm!ã SOUND 750, 2ã SOUND 550, 2ã SOUND 650, 2ã IF INKEY$ <> "" THEN EXIT FORãNEXTããEND SUBããSUB Keyscanã' This would be a good place to check for PgDn/PgUp and shell to anã' external transfer protocol like Zmodem.ããa$ = INKEY$ã IF a$ = CHR$(0) + CHR$(45) THEN CLOSE : END ' ALT-X to exit.ã PRINT #1, a$; ' send keypress to modemãEND SUBãDavid Colston BBS DICE DOOR GAME FidoNet QUIK_BAS Echo Year of 1993 QB, PDS 452 11136 DOORGAME.BAS'A local sysop wanted a door to roll dice for a dungeons and dragonsã'game. I thought you might like to see it. Some of the code might lookã'familar. Not all of the fossil routines are used, but are offeredã'for completeness.ããDECLARE SUB Delay (X!)ãDECLARE SUB CheckPortStatus (Port%, Info%, Reg AS ANY)ãDECLARE SUB FossInit (Port%, Present%, Reg AS ANY)ãDECLARE SUB GetChar (Port%, Good%, InBound$, Present%, Reg AS ANY)ãDECLARE SUB PrintCon (A$, Reg AS ANY)ãDECLARE SUB SendChar (Port%, Sent%, Present%, Outbound$, Reg AS ANY)ã' $INCLUDE: 'QBX.BI'ã' Include Data Types for INãDEFINT A-Zã'$STATICãDIM Reg AS RegType ' Used for INTERRUPT callsãA# = TIMER + 120 'Allow only two minute in this doorã 'This saves us from constantly monitoringã 'carrier detect.ãON TIMER(A#) GOSUB QuitãON KEY(10) GOSUB Quit'Allow local bail out by sysopãTIMER ONãKEY(10) ONãPort = VAL(LTRIM$(RTRIM$(COMMAND$)))' Port =0 is port 1, etc.ãStart:ãDIM Rolls(1000)ãFossInit Port, Present, Reg 'Find out if fossil is present orã 'if we're just looking on a PC.ãBits = 8 'Defaults for almost all boards!ãStops = 1ãParity$ = "N"ãSendChar Port, Sent, Present, CHR$(12), Reg 'Just in case theyã ã'haveãX$ = CHR$(27) + "[2J Dice Door 1.0 By David Colston (c) 1993"ãX$ = X$ + CHR$(13) + CHR$(10)ã'Send ansii clear screen and return; line feedã ãX$ = X$ + " Enter your character name:"ãFOR I = 1 TO LEN(X$)ã SendChar Port, Sent, Present, MID$(X$, I, 1), Regã PrintCon MID$(X$, I, 1), Reg'Echo to board consol.ãNEXTãDOã GetChar Port, Good, InBound$, Present, Regã IF Good THENã IF InBound$ <> CHR$(13) THEN User$ = User$ + InBound$ã SendChar Port, Sent, Present, InBound$, Regã PrintCon InBound$, Regã END IFãLOOP UNTIL InBound$ = CHR$(13)ãDiceSides:ãX$ = CHR$(13) + CHR$(10) + " Enter Number of Dice Sides:"ãFOR I = 1 TO LEN(X$)ã SendChar Port, Sent, Present, MID$(X$, I, 1), Regã PrintCon MID$(X$, I, 1), RegãNEXTãSides$ = ""ãDOã GetChar Port, Good, InBound$, Present, Regã IF Good THENã IF INSTR(1, "1234567890", InBound$) > 0 THENã Sides$ = Sides$ + InBound$ã SendChar Port, Sent, Present, InBound$, Regã END IFã PrintCon InBound$, Regã END IFãLOOP UNTIL InBound$ = CHR$(13)ãIF VAL(Sides$) < 2 OR VAL(Sides$) > 100 THEN GOTO DiceSidesãDice:ãX$ = CHR$(13) + CHR$(10) + " Enter Number of Dice :"ãFOR I = 1 TO LEN(X$)ã SendChar Port, Sent, Present, MID$(X$, I, 1), Regã PrintCon MID$(X$, I, 1), RegãNEXTãDice$ = ""ãDOã GetChar Port, Good, InBound$, Present, Regã IF Good THENã IF INSTR(1, "1234567890", InBound$) > 0 THENã Dice$ = Dice$ + InBound$ã SendChar Port, Sent, Present, InBound$, Regã END IFã PrintCon InBound$, Regã END IFãLOOP UNTIL InBound$ = CHR$(13)ãIF VAL(Dice$) < 2 OR VAL(Dice$) > 100 THEN GOTO DiceãGrey = FREEFILEãOPEN "Greyhawk.rol" FOR APPEND AS Grey' Output for game bulletinãPRINT #Grey, "On "; DATE$; " "; User$; " had the following roll."ãPRINT #Grey, "# Dice = "; Dice$; " # Sides = "; Sides$ãRANDOMIZE TIMERãTotalRoll = 0ãFOR I = 1 TO VAL(Dice$)ã Roll = INT(RND(1) * VAL(Sides$)) + 1ã X$ = CHR$(13) + CHR$(10) + " Die" + STR$(I) + " Showed" + STR$(Roll)ã TotalRoll = TotalRoll + Rollã FOR J = 1 TO LEN(X$)ã SendChar Port, Sent, Present, MID$(X$, J, 1), Regã PrintCon MID$(X$, J, 1), Regã NEXTã PRINT #Grey, RIGHT$(X$, LEN(X$) - 2)ãNEXTãX$ = CHR$(13) + CHR$(10) + " Total Rolled Was" + STR$(TotalRoll)ãPRINT #Grey, RIGHT$(X$, LEN(X$) - 2)ãPRINT #Grey, SPACE$(10)ãFOR J = 1 TO LEN(X$)ã SendChar Port, Sent, Present, MID$(X$, J, 1), Regã PrintCon MID$(X$, J, 1), RegãNEXTãSendChar Port, Sent, Present, CHR$(13), RegãX$ = CHR$(13) + CHR$(10) + " Press any key."ãFOR J = 1 TO LEN(X$)ã SendChar Port, Sent, Present, MID$(X$, J, 1), Regã PrintCon MID$(X$, J, 1), RegãNEXTãDOã GetChar Port, Good, InBound$, Present, Regã IF Good THEN PrintCon InBound$, RegãLOOP UNTIL GoodããQuit:ãENDã ã'This door in not error trapped one of you guys might do better!ããSUB CheckPortStatus (Port, Info, Reg AS RegType)ã ã' ah = &H03 Fossil Function Number - Statusã' al = &H00 Place Holderã' dx = Communications port number (0-3)ãReg.dx = PortãReg.ax = &H300ãINTERRUPT &H14, Reg, Regã ãIF (Reg.ax AND &H80) <> 0 THEN Info = (Info OR &H1)ã' carrier detect present ?ãIF (Reg.ax AND &H100) <> 0 THEN Info = (Info OR &H2)ã' buffer has data?ãIF (Reg.ax AND &H200) <> 0 THEN Info = (Info OR &H4)ã' Was buffer overun?ãIF (Reg.ax AND &H4000) = 0 THEN Info = (Info OR &H8)ã' output buffer data ?ãIF (Reg.ax AND &H2000) = 0 THEN Info = (Info OR &H10)ã' Is output buffer overrun?ãEND SUBããSUB CtrlBreak (Port, Present)ãSELECT CASE Portã CASE 0ã address = &H3F8ã CASE 1ã address = &H2F8ã CASE 2ã address = &H3E8ã CASE ELSEã address = &H2E8ãEND SELECTãOld1 = INP(address + 1)ãOUT address + 1, 0ãOld2 = INP(address + 3)ãSetLow = Old2 OR &H40ãA# = TIMERãOUT address + 3, SetLowãDelay .5ãOUT address + 3, Old2 'Set it back the way it was!ãOUT address + 1, Old1ãEND SUBããDEFSNG A-ZãSUB Delay (X!) STATICãCheckTime! = TIMERãWHILE TIMER < CheckTime! + X!ãWENDãEND SUBããDEFINT A-ZãSUB ErrorMessage (A$, X) STATICãA$ = ""ãSELECT CASE Xã ã CASE 3ã A$ = "Return with out GOSUB."ã CASE 4ã A$ = "Out of Data."ã CASE 5ã A$ = "Illegal Function Call."ã CASE 6ã A$ = "Math Overflow."ã CASE 7ã A$ = "Out of Memory."ã CASE 9ã A$ = "Subscript out of range."ã CASE 11ã A$ = "Division by Zero."ã CASE 14ã A$ = "Out of String Space."ã CASE 16ã A$ = "String Formula Too Complex."ã CASE 19ã A$ = "No RESUME."ã CASE 20ã A$ = "RESUME without error."ã CASE 24ã A$ = "Device TimeOut."ã CASE 25ã A$ = "Device Fault."ã CASE 27ã A$ = "Out of Paper."ã CASE 39ã A$ = "Case Else Expected."ã CASE 40ã A$ = "Variable Required."ã CASE 50ã A$ = "Field OverFlow."ã CASE 51ã A$ = "Internal Error."ã CASE 52ã A$ = "Bad File Name or Number."ã CASE 53ã A$ = "File Not Found."ã CASE 54ã A$ = "Bad File Mode."ã CASE 55ã A$ = "File Already Open."ã CASE 56ã A$ = "Field Statement Active."ã CASE 57ã A$ = "Device I/O Error."ã CASE 58ã A$ = "File Already exists."ã CASE 59ã A$ = "Bad Record Length."ã CASE 61ã A$ = "Disk Full."ã CASE 62ã A$ = "Input past end of file."ã CASE 63ã A$ = "Bad Record Number."ã CASE 64ã A$ = "Bad File Name."ã CASE 67ã A$ = "Too many files."ã CASE 68ã A$ = "Device Unavailable."ã CASE 69ã A$ = "Communications Buffer OverFlow."ã CASE 70ã A$ = "Access Denied."ã CASE 71ã A$ = "Disk or Drive Not Ready."ã CASE 72ã A$ = "Disk Media Error. (Bad Disk!)"ã CASE 75ã A$ = "Path/File access error."ã CASE 76ã A$ = "Path not Found."ã CASE ELSEã A$ = "Unknown Error #" + STR$(X)ã ãEND SELECTã ãEND SUBããSUB FossDeinit (Port, Reg AS RegType)ã' Release the FOSSIL device driverãReg.ax = &H500ãReg.dx = PortãINTERRUPT &H14, Reg, RegãEND SUBããSUB FossInit (Port, Present, Reg AS RegType)ãPresent = -1ã ã' Initialize the FOSSIL device driverã'ã' dx = Communications port number (0-3)ã' ah = &H04 Fossil Function Number - Initialize FOSSIL driverã' (Raises DTR in the porcess)ã ãReg.dx = PortãReg.ax = &H400ãINTERRUPT &H14, Reg, RegãIF Reg.ax <> &H1954 THENã Present = 0 'Fossil Not FoundãEND IFã ãEND SUBããSUB GetChar (Port, Good, InBound$, Present, Reg AS RegType)ãCheckPortStatus Port, Info, Reg ' Test for space in OUTPUT bufferãIF NOT Present THENã InBound$ = INKEY$ã IF InBound$ > "" THENã Good = -1ã ELSEã Good = 0ã END IFã EXIT SUBãEND IFãIF (Info AND &H4) = 0 THENã IF (Info AND &H2) = &H2 THENã Reg.ax = &H200ã Reg.dx = Portã INTERRUPT &H14, Reg, Regã InBound$ = CHR$(Reg.ax)ã Good = -1ã ELSEã Good = 0' No Characters in input bufferã InBound$ = INKEY$ã IF InBound$ > "" THEN Good = -1ã END IFãELSE ' Input buffer over-runã Good = 0ã Reg.ax = &HA00ã Reg.dx = Portã INTERRUPT &H14, Reg, Regã BEEPãEND IFãEND SUBããSUB PrintCon (A$, Reg AS RegType) STATICãIF A$ = "" THEN EXIT SUBã Reg.ax = &H600ã Reg.dx = ASC(A$)ã INTERRUPT &H21, Reg, Regã IF A$ = CHR$(13) THENã Reg.ax = &H600ã Reg.dx = 10ã INTERRUPT &H21, Reg, Regã END IFãEND SUBããSUB SendChar (Port, Sent, Present, Outbound$, Reg AS RegType)ãA! = TIMERãIF NOT Present THENã Sent = 0ã EXIT SUBãEND IFãDOã CheckPortStatus Port, Info, Reg ' room in buffer ?ã IF (Reg.ax AND &H80) = 0 THENã Sent = -1ã EXIT DOã END IFã IF (Info AND &H10) = 0 THENã Reg.dx = Portã Reg.ax = &H100 + ASC(Outbound$)ã INTERRUPT &H14, Reg, Regã Sent = -1ã END IFãLOOP WHILE NOT Sent AND TIMER - A! < 2ãIF Sent = 0 AND Reg.ax AND &H80 <> 0 THENã Sent = 0 ' Output buffer fullã Reg.ax = &H900ã Reg.dx = Portã INTERRUPT &H14, Reg, RegãEND IFãEND SUBããSUB SetDtr (Port, DtrStatus$, Reg AS RegType)ãReg.dx = Port 'Set carrier detect low or highãSELECT CASE UCASE$(DtrStatus$)ã CASE "L"ã Reg.ax = &H600ã CASE "H"ã Reg.ax = &H601ã CASE ELSEã Reg.ax = &H600ã BEEPãEND SELECTãINTERRUPT &H14, Reg, RegãEND SUBããSUB SetHandShake (Port, HandShake, Reg AS RegType)ãReg.dx = PortãIF HandShake > &HF THENã HandShake = &H2ã 'Set handshake to RTS/CTS.ã BEEPãEND IFãReg.ax = &HF00 + HandShakeãINTERRUPT &H14, Reg, RegãReg.ax = &H1000ãReg.dx = PortãINTERRUPT &H14, Reg, RegãEND SUBããSUB SetPortParams (Port, Baud$, Bits, Stops, Parity$, Reg AS RegType)ãReg.dx = PortãReg.ax = 0ãSELECT CASE Baud$ã CASE "300"ã Reg.ax = (Reg.ax OR &H40)ã CASE "600"ã Reg.ax = (Reg.ax OR &H60)ã CASE "1200"ã Reg.ax = (Reg.ax OR &H80)ã CASE "2400"ã Reg.ax = (Reg.ax OR &HA0)ã CASE "4800"ã Reg.ax = (Reg.ax OR &HC0)ã CASE "9600"ã Reg.ax = (Reg.ax OR &HE0)ã CASE "19200"ã Reg.ax = (Reg.ax OR &H0)ã CASE "38400"ã Reg.ax = (Reg.ax OR &H20)ã CASE ELSEã Reg.ax = (Reg.ax OR &HA0)ã 'Default to 2400 baudãEND SELECTã ãSELECT CASE Bitsã CASE 5ã Reg.ax = (Reg.ax OR &H0)ã CASE 6ã Reg.ax = (Reg.ax OR &H1)ã CASE 7ã Reg.ax = (Reg.ax OR &H2)ã CASE 8ã Reg.ax = (Reg.ax OR &H3)ã CASE ELSEã Reg.ax = (Reg.ax OR &H3)ã 'Default to 8 bitsãEND SELECTã ãSELECT CASE Stopsã CASE 1ã Reg.ax = (Reg.ax OR &H0)ã CASE 2ã Reg.ax = (Reg.ax OR &H4)ã CASE ELSEã Reg.ax = (Reg.ax OR &H0)ã 'Default to 1 stop bitãEND SELECTããSELECT CASE UCASE$(Parity$)ã CASE "N"ã Reg.ax = (Reg.ax OR &H0)ã CASE "O"ã Reg.ax = (Reg.ax OR &H8)ã CASE "E"ã Reg.ax = (Reg.ax OR &H18)ã CASE ELSEã Reg.ax = (Reg.ax OR &H0)ã ' Default to no parityãEND SELECTãReg.dx = PortãINTERRUPT &H14, Reg, Reg 'Set it up!ãEND SUBããBob Perkins QB FOSSIL ROUTINES FidoNet QUIK_BAS Echo 10-24-95 (21:28) QB, PDS 348 11206 QBFOSSIL.BAS ' -=-=-=-=-=- Data for initfossil() -=-=-=-=-=-=-ã '[initialize fossil driver]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'DTR is raisedã 'returns 0 for successful, -1 for failureã 'ã ' -=-=-=-=-=- Data for inituart() -=-=-=-=-=-=-ã '[initialize uart]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'valid baud rates are 38400, 19200, 9600, 4800, 2400, 1200, 600, 300ã 'parity% : 0=none 8=odd 24=evenã 'stop% : 0=1bit 4=2bitsã 'wordlen%: 0=5bits 1=6bits 2=7bits 3=8bitsã 'returns rs-232 status code bits in ahã 'bit0=RDA (input data available in buffer)ã 'bit1=OVRN (data has been lost)ã 'bit5=THRE (room available in output buffer)ã 'bit6=TSRE (output buffer empty)ã 'returns modem status bits in alã 'bit3 = always setã 'bit7 = carrier detectã 'ã ' -=-=-=-=-=- Data for deinitfossil() -=-=-=-=-=-=-ã '[deinitialize fossil driver]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'state of DTR is not affected, use setDTR() first to set desired state.ã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for setDTR() -=-=-=-=-=-=-ã '[set state of DTR]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'state% = 0 to lower, 1 to raiseã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for waitreceive -=-=-=-=-=-=-ã '[get character from port with wait]ã 'NOTE: Will not return until a character is received!ã ' Use check4char%() before calling!ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'returns ascii value of character receivedã 'ã ' -=-=-=-=-=- Data for check4char -=-=-=-=-=-=-ã '[non-destructive read-ahead]ã 'Use before waitreceive() to make sure character available.ã '"peeks" at character without retrieving from buffer.ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'returns 0 for no character, or ascii value of char waiting in bufferã 'ã ' -=-=-=-=-=- Data for sendchar% -=-=-=-=-=-=-ã '[send character out port]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'returns 0 if successful, -1 if character rejected (buffer full)ã 'ã ' -=-=-=-=-=- Data for getdriverinfo -=-=-=-=-=-=-ã '[get information about fossil driver]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'loads structure driverinfo with information about driverã 'ã ' -=-=-=-=-=- Data for flushbuffer -=-=-=-=-=-=-ã '[flush output buffer]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'flushes buffer, waiting until all characters have been sentã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for purgeoutputbuff -=-=-=-=-=-=-ã '[purge output buffer]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'clears output buffer destroying any characters waiting to be sent.ã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for purgeinputbuff -=-=-=-=-=-=-ã '[purge input buffer]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'clears input buffer destroying any characters waiting to be read.ã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for sendbreak -=-=-=-=-=-=-ã '[toggle break]ã 'port% = 0=com1, 1=com2, 2=com3, 3=com4ã 'status: 1 = start sending break, 0 = stop sending breakã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for reboot -=-=-=-=-=-=-ã '[fossil reboot]ã 'if coldwarm% = 0 then cold boot (memory check)ã 'if coldwarm% = 1 then warm bootã 'nothing returned (obviously)ã 'ã ' -=-=-=-=-=- Data for writeansi -=-=-=-=-=-=-ã '[writes character to screen with ANSI support]ã 'nothing returnedã ' -=-=-=-=-=- Data for writeansistrng -=-=-=-=-=-=-ã '[writes a string of characters to the screen with ANSI]ã 'uses calls to writeansi()ã 'nothing returnedã 'ã ' -=-=-=-=-=- Data for getcurorpos -=-=-=-=-=-=-ã '[get current cursor location]ã 'current row returned in row%, column in column%ã 'ã ' -=-=-=-=-=- Data for setcurorpos -=-=-=-=-=-=-ã '[set cursor location]ã 'specify row% and column%ã 'nothing returnedã 'ã 'ã TYPE driverinfoã structsize AS INTEGER 'size of structureã spec AS STRING * 1 'spec fossil conforms toã revlevel AS STRING * 1 'rev level of fossilã IDoffset AS INTEGER 'id string offsetã IDsegment AS INTEGER 'id string segmentã inputbuffsize AS INTEGER 'input buffer size in bytesã inpbytesleft AS INTEGER 'bytes waiting in bufferã outputbuffsize AS INTEGER 'output buffer size in bytesã outbytesleft AS INTEGER 'bytes waiting in bufferã screenwidth AS STRING * 1 'screen widthã screenlength AS STRING * 1 'screen lengthã comp2modembaud AS STRING * 1 'computer to modem baud rateã END TYPEã DIM SHARED driverinfo AS driverinfo 'structure for getdriverinfo()ã 'ãã '$INCLUDE: 'qb.bi'ã DIM SHARED regs AS regtypeã 'ã DECLARE FUNCTION initfossil% (port%)ã DECLARE SUB deinitfossil (port%)ã DECLARE FUNCTION inituart% (port%, baud&, parity%, stopbits%, wordlen%)ã DECLARE SUB setDTR (port%, state%)ã DECLARE FUNCTION waitreceive% (port%)ã DECLARE FUNCTION check4char% (port%)ã DECLARE FUNCTION sendchar% (port%, char%)ã DECLARE SUB getdriverinfo (port%)ã DECLARE SUB flushbuffer (port%)ã DECLARE SUB purgeoutputbuff (port%)ã DECLARE SUB purgeinputbuff (port%)ã DECLARE SUB sendbreak (port%, status%)ã DECLARE SUB reboot (coldwarm%)ã DECLARE SUB writeansi (char%)ã DECLARE SUB writeansistrng (ansistring$)ã DECLARE SUB setcursorpos (row%, column%)ã DECLARE SUB getcursorpos (row%, column%)ã DECLARE FUNCTION getblock% (buffer$, port%)ã DECLARE FUNCTION writeblock% (port%)ã 'ã crlf$ = CHR$(13) + CHR$(10)ã ctrlx$ = CHR$(24)ã port% = 1 'com2:ã '......................... Initialize FOSSIL .........................ã IF initfossil%(port%) THEN PRINT "Fossil driver not loaded!": ENDã '.......................... Initialize UART ...........................ã 'com2:, 9600 baud, no parity, 1 stop bit, 8 data bitsã baud& = 9600: parity% = 0: stopbits% = 0: wordlen% = 3ã status% = inituart%(port%, baud&, parity%, stopbits%, wordlen%)ã '.................. Display Fossil driver ID string ...................ã getdriverinfo (port%)ã DEF SEG = driverinfo.IDsegment 'get fossil ID stringã CLS : x% = 0: PRINT "Fossil ID string = ";ã DOã a% = PEEK(driverinfo.IDoffset% + x%)ã writeansi a%ã x% = x% + 1ã LOOP UNTIL a% = 0ã DEF SEGã writeansistrng crlf$ + crlf$ + "To exit press CTRL-X" + crlf$ã '......................... Main Program Loop...........................ã 'simple modem communications program...ã DOã a$ = INKEY$ã IF LEN(a$) THENã DOã test% = sendchar%(port%, ASC(a$)) 'send until acceptedã LOOP WHILE test%ã END IFã IF check4char%(port%) THENã char% = waitreceive(port%)ã writeansi char%ã END IFã LOOP UNTIL a$ = ctrlx$ã '............................. Program End ............................ã 'ã setDTR port%, 0 'lower DTRã writeansistrng crlf$ + "FOSSIL deinitializing. Program End."ã deinitfossil port% 'release fossilã ENDãã FUNCTION check4char% (port%)ã 'non-destructive read-ahead to peek and see if char waiting..ã regs.ax = &HC00ã regs.dx = port%ã interrupt &H14, regs, regsã IF regs.ax = &HFFFF THENã check4char% = 0ã ELSEã check4char% = regs.ax AND &HFFã END IFã END FUNCTIONãã SUB deinitfossil (port%)ã 'DTR is NOT affectedã regs.ax = &H500ã regs.dx = port%ã interrupt &H14, regs, regsã END SUBãã SUB flushbuffer (port%)ã 'flush buffer waiting until all output is doneã regs.ax = &H800ã regs.dx = port%ã interrupt &H14, regs, regsã END SUBãã FUNCTION getblock% (buffer$, port%)ã DIM regsx AS regtypexã regsx.ax = &H1800ã regsx.cx = LEN(buffer$)ã regsx.dx = port%ã regsx.es = VARSEG(buffer$)ã regsx.di = SADD(buffer$)ã interruptx &H14, regsx, regsxã getblock% = regs.axã END FUNCTIONãã SUB getcursorpos (row%, column%)ã regs.ax = &H1200ã interrupt &H14, regs, regsã row% = (regs.dx AND &HFF00) \ 256ã column% = regs.dx AND &HFFã END SUBãã SUB getdriverinfo (port%)ã DIM regsx AS regtypexã regsx.ax = &H1B00ã regsx.dx = port%ã regsx.cx = LEN(driverinfo)ã regsx.es = VARSEG(driverinfo)ã regsx.di = VARPTR(driverinfo)ã interruptx &H14, regsx, regsxã 'ã ' AX = number of characters transferredã ' CX = 3058h ("0X") (X00 FOSSIL only)ã ' DX = 2030h (" 0") (X00 FOSSIL only)ã 'ã 'structure driveinfo filled with data from call..ã END SUBãã FUNCTION initfossil% (port%)ã regs.ax = &H400ã regs.dx = port%ã interrupt &H14, regs, regsã IF regs.ax = &H1954 THEN initfossil% = 0 ELSE initfossil% = -1ã END FUNCTIONãã FUNCTION inituart% (port%, baud&, parity%, stopbits%, wordlen%)ã 'regs.ah = 0, regs.al = parametersã 'regs.dx = port to init 0=com1, 1=com2, etc.. (255 for local testing)ã 'parity = bits 4-3, stopbits = bit 2, wordlength = bits 1-0ã SELECT CASE baud&ã CASE 38400: baudrate% = 32 '001 bits 7-6-5ã CASE 19200: baudrate% = 0 '000ã CASE 9600: baudrate% = 224 '111ã CASE 4800: baudrate% = 192 '110ã CASE 2400: baudrate% = 160 '101ã CASE 1200: baudrate% = 128 '100ã CASE 600: baudrate% = 96 '011ã CASE 300: baudrate% = 64 '010ã END SELECTã regs.ax = baudrate% + parity% + stopbits% + wordlen%ã regs.dx = port%ã interrupt &H14, regs, regsãã 'Return: AH = RS-232 status code bitsã ' 0: RDA - input data is available in bufferã ' 1: OVRN - data has been lostã ' 5: THRE - room is available in output bufferã ' 6: TSRE - output buffer emptyã ' AL = modem status bitsã ' 3 : always 1ã ' 7: DCD - carrier detectãã inituart% = regs.axã END FUNCTIONãã SUB purgeinputbuff (port%)ã regs.ax = &HA00ã regs.dx = port%ã interrupt &H14, regs, regsã END SUBãã SUB purgeoutputbuff (port%)ã regs.ax = &H900ã regs.dx = port%ã interrupt &H14, regs, regsã END SUBãã SUB reboot (coldwarm%)ã 'if coldwarm% = 0 then cold boot, 1 then warm boot.ã regs.ax = &H1700 + coldwarm%ã interrupt &H14, regs, regsã END SUBãã SUB sendbreak (port%, status%)ã 'status = 1 send break, status = 0 stop sending breakã regs.ax = &H1A00 + status%ã regs.dx = port%ã interrupt &H14, regs, regsã END SUBãã FUNCTION sendchar% (port%, char%)ã 'returns 0 if char accepted, -1 if not..ã regs.ax = &HB00 + char%ã regs.dx = port%ã interrupt &H14, regs, regsã IF regs.ax = 0 THEN sendchar% = -1 ELSE sendchar% = 0ã END FUNCTIONãã SUB setcursorpos (row%, column%)ã regs.ax = &H1100ã regs.dx = row% * 256 + column%ã interrupt &H14, regs, regsã END SUBãã SUB setDTR (port%, state%)ã regs.ax = &H600 + state% 'state% = 0 for lower or 1 for raiseã regs.dx = port%ã interrupt &H14, regs, regsã END SUBãã FUNCTION waitreceive% (port%)ã regs.ax = &H200ã regs.dx = port%ã interrupt &H14, regs, regsã waitreceive% = regs.ax 'ah will be 0 so no need to AND with FFhã END FUNCTIONãã SUB writeansi (char%)ã regs.ax = &H1300 + char%ã interrupt &H14, regs, regsã END SUBãã SUB writeansistrng (ansistring$)ã 'calls writeansi() for each character in stringã FOR x% = 1 TO LEN(ansistring$)ã writeansi ASC((MID$(ansistring$, x%, 1)))ã NEXT x%ã END SUBããDouglas Lusher READ/CHANGE BAUD RATE FidoNet QUIK_BAS Echo Unknown Date QB, QBasic, PDS 129 4064 UART.BAS ' > BTW, what's MCR???ãã' Modem Control Register.ãã' > 'Douglas Lusher posted some code sometime back showing howã' > 'to read and change the baud rate using INP/OUT.ããã FUNCTION UARTpresent% (CommPort%)ã 'returns True (-1) if a National Semiconductor UART (8250B,ã ' 16450, 16550, or 16550A) is present at the comm portã ' specified. If communications is in progress on the port,ã ' it will be disrupted by running this proceedure.ã 'Based on Pascal code by Jeff Duntemannã ' in Dr. Dobbs Journal, July 1991ã ' assume False, UART not detectedã UARTpresent% = 0ã ' a constantã LoopBit% = &H10ã ' get the base address for the specified portã SELECT CASE CommPort%ã CASE 1: PortBase% = &H3F8ã CASE 2: PortBase% = &H2F8ã CASE 3: PortBase% = &H3E8ã CASE 4: PortBase% = &H2E8ã CASE ELSE: ERROR 5ã END SELECTã RBRPort% = PortBase%ã THRPort% = RBRPort%ã MCRPort% = RBRPort% + 4ã MSRPort% = RBRPort% + 6ã ' put UART into loopback test mode:ã ' first, save the current value of MCRã HoldMCR% = INP(MCRPort%)ã ' turn on loopback test modeã OUT MCRPort%, HoldMCR% OR LoopBit%ã HoldMSR% = INP(MSRPort%)ã ' out a specific pattern of bitsã OUT MCRPort%, &HA OR LoopBit%ã ' see if the correct pattern of bits comes backã Temp% = INP(MSRPort%) AND &HF0ã IF Temp% = &H90 THEN UARTpresent% = -1ã ' restore the value of MSRã OUT MSRPort%, HoldMSR%ã ' take the UART out of loopback mode and restoreã ' original value of MCRã OUT MCRPort%, HoldMCR AND NOT LoopBit%ã END FUNCTIONãã FUNCTION UARTtype% (CommPort%)ã 'returns the type of UART installed at the specified comm portã ' 0 = error (bad UART or no UART at this comm port)ã ' 1 = 8250, usually (not always) found in PC or XTã ' 2 = 16450, usually found in AT class machinesã ' 3 = 16550, found in PS/2 mod 50/60/early 80. FIFOs don't work!ã ' 4 = 16550A, found in later PS/2's. FIFOs fully operative.ã 'Based on Pascal code by Jeff Duntemannã ' in Dr. Dobbs Journal, July 1991ãã ' get the base address for the specified portã SELECT CASE CommPort%ã CASE 1: PortBase% = &H3F8ã CASE 2: PortBase% = &H2F8ã CASE 3: PortBase% = &H3E8ã CASE 4: PortBase% = &H2E8ã CASE ELSE: ERROR 5ã END SELECTãã FCRport% = PortBase% + 2ã IIRport% = FCRport%ã Scratchport% = PortBase% + 7ã ' write a pattern of bits to the scratch registerã OUT Scratchport%, &HAAã ' attempt to read it backã IF INP(Scratchport%) <> &HAA THENã ' a UART w/o a scratch register is an 8250ã UARTtype% = 1ã ELSEã ' setting bit zero of the FCR port enables FIFO buffersã OUT FCRport%, &H1ã ' get the FIFO status bitsã Temp% = INP(IIRport%) AND &HC0ã SELECT CASE Temp%ã ' if bits 6 & 7 are set it is a 16550Aã CASE &HC0: UARTtype% = 4ã ' if bit 7 is set and bit 6 is clear it is a 16550ã CASE &H80: UARTtype% = 3ã ' neither bit 6 or bit 7 set means it is a 16450ã CASE &H0: UARTtype% = 2ã ' error occuredã CASE ELSE: UARTtype% = 0ã END SELECTã ' disable the FIFO buffersã OUT FCRport%, &H0ã END IFãã END FUNCTIONãã FUNCTION BaudRate& (CommPort%)ã 'returns the current baud rate for the specifed portã BaudRate& = 0ã SELECT CASE CommPort%ã CASE 1: BaseAddr% = &H3F8ã CASE 2: BaseAddr% = &H2F8ã CASE ELSE: EXIT FUNCTIONã END SELECTã OUT BaseAddr% + 3, INP(BaseAddr% + 3) OR &H80ã LSB% = INP(BaseAddr%)ã MSB% = INP(BaseAddr% + 1)ã OUT BaseAddr% + 3, INP(BaseAddr% + 3) AND &H7Fã Divisor& = (MSB% * &H100) + LSB%ã IF Divisor& THEN BaudRate& = 115200 \ Divisor&ã EXIT FUNCTIONãã SUB SetBaudRate (CommPort%, NewBaudRate&)ã ' Dr. Dobbs Journal, May 1991, pg. 127ã SELECT CASE CommPort%ã CASE 1: BaseAddr% = &H3F8ã CASE 2: BaseAddr% = &H2F8ã CASE ELSE: EXIT SUBã END SELECTã LCR% = BaseAddr% + 3ã Divisor% = 115200 \ NewBaudRate&ã Temp% = INP(LCR%)ã OUT LCR%, Temp% OR &H80 ' OUT LCR%, INP(LCR%) OR &H80ã OUT BaseAddr% + 1, Divisor% \ &H100ã OUT BaseAddr%, Divisor% AND &HFFã OUT LCR%, Temp% AND &H7F ' OUT LCR%, INP(LCR%) AND &H7Fã END SUBãChad Beck COM ROUTINES FidoNet QUIK_BAS Echo 11-09-95 (02:12) QB, QBasic, PDS 62 3401 COM.BAS ' > I am STILL in need of a routine to initialize com ports 1 through 4ã' > at speeds up to hopefully 115,200bps... My routines have stoppedã' > working. I do NOT need any routines for writing/reading port data,ã' > all I need is something to set the bps rate, and maybe the parity,ã' > data bits, and stop bits as well. Doesn't anyone have source thatã' > meets these requirements?ãã' Alright, alright. You've suffered long enough. To set the BPSã'rate, first you need to calculate the Baud Rate Divisor, then set bit 7ã'of the Line Control Register on, then write the Baud Rate Divisor, theã'set bit 7 of the Line Control Register back off. This is untested:ãã BRD = 1843200 \ (16 * BitRate) 'calculate Baud Rate Divisorãã Byte = INP(ComAddress + 3) OR 128 'set bit 7 of LCR highã OUT ComAddress + 3, Byteãã OUT ComAddress + 1, BRD \ 256 'MSB of BRDã OUT ComAddress, BRD AND 255 'LSB of BRDãã Byte = INP(ComAddress + 3) AND 127 'set bit 7 of LCR lowã OUT ComAddress + 3, Byteãã ---***---ãã The Parity, Data & Stop bits are easier:ãã OUT ComAddress + 3, Byteãã The bit values of Byte are as follows (I'll spare the high ASCII):ã------------------------------------------------------------------------ã| Bit # Meaning Setting |ã|----------------------------------------------------------------------|ã| 0-1 Character length |ã| 5 bits 00 |ã| 6 bits 01 |ã| 7 bits 10 |ã| 8 bits 11 |ã| 2 Stop bits |ã| 1 bit 0 |ã| 1.5 bits 1 (5-bit characters) |ã| 2 bits 1 (6, 7 & 8-bit characters) |ã| 3-5 Parity |ã| Ignore 000 |ã| Odd 100 |ã| Even 110 |ã| Mark 101 |ã| Space 111 |ã| 6 Break condition |ã| Disabled 0 |ã| Enabled 1 |ã| 7 Port toggle |ã| Normal 0 (use THR/RDR & IER registers) |ã| Alternate 1 (use BRDL & BRDH registers) |ã| |ã------------------------------------------------------------------------ãã So, for instance, 8 data bits, 1 stop bit and no parity is 00000011ãbinary (3) while 7 data bits, 1 stop bit and even parity is 00011010ãbinary (26).ã Make sense? Let's hope so.ããErik Olson ANSI MODEM TERMINAL Rolf@ice.prima.ruhr.de 05-16-94 (23:20) PB 539 12416 TERMINAL.BAS' Ansi modem terminal program for PowerBASICã' Public Domain by Erik Olsonãã$OPTION CNTLBREAK OFFã$COM 2048ã$STRING 4ã$LIB GRAPH OFFã$LIB IPRINT OFFã$LIB LPT ONã$LIB COM ONã$FLOAT EMULATEã$COMPILE EXEãã%FALSE = 0ã%TRUE = NOT %FALSEãã' sound effectsãDECLARE SUB BELL()ãDECLARE SUB DAGNABBIT()ãDECLARE SUB FWEEP()ãDECLARE SUB FWOP()ãDECLARE SUB YIPPEE()ãã' support routinesãDECLARE SUB TERMINAL(STRING)ãDECLARE FUNCTION POPDIR$(STRING)ããON ERROR GOTO ErrorHandlerããDIM MENU$(10)ãSHARED MENU$(), TermScreen$, Termx%, Termy%, ScrnBuf%ããCLSãFWEEPãMESSAGE "ANSI MODEM TERMINAL"ãDELAY .5ãMESSAGE "PowerBASIC 3.00b"ãDELAY .5ãMESSAGE "INITIALIZING PORTS"ãSETPORTSãDELAY .3ãMESSAGE "VERIFY PARAMETERS"ãBELLããA$ = DIR$("OPENCOM.DAT")ãIF A$="" THENã P$="COM2:2400,N,8,1,RS,CS,CD,DS,ME "ãELSEã OPEN A$ FOR INPUT AS #1ã LINE INPUT #1, P$ã CLOSE #1ãEND IFãP$=P$+SPACE$(40-LEN(P$))ãP$=EDITBOX$(P$)ãIF P$="" THEN END ELSE OPEN "OPENCOM.DAT" FOR OUTPUT AS #1:PRINT #1, P$:CLOSEããTERMINAL P$ããLOCATE 25,1:ENDããã' ==========[subroutines]=============ããããSUB TERMINAL(Parameter$)ãIF Parameter$ = "" THEN EXIT SUBãComBuf% = FREEFILEãCapBuf% = 9ãPrnBuf% = 10ãOPEN Parameter$ FOR RANDOM AS #ComBuf%ãScrnBuf% = FREEFILEãOPEN "CONS:" FOR OUTPUT AS #ScrnBuf%ãIF LEN(TermScreen$) THENã RESTORESCREEN TermScreen$:ANSILOCATE Termx%, Termy%ã LOCATE Termx%,Termy%,1ãELSEã CLS:ANSILOCATE 1,1:LOCATE 1,1,1ãEND IFãPRINT #ScrnBuf%, "PowerBASIC 3.00b Modem Terminal Program"ãPRINT #ScrnBuf%, "Terminal Mode þ Press INSERT for menu"ãPRINT #ScrnBuf%, "RESETTING MODEM..."ãRESETMODEM ComBuf%ãBELLããDOã A$=INKEY$ã IF A$=CHR$(27) THEN A$=CHR$(0,82)ã IF LEN(A$) = 2 THENã ANSICURSOR x%,y%ã LOCATE x%,y%,0ã SELECT CASE A$ã CASE CHR$(0,45) 'alt-X = quitã CLS:PRINT "Wait...":RESETMODEM ComBuf%:PRINT "*** End Program"ã LOCATE 25,1,1:CHAIN "PA(CAR).EXE" 'ENDãã CASE CHR$(0,72) ' up arrowã Print #Combuf%,chr$(27)+"]A";ã CASE CHR$(0,75) ' left arrowã Print #Combuf%,chr$(27)+"]C";ã CASE CHR$(0,77) ' right arrowã Print #Combuf%,chr$(27)+"]D";ã CASE CHR$(0,79) ' endã Print #Combuf%,chr$(27)+"]K";ã CASE CHR$(0,80) ' down arrowã Print #Combuf%,chr$(27)+"]B";ã CASE CHR$(0,71) ' homeã Print #Combuf%,chr$(27)+"]H";ã CASE CHR$(0,83) ' Deleteã Print #Combuf%,chr$(&H7F);ãã CASE CHR$(0,104) ' ALT-F1ã O$=SAVESCREEN$ã FWEEPã IF Capture%=0 THEN MESSAGE "CAPTURE FILENAME:"ã INCR Capture%ã IF Capture% THEN Cap$=EditBox$(" ")ã IF Cap$="" THEN Capture%=0ã FWEEPã IF Capture%=1 THENã Capture%=-1ã MESSAGE "CAPTURE ON"ã OPEN Cap$ FOR APPEND AS #CapBuf%ã ELSEã MESSAGE "CAPTURE OFF"ã CLOSE #CapBuf%ã END IFã DELAY 1ã RESTORESCREEN O$ãã CASE CHR$(0,38) ' ALT-Lã O$=SAVESCREEN$ã INCR Printer%ã FWEEPã IF Printer%=1 THENã Printer%=-1ã MESSAGE "PRINTER ON"ã ELSEã MESSAGE "PRINTER OFF"ã END IFã DELAY 1ã RESTORESCREEN O$ã CASE CHR$(0,35) ' ALT-Hã O$=SAVESCREEN$ã FWEEPã MESSAGE "RESETTING MODEM..."ã RESETMODEM Combuf%ã FWOPã RESTORESCREEN O$ã ANSILOCATE x%,y%ã CASE ELSEã 'menuã O$ = SAVESCREEN$ã ANSICURSOR X%, Y%ã MENU$(1) = "Dial a Number "ã MENU$(2) = "Toggle Capture "ã MENU$(3) = "Toggle Printing"ã MENU$(4) = "End Session "ã MENU$(5) = ""ã FWEEPã SELECT CASE POPMENU(MENU$())ã CASE 1ã O2$=SAVESCREEN$ã MESSAGE "Number to Dial"ã A$ = EDITBOX$(" ")ã RESTORESCREEN O2$ã IF LEN(A$) THENã RESETMODEM ComBuf%ã DELAY 1ã PRINT #ComBuf%, "ATDT"+A$ã END IFãã CASE 2ã FWEEPã IF Capture%=0 THEN MESSAGE "CAPTURE FILENAME:"ã INCR Capture%ã IF Capture% THEN Cap$=EditBox$(" ")ã IF Cap$="" THEN Capture%=0ã FWEEPã IF Capture%=1 THENã Capture%=-1ã MESSAGE "CAPTURE ON"ã OPEN Cap$ FOR APPEND AS #CapBuf%ã ELSEã MESSAGE "CAPTURE OFF"ã CLOSE #CapBuf%ã END IFã DELAY 1ã CASE 3ã INCR Printer%ã FWEEPã IF Printer%=1 THENã Printer%=-1ã MESSAGE "PRINTER ON"ã ELSEã MESSAGE "PRINTER OFF"ã END IFã DELAY 1ã CASE 4 ' end sessionã MESSAGE "RESETTING MODEM"ã RESETMODEM ComBuf%ã AbortFlag% = %TRUE:CHAIN "PA(CAR).EXE"ã CASE ELSEã FWOPã END SELECTã RESTORESCREEN O$ã FWOPã ANSILOCATE X%,Y%ã END SELECTã IF AbortFlag% THEN EXIT LOOPã ELSE ' len a$ does not equal 2ã PRINT #ComBuf%,A$;ã END IF ' len a$ãã IF LOC(ComBuf%) THENã A$=INPUT$(1,ComBuf%)ã IF A$=CHR$(8) THEN A$=CHR$(8)+" "+CHR$(8)ã IF A$ = CHR$(7) THEN A$ = "": BELLãã IF Printer% THEN LPRINT A$;ã IF Capture% THEN PRINT #CapBuf%, A$;ã PRINT #ScrnBuf% , A$;ã END IFãLOOPãCLOSE #ComBufãTermScreen$ = SAVESCREEN$ãANSICURSOR Termx%, Termy%ãENDããEND SUBããSUB SETPORTSãdef seg=&h40ãpoke 0,&hf8 '03F8 sets com1 address irq 4ãpoke 1,&h03ãpoke 2,&hf8 '02F8 sets com2 address irq 3ãpoke 3,&h02ãpoke 4,&he8 '03E8 sets com3 address irq 4ãpoke 5,&h03ãpoke 6,&he8 '02E8 sets com4 address irq 3ãpoke 7,&h02ãdef segããEND SUBããSUB RESETMODEM(m%)ã DELAY 1.1ã PRINT #m%,"+"; : DELAY .3ã PRINT #m%,"+"; : DELAY .3ã PRINT #m%,"+"; : DELAY 1.1ã PRINT #m%,"ATZ"ã DELAY .5ãEND SUBãããFUNCTION SaveScreen$ãREG 1, 15*256ãCALL INTERRUPT &H10ãIF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address=&HB000 else Address=&HB800ãDEF SEG = ADDRESSãSaveScreen$=PEEK$(0,4000)ãDEF SEGãEND FUNCTIONããSUB RestoreScreen(S$)ãREG 1, 15*256ãCALL INTERRUPT &H10ãIF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address=&HB000 else Address=&HB800ãDEF SEG = AddressãPOKE$ 0, S$ãDEF SEGãEND SUBããFUNCTION PopMenu(item$())ã' Center a scrolling menu on the screen containing options in Item$()ã' This function returns the number of the selected item, or 0 if ESC pressed.ãCOLOR 0,7ãMenWid=0:MenHi=0ãDO:MenHi=MenHi+1:IF LEN(Item$(MenHi))>MenWid then MenWid=LEN(Item$(MenHi))ãLOOP WHILE LEN(Item$(MenHi))ãMenHi=MenHi:MenWid=MenWid+4ãã' Menu box is MenHi x MenWidã wa% = 12 - (MenHi\2)ã wb% = 40 - (MenWid\2)ã wc% = wa% + MenHiã wd% = wb% + MenWidãCALL SingleBox(Wa%,Wb%,Wc%,Wd%)ããFor y=1 to MenHi-1ã Locate 12 - (MenHi\2) + y, 42 - (MenWid\2):Print Item$(y)ãNext yãã PopMe=1ã DOã Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2),0ã Color 7,0 : Print Item$(PopMe) : Color 0,7ã do:a$ = Inkey$:loop while a$=""ã If Len(a$) = 2 THEN a=asc(right$(a$,1)) else a=asc(a$)ããã SELECT CASE aãã CASE &H48 ' up arrowã Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)ã Print Item$(PopMe)ã PopMe=PopMe-1ã If PopMe = 0 then PopMe = MenHi-1ãã CASE &H50 ' dn arrowã Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)ã Print Item$(PopMe)ã PopMe=PopMe+1ã If PopMe = MenHi then PopMe = 1ããã CASE &H47 ' homeã Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)ã Print Item$(PopMe)ã PopMe=1ããã CASE &H4D ' right arrow ........ it could happenã CASE &H4B ' left arrowã ' these keys might indicate that theã ' user wants to move horizontally toã ' another menu. See CASEKEYS.BAS forã ' a generic keyboard polling CASE structãããã CASE &H51 ' page downã Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)ã Print Item$(PopMe)ã PopMe=MenHiãã CASE &H49 ' page upã Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)ã Print Item$(PopMe)ã PopMe=1ãã CASE 27 ' escapeã PopMenu=0 : Exit Loopãã CASE 13ã PopMenu=PopMe : Exit Loopãã CASE ELSEã END SELECTãããloopããCOLOR 7,0ãEND FUNCTIONãããããFUNCTION EditBox$(Default$)ããCOLOR 0,7ãCALL SingleBox(19, 38-(LEN(Default$)\2), 21, 42+(LEN(Default$)\2))ãy = 40 - (LEN(Default$) \ 2) : YY=len(rtrim$(default$))ãDOããã LOCATE 20,Y,0:PRINT Default$ ' if you want to put the box somewhereã LOCATE 20,Y+yy,1 ' else, change these locate statementsããã DO:A$=INKEY$:LOOP WHILE LEN(A$)=0ã IF LEN(A$) THENã SELECT CASE(A$)ã CASE CHR$(27), CHR$(13)ã EXIT SELECTã CASE CHR$(8)ã IF YY THENã YY=YY-1ã IF YY THENã Default$=LEFT$(Default$,yy)+MID$(Default$,yy+2) + " "ã ELSEã Default$=MID$(Default$,yy+2) + " "ã END IFã END IFã CASE CHR$(0)+CHR$(83)ã IF YY THENã Default$=LEFT$(Default$,yy)+MID$(Default$,yy+2) + " "ã ELSEã Default$=MID$(Default$,yy+2) + " "ã END IFã CASE CHR$(0)+CHR$(&H4D)ã IF YY < LEN(Default$) THEN YY=YY+1ã CASE CHR$(0)+CHR$(&H4B)ã IF YY THEN YY=YY-1ã CASE CHR$(0)+CHR$(79) 'endã yy=LEN(RTRIM$(default$))ã CASE CHR$(0)+CHR$(71)ã yy=0ãã CASE ELSEã IF LEN(A$)=1 and YY=0 THEN Default$=SPACE$(LEN(default$))ã IF LEN(A$)=1 and YY < LEN(Default$) THEN_ã MID$(Default$,YY+1,1) = A$ : YY=YY+1ãã END SELECTã IF A$=CHR$(27) THEN EditBox$="":EXIT LOOPã IF A$=CHR$(13) THEN EditBox$=RTRIM$(Default$):EXIT LOOPãã END IFãLOOPãCOLOR 7,0ãEND FUNCTIONãããSUB SingleBox (Wa%, Wb%, Wc%, Wd%) PUBLICããREG 1, 15*256ãCALL INTERRUPT &H10ãIF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address&=&HB000 else Address&=&HB800ãDEF SEG = ADDRESS&ãã LOCATE Wa%, Wb%,0: PRINT CHR$(213) + STRING$((Wd% - Wb%) - 1, 205) + CHR$(184)ã LOCATE Wc%, Wb%: PRINT CHR$(212) + STRING$((Wd% - Wb%) - 1, 205) + CHR$(190)ãã FOR zxy% = 1 TO Wc% - Wa% - 1ã LOCATE Wa% + zxy%, Wb%ã PRINT CHR$(179) + SPACE$((Wd% - Wb%) - 1) + CHR$(179)ã ' right side of the box is Wa+zxy *80 + Wd + 1ã ' stuff an attribute into thereã POKE ( (Wa%+Zxy%) * 160 ) + (Wd%*2) + 1,8ã NEXT zxy%ã for i%=(Wc% * 160) + ((wb%+2)*2)-1 TO (Wc%*160) + ((Wd%*2)+2)-1 STEP 2ã ' What this does is calculate the memory locations of the charactersã ' in video ramã POKE i%, 8ã Next i%ãDEF SEGãEND SUBããSUB Message (E$)ã CALL SingleBox(10, 20, 12, 60)ã LOCATE 11, 40 - (LEN(E$) \ 2)ã PRINT E$;ãEND SUBããFUNCTION YesNo (Prompt$)ãIF LEN(Prompt$) < 15 THEN Prompt$ = SPACE$(8 - LEN(Prompt$) \ 2) + Prompt$ + SPACE$(8 - LEN(Prompt$) \ 2)ãWb% = 38 - LEN(Prompt$) \ 2ãWd% = 42 + LEN(Prompt$) \ 2ãWa% = CSRLINãWc% = Wa% + 3ãCALL SingleBox(Wa%, Wb%, Wc%, Wd%)ãLOCATE Wa% + 1, 40 - LEN(Prompt$) \ 2: PRINT Prompt$ãYorN = -1ãLET YorN$ = " No "ãDOã LOCATE Wa% + 2, 34: PRINT YorN$ã DO: A$ = INKEY$: LOOP WHILE A$ = ""ã IF UCASE$(A$) = "Y" THEN YorN = -1ã IF UCASE$(A$) = "N" THEN YorN = 0ã IF A$ = CHR$(0) + CHR$(&H4D) THEN YorN = 0ã IF A$ = CHR$(0) + CHR$(&H4B) THEN YorN = -1ã IF A$ = CHR$(13) THEN EXIT LOOPã IF YorN THEN LET YorN$ = " No " ELSE LET YorN$ = " Yes "ããLOOPãYesNo = YorNããEND FUNCTIONããSUB SETHIBIT ' toggle blink to intensity bitã REG 1,&H1003ã REG 2,0ã CALL INTERRUPT &H10ãEND SUBããSUB ANSILOCATE(ROW%, COL%) 'Sets BIOS cursorã LOCATE Row%,Col%,1ã REG 1,&H0200ã REG 2,0ã REG 3,(Row%*256)+COL%ã CALL INTERRUPT &H10ãEND SUBããSUB ANSICURSOR(ROW%, COL%) 'Returns the current position of the cursorãREG 1,&H0300ãREG 2,0ãCALL INTERRUPT &H10ãROW% = (REG(4) \ 256) + 1ãCOL% = (REG(4) AND &HFF) + 1ãEND SUBããSUB FWEEPãFor y% = 800 TO 1800 STEP 200ãSOUND y%,.1ãNEXT y%ãEND SUBããSUB FWOPãFOR y% = 1800 TO 800 STEP -200ãSOUND y%, .1ãNEXT y%ãEND SUBããSUB YIPPEEãSOUND 1000,1:SOUND 2000,1:SOUND 3000,1ãEND SUBããSUB DAGNABBITãSOUND 50,5ãEND SUBããSUB BELLãSound 1000,.1ãSOUND 5000,.1ãSOUND 2500,.1ãSOUND 1000,.1ãDELAY 1ãEND SUBãããErrorHandler:ããE = ErrãEO$=SAVESCREEN$ãDAGNABBITãFWOP:FWOP:FWOPãMESSAGE "ERROR:" + STR$(E)ãLOCATE 19,1ãIF YesNo("Continue?") THEN RESTORESCREEN EO$:RESUME NEXTãFWEEPãLOCATE 19,1ãIF YesNo("Exit to DOS?") THEN CLS:ENDãFWEEPãRESTORESCREEN EO$:MESSAGE "RESETTING MODEM...":RESETMODEM ComBuf%ãRESTORESCREEN EO$ãRUNããErik Olson PB FOSSIL ROUTINES Rolf@ice.prima.ruhr.de 08-14-94 (02:57) PB 127 8372 PBFOSL.BAS ' Please run under PowerBASIC to extract PBFOSL.ZIPãDEFINT A-Z: SHARED K,S,B&,Z&:V1 'Created by PostIt! 7.2ãSUB V1:OPEN "O",1,"PBFOSL.ZIP",4^6:Z&=5973:?STRING$(50,177);ãU"%up()%9%%%.-%*y&n>%5,=&S1%%%DI%%%0%%%%ug%kxht%rSgfFx.>K*Zj/1Fg$2b64I'Y-E:\aO[?vnNHq8F.DPA2E)FãU"t[XI-WXD.I%]MBtO8Z%YLSgkh-EiIP=6:nB6$$V$Z3[dOrgi&$VhfK]84l\QWfLãU"N#%Zs&aFRuJh3p&,o)F-m/.XDk4f'h%KnDPg7xN0EdIL;.keDW8j5gRs1=YOmC;ãU"TL>F3wYQ\OSJ).5[$uBxSF[CI_EO27xgveW]**8_)YjAj22tcI;k)M3p>s)4q7fãU"2fXq9#yGZ^F7Bgti%ug(kXh>:5vi:93+?t4rtXmOKiFIp\Kf)l&_*:qLYaãU"aAMn;cuMVR#NLYKB/m-,6T$gC%<3t#>c2i[0j>t+m-rc\6i'^v.]Q48Q4#I)0hGãU"S3G&59f15ijsK0&X]RXB0u7=AzEoq-+&'5dP^A2D.oKC\S2l\^^Ctxt0L?_m-Q/ãU"C&v9c7$G8-LgI]0+4ugJK4W[*E)p>.55:+56A[gFhmqI>a'EakV\09CEGx03r1EãU")Ao5KfW<&t6*D<&&#g*sh:-.JK*'8wtB;3'.'=XãU"/qM9(Z64XVGXqb\Oz9r>\EhoJm:RXCRodhm&+,LFkokgTs(D;a[htgT$Emv.Y1SãU"x^-xiOq'M*KS:6Iu&Tci.-5)EuFMCT=S:%nNY_qM>=;V9'Gt=0bP:a]6pH,JC%SãU"&Cv:foCX_pS%.%Jw>P]RKxHl#qA#L<;xHP7Ldh.fic];r]Hi[AM,>(aYN4K/5TiãU".l5HI4%Z#o3'OB)I0wM.OWXE[gfw/QM#u_>.f=Gpl;KqN;^0x11-wgkfa5=2(/YVcRE_7dnHnS9jOO68fEAK#ãU"3qm5X\Vbo:4Z<8oIBBu_BC',2HFMdgxNgC-MAlp[7-YNHe_mNsSFb$n.>nbzãU"1n<5ggP'4v3[X=r,DbB'ZD0R;Hwe7ieytjiJ0?2b?&MH0f6w%1V.)SkRO*g6nErãU"^7dbE4,RMthTh-771%w[O7=pU%W<#hM:?[$RQMVBKr\+b%T?BN6.0biCL;\2qi7;X[.7$>2cqHt#rRJTtp8#i,5iNbq&N_$:K8WA6ufMYnnbEWuRDR*kAIUc^RvabQVww/.I-q<:p2K_Q_ãU"JYbk\gt=Elw5OWtWVQBp])lh\ln7XWVcjKFK+<_xjLr_9rP8Ddd=v7&J;z[q(+\ãU"VMIvit\(FnlD-UeEKf+:(ll4AZN?j^aN%1jSqubdns/f_&=*<3$tMC23^rCYbrHãU"zEJ,'yca$>B\[9cdu*l31z1/4s0q;:p6Ng;?'J.A5ghrpPMf?ZgXs1?oLQYL7-iãU"t)27//gH,GD=;*o06'$OfOvF]j_J5ooC5,17-64$WH.he;4-D$[,t_+8a4kc\JaãU">.a+n_+:ZIB$7G1'WZW5mc90\bXU+tFkYh+>pwKxN+3?ADhf'JN.M)4Yem4uL0tãU"4BJhoL=vG=Ml%8DJ4&jdv[IuDhH.%2N/3KHN-.G:\m.Sxl0%g>LPOZp5S^9?04YãU"4x31'B4v_*V\wpY+gp9J),nYAHK--<;q3(d4kXKmD.-?6e235D^E)a2SlqZãU",1UBn.)$)W*M,L3InjEV[D1[REl)08>3MbZkX&UPSz?-sGutuf_-j?7Vo$kV/SeãU"0szZ13mrbv5%gNcH9al?i3?XSjr++[vmg%V=kAd382HeKF1q^Bj=tmdH72Z0L/k63jY'ãU"QE8/QMYF%.J05,ilqV]s8LLjAhm^Y40Ppb.oN75EGu(f\xb_f5LUK0*nwMphrlgw#L:1r/^#mz(Y.T&aNC#%g?j_2/q'WB':D7%jWgUdiofj1ãU"_aLho-Hk5/SxP\KCe(w:\ãU">;^NDV$HKtm1BYpMVO#X79rdwWx5)'spnoJyp:\+D98a(q?pf_47xd\$,'];HF7ãU";+jnIIbZdf$;YrTt:CJf1B[V_ZmXX^/.aeLrjãU"QU(J0H>93_5(P]hI3c3HdZ855Mp[&7]dy\GL>waN-po_t=XHjãU"Vs\3=:8ZnvkD_&]5C^bjHCn^^k>oWãU"6oEC>jmRA5mrU=q26UZ3/B(=_g+t-pB,=cLkaXhkv1hDM'o(LSPgjJ2l:y)N=3[ãU"E$AQ0JblA?F4\n'0&L][gvQla.*R>n&6APsDpesRBtIrb]9GZT65HVdEt_SROGgãU"_]npCkol.Ftiw>wb<.r0Ep2&m8Hc2p6\Dn^T<8NDPXz/%a1o.gNjãU"Wnq>>S&m;M'+X/^8l5O#E1GhhB[+jsp:KiH0%Yz3wyMtp6%Um4oLI^0'M>bE/]TãU"u[WML8n\OcGPtrWEgKWfVVs\^k9aqsYH6hbKC;Q+dx#u%p()9%%%%-g%H+tC?s=ãU"$%3D(%+%[+%%%0%%%%ktx%yjwr%SgfxJ\y<^\y]9w8Kru4V6'F/gg5C_(Kj]VO#ãU"=IVA+;-/lOv'ZUUa:1ZS[Uno8R1C73s+VD)JsnkvHHdWABvn5/%R]PE6V?K2VURãU"(:#a$sG)Wq+s[+c;;vL=r^aORZQM8F78%1,JP7E9d0YfAR&>Vd8G#7bF9kT)uA*ãU"be%NDtY9uhffA%E^4+grFzRSUlY9\.rD,bTq62uven8Z%1U%NA9QB&3*J$tNy*GãU"s+;&7Grnhr>C%1a)J]ZYr[R<'-h^Tq_FYp:5p%^5R-Df&U7x:=H(jV;vtaIaLWQãU"HD8,n=4;\z+H1][bgA5/geZ.wQ2u/ezCLaXR'GjL'TaL^WFQL^xV9H%jb[huj=XãU"R\/k:wUB9oXVbXA.\)hw,l$WA>Jis]5-gB*]sLK*tx6&E-^qTEãU";/D1^zm%dkw]=wmdPCNfpD-PtLbe\(ESMrqI2l-5P&M]L7R3&].e$48EFpa]F)uãU"[+F_ab-[f+*lu0Dx*Ft_4X>]m*iãU"4z[1B46+EbUWVYW[11Lic\2&dLEQ/b\=#h>dZZ&+E]M)>_Q*hAql9(&Y'ZAA:Mkpb)1w=tk0/iZjY9pcffbNp%Mv<4)1co]6X-plb>%1b1^\.5O;*6[qsxBXrp\0gr3XãU"j:m?d6pVsHP&rP&mplRX&NlZD50H&aX<]bFr%mM30mUbYL-;I-j'\K?m[OI70i&B122w0T*.s^k]AvCBg8LQ\5P?s3oDãU"W]Wjh]c&hNu%jMvG$G]Z/e>(8gkr#L2(0/W>7a7+2Gy4]=RbC:$n1/bKJl3CvorãU"WH5i?\pPxG+$Ia_j]5;;EGrV9O:%?ESV60ZVEl9Tqh%7%X0C$uaU%]Jn%RG_C[RãU"fB5y2WQVu&4):?U+H8EmxeeIk(0nd*d+yU^w0vqFOUtCX*9;ww%%up()%9%%%%-%Z08rãU").%%07%%%/%%%%kt%xxnq%SgfxN&&0>][k5vRCNx0m?fGa_AxrA0nwdo&/qfGO)ãU"Rutsw8eRgp'ljPqniSkNX(Tp)jQq5a4d7OJdH>ZWGE]o#2lZJM[m'LUn],'1=c]ãU"3GGAbcdHTGuHGHa*,sGIg&g1+V;+:[+0Ry4kUlxbe]Du)iIDVCUcXvuquMxK>QRãU"5dU>j$6S_R#iD'u05-H*EVm^aS(l]R\'i8MqOu1R6eidU]D7UO9k94/F9I_&&r$ãU"Tl?-e#/Lp9rYS]8X[gs+pPtpQ8rA)i4M)4:Z#%\5lUi3N+[mnQRO./h+p4s56$tãU"e6EW3'i\x:RroK_;Z^AakAnFF)n8kduCQ&Z,hT%st\a_S(W>iBN^-brFn+6JE3PãU"fa]%w/dK5^M%sawst$4OLs3D+qO0QBbI#8&O%MYtiZJ-Sxwf\W_dNZ>JY)ãU"+AjX'79/P47:&o4hY*ORiAO#*.dS?4v*tcA7XGg]U&G2puIs\7,l>75[GyzClDxãU"oR?/+5cZ\$2m_*'7bo]#q[ywt7Ghc;xNU$<0o-)$dn&V$*Xa=(]He,GB+7+'s?*ãU"KnkHgc-M.x);r.62)iO68R4gAIajXU;EalI#kiXUQ.y2:?QIQpUv:PWW+S%(?m'ãU"/-eX%fBFqa7u02)If(u1[w#u\JTJx0SD-E^*8JHr94m\6%F=+WuDkT1XybnQ4L+ãU"Z7(^GS(B[24$+f?G)n259u[ntBxI7(0Tl9&_PVEp3,bn;uJnqamgE?tR1Z\_'6ãU"(XL&-dq.]mHl3w$^myA.nZvt8so2L(p8Hd$t36>yb,LB4D3hAbp5]41635+0uS\ãU"%[WisyKY4nbO]&cQ%E0Z3/hjVHggN%JoH&Pr/7(k:KJ?n(N9=N:$Y^'D>oW.k+$ãU"m%>LWbR7W/7:N+JLTQWUok_LrdGX)j=]iJEuNs=](od7jW<09n69\p9RaM)8=cpãU"[ZB+F%$,7Og1+CRHm%'$C0)O7[k$3ZKL1zd3crg]DY960oL7^E\-#W$b'W9aãU"C3H$dXP385Ur%lPC:lq=LhCp=?nlvs&pvLBEEp,WO9j5-yWON1t?d&'3lgAi7>mãU"qpGZ3_A=n7>aI9<,a=L?-VRv%A86dnAHKSuãU"g[GVn:J&>ãU"%5='&S1%%%DI%%%0%%%%%%%%%&%E%%%%%%%%%u%gkxh%trSg%fxup%&'9%%9%%%ãU"I-%H+0t?s=&$3D(7%%[+%%%0%%%%%%%%%&%%E%%%&&1%%%ktxy%jwrS%gfxu%p&ãU"'9%%9%%#%-%<,9#AlXFV$L[&%%C%'%%+%%%%%%%%%&%%E%%(%n4%%%wjf%irju%ãU"p&'9%%9%%%%-%Z#<3BHq808r#)%%0%7%%/%%%%%%%%%&%%E%%%%e6%%%ktx%xnqãU"S%gfxu%p*+%%%%%)[%)%W#%%%0%;%%%%%ãEND SUBãCLOSE:IF S=98AND 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ãMichael Parker COM SUPPORT comp.lang.basic.misc 03-03-96 (07:25) QB, QBasic, PDS 110 3328 COMSUPP.BAS '> Help on how to access COM's 1 through 4 or 8. Please help.ãã'Here's a _very_ nice routine to open com1-com4 (up to 115k baud, too).ã'These routines were written by Michael Parker. Hope they help.ã'Originally posted by Jonathan Leger ãã'--- START HERE ---ãã' Quick Basic Routine OpenComã' This routine will accept the entire OPEN command parametersã' that is in QB 4.5 , the only exception is the baud rate andã' COM port. Baud rate is optional, if specified, this moduleã' will set the specifed rate up to 115,200. If the baud rateã' is specifed at 0, the specifed port will be polled for theã' current baud rate and the baud rate will be set at the rateã' that is present, if any. NOTE: the baud rate parameter onã' the command line IS NOT optional, if you want this moduleã' to set the baud rate, put an extra comma into the commandã' line to replace the baud rate. The COM Port will accept upã' to COM 4 now.ãã' OPENCOM "COMX:{option list1 [baudrate,parity,databit]},{option list2}ã' AS FileNum"ã' examples:ã' OPENCOM "COM1:38400 as 1"ã' OPENCOM "COM4:,op500 as 1"ã' OPENCOM "COM2:2400,n,8,1,op500 as 4"ã' OPENCOM "COM3:,,, OP500 as 2"ããDECLARE SUB OPENCOM (InString$)ãCALL OPENCOM(InString$)ãENDããSUB OPENCOM (Sting$)ãSting$ = LTRIM$(RTRIM$(Sting$))ãPort$ = UCASE$(LEFT$(Sting$, 5))ãSting$ = RIGHT$(Sting$, LEN(Sting$) - 5)ãFOR x = 1 TO LEN(Sting$)ã H$ = MID$(Sting$, x, 1)ã IF UCASE$(H$) = "A" THENã H$ = H$ + MID$(Sting$, x + 1, 1)ã IF UCASE$(H$) = "AS" THENã FileNum = VAL(MID$(Sting$, x + 2, LEN(Sting$)))ã EXIT FORã END IFã END IFã InputString$ = InputString$ + H$ãNEXT xãFOR x = 1 TO LEN(InputString$)ã IF MID$(InputString$, x, 1) <> "," THENã BaudRate$ = BaudRate$ + MID$(InputString$, x, 1)ã ELSEã InputString$ = MID$(InputString$, x + 1, LEN(InputString$))ã EXIT FORã END IFãNEXT xãIF LTRIM$(BaudRate$) = "" THENã BaudRate& = 0ãEND IFãSELECT CASE Port$ã CASE "COM1:"ã BaseAddr% = &H3F8ã Port1$ = "COM1:"ã CASE "COM2:"ã BaseAddr% = &H2F8ã Port1$ = "COM2:"ã CASE "COM3:"ã BaseAddr% = &H2F8ã Port1$ = "COM1:"ã CASE "COM4:"ã BaseAddr% = &H3F8ã Port1$ = "COM2:"ã CASE ELSEã PRINT "Illegal COM Port"ãEND SELECTããIF BaudRate$ = "" THENã OUT BaseAddr% + 3, INP(BaseAddr% + 3) OR &H80ã LSB% = INP(BaseAddr%)ã MSB% = INP(BaseAddr% + 1)ã OUT BaseAddr% + 3, INP(BaseAddr% + 3) AND &H7Fã Divisor& = MSB% * &H100 + LSB%ã IF Divisor& = 0 THENã BaudRate& = 0ã ELSEã BaudRate& = 115200 / Divisor&ã END IFãELSEã BaudRate& = VAL(BaudRate$)ãEND IFãIF LEFT$(InputString$, 1) <> "," THENã InputString$ = "," + InputString$ãEND IFãOPEN Port1$ + "300" + InputString$ FOR RANDOM AS FileNumãIF Port$ = "COM3:" THENã POKE &H400, &HE8ãELSEIF Port$ = "COM4:" THENã POKE &H402, &HE8ãEND IFãIF BaudRate& <> 0 THENã Divisors# = 115200 / BaudRate&ãEND IFãLCR = BaseAddr% + 3ãTemp = INP(LCR)ãOUT LCR, Temp OR 128ãOUT BaseAddr% + 1, INT(Divisors# / 256)ãOUT BaseAddr%, Divisors#ãOUT LCR, Temp AND 127ããEND SUBãDick Dennison DIAL A PHONE NUMBER QB Tidbits 10-19-91 (00:00) QB, QBasic, PDS 192 5630 DIAL.BAS ' DIAL BAS : Dial a phone number on the screenã' author .....: Dick Dennison [74270,3636] 1:272/34 914-374-3903 *hst 24 hrsã' supports ...: COM1 - COM4ã' syntax .....: DIAL portnum%ã' includes ...: Noneã' notes ......: Move the cursor with the arrow keys to the phone numberã' : Press the ']' key and move the right arrow key acrossã' : the number and press Enterã' : Uses Basic's OPEN COMx commandsã' cost .......: Free = Credit where credit dueã' : Do not use as is for commercial use - may not be resoldã' : May not be rebundled without prior written consentã' dated ......: 10/19/91ã' credits ....: Thanks to Mike Welch for CLIPMSG, and Pete Petrakis for his ã' : notes on Com Port swapping.ããDECLARE SUB Hangup (Port%)ãDECLARE SUB Getnum (row%, Col%, markit%, Port%)ãDECLARE SUB Setup (Port%)ããCOLOR 0, 7ãLOCATE 25, 1ãPRINT " Move the cursor to the beginning of the phone number and press Space ";ãLOCATE 10, 1ãIF VAL(COMMAND$) < 1 OR VAL(COMMAND$) > 4 THEN 'Get the portnum%ã PRINT "Port number must be on command line"ã ENDãELSE Port% = VAL(COMMAND$)ãEND IFã ã 'Setup some special key functionsãCR$ = CHR$(13)ãNul$ = CHR$(0)ãArrowLt$ = Nul$ + CHR$(75)ãArrowRt$ = Nul$ + CHR$(77)ãArrowUp$ = Nul$ + CHR$(72)ãArrowDn$ = Nul$ + CHR$(80)ãEndKey$ = Nul$ + CHR$(79)ãEsc$ = CHR$(27)ãHome$ = Nul$ + CHR$(71)ãSpaceBar$ = CHR$(32)ã 'Save vectors at bios Addresses for Com1-Com2ã OldPort1H = PEEK(&H400)ã OldPort1L = PEEK(&H401)ã OldPort2H = PEEK(&H402)ã OldPort2L = PEEK(&H403)ãã'Move cursor aroundã'==================================================================ãDO 'This section lets the user moveã In$ = INKEY$ 'move the cursor around on the screenã SELECT CASE In$ 'to the beginning of the phone numberã CASE CR$ã IF markit% THEN 'A CR signals the end of the highlightã row% = CSRLINã Col% = POS(0) - count%ã EXIT DOã END IFã CASE Esc$ 'ENDã ENDã CASE Home$ 'Goto the beginning of the lineã LOCATE , 1ã CASE EndKey$ 'Goto the end of the lineã LOCATE , 80ã CASE ArrowUp$ 'UpArrowã x% = CSRLINã IF x% > 1 THEN LOCATE x% - 1ã CASE ArrowDn$ 'DownArrowã x% = CSRLINã IF x% < 25 THEN LOCATE x% + 1ã CASE ArrowLt$ 'LeftArrowã IF POS(0) > 1 THEN LOCATE , POS(0) - 1ã IF markit% THEN count% = count% - 1 'If markit% then ' ' was pressedã CASE ArrowRt$ 'RightArrowã ã IF markit% THENã count% = count% + 1 'If markit% then ' ' was pressedã row% = CSRLIN: Col% = POS(0)ã a% = SCREEN(row%, Col%)ã PRINT CHR$(a%);ã ELSEã IF POS(0) < 80 THEN LOCATE , POS(0) + 1ã END IFã CASE SpaceBar$ã IF markit% THENã count% = count% + 1 'If markit% then ' ' was pressedã row% = CSRLIN: Col% = POS(0)ã a% = SCREEN(row%, Col%)ã PRINT CHR$(a%);ã ELSEã BEEPã markit% = -1 'Flag set for marking numberã END IFã END SELECTã LOCATE , , 1 'Keep cursor flashingãLOOPã'======================================================================ãã 'Get the phone number off the screenãGetnum row%, Col%, count%, Port%ãã 'Restore old vectorsãCLOSE 1ã DEF SEG = 0ã POKE &H400, OldPort1Hã POKE &H401, OldPort1Lã POKE &H402, OldPort2Hã POKE &H403, OldPort2Lã DEF SEGãENDããSUB Getnum (row%, Col%, markit%, Port%)ãIF row% < 1 THEN row% = 1: IF Col% < 1 THEN Col% = 1ãLOCATE row%, Col%ãFOR x% = 0 TO markit% 'Read the phone number off the screenã a% = SCREEN(row%, Col% + x%)ã Dialstr$ = Dialstr$ + CHR$(a%)ãNEXT x%ãLOCATE 23, 25ãPRINT "Dialing : "; Dialstr$;ãLOCATE 25, 1ãPRINT " Pickup handset and then press space or ESC phone rings ";ãCOLOR 7, 0ããSetup Port%ãPRINT #1, "ATM1DT" + Dialstr$ 'Dial the numbarããDOã b$ = INKEY$ã IF b$ = " " THENã Hangup Port%ã EXIT DOã END IFã IF b$ = CHR$(27) THENã Hangup Port%ã EXIT DOã END IFãLOOPããEND SUBããSUB Hangup (Port%)ããPRINT "...Disconnecting 1";ãSELECT CASE Port% 'Drop DTRã CASE 1ã OUT &H3FC, (INP(&H3FC) AND 252) 'com1ã CASE 2ã OUT &H2FC, (INP(&H2FC) AND 252) 'com2ã CASE 3ã OUT &H3FC, (INP(&H3FC) AND 252) 'com3ã CASE 4ã OUT &H2FC, (INP(&H2FC) AND 252) 'com4ãEND SELECTã PRINT "...2...";ã PRINT #1, "+++"; 'Switch to modem command modeã SLEEP 1ã PRINT #1, "ATH" 'Send hangup commandã PRINT "...CLICK";ããEND SUBããSUB Setup (Port%)ã'Sets up the comport by swapping the address fo com4 with com2 andã'com3 with com1 if necessaryãDEF SEG = 0ã POKE &H400, &HF8ã POKE &H401, 3ã POKE &H402, &HF8ã POKE &H403, 2ããSELECT CASE Port%ã CASE 1ã Start$ = "COM1:2400,N,8,1,DS0"ã CASE 2ã Start$ = "COM2:2400,N,8,1,DS0"ã CASE 3ã POKE &H400, &HE8 'For com1 to com3ã POKE &H401, &H3ã Start$ = "COM1:2400,N,8,1,DS0"ã CASE 4ã POKE &H402, &HE8 'For com2 to com4ã POKE &H403, &H2ã Start$ = "COM2:2400,N,8,1,DS0"ãEND SELECTãDEF SEGãããOPEN Start$ FOR RANDOM AS 1ããEND SUBããCarl Gorringe IRQ # OF TCP/IP DRIVER PACKET FidoNet QUIK_BAS Echo 05-29-96 (16:15) QB, QBasic, PDS 81 2502 TCP.BAS '>I've been working on a program a game that can be played across a modem linã'>and alot of my freinds seem to like it and have ased that I try to make inã'>work on a IPX network using ethiernet card. The code to make it three playeã'>would be easy to do, but I haven't a clue how to send packets throught aã'>network. Does anyone know any books, liberies, source code, that deals withã'>programs working across networks ?ãã'Isn't IPX in some ways similar to the TCP/IP Internet protocal?ã'Well, I wish I could help with some code to send packets of data, butã'I haven't gotten around to figuring it out yet. What I DO have is someã'code to detect which IRQ number a Packet Driver is loaded on. (A Packetã'Driver is a TSR which helps in sending packets of data over networks.)ã'Maybe you can find a use for it!ãã'-------------------------------ã' TCP1.BASã'-------------------------------ã' (c) Carl Gorringe 1/14/96ã' Released to the PUBLIC DOMAINãã' This is used to detect a PC/TCP Packet DriverããDECLARE FUNCTION TCP.GetIRQ% ()ã'------------------------------------------------------------ãCLSãNum% = TCP.GetIRQ%ããPRINTãPRINTãPRINT "IRQ ="; Num%; " ("; HEX$(Num%); " hex)"ããENDããFUNCTION TCP.GetIRQ%ãã' (c) Carl Gorringe 1/14/96 << v1.0 >>ã'--------------------------------------ã' Returns the IRQ number that theã' TCP/IP packet driver resides.ã' Returns 0 if driver not loaded.ã'--------------------------------------ã'<< Done - Tested OK >>ããRetNum% = 0ãFOR IRQ% = &H60 TO &H80ãã VectorOff% = IRQ% * 4 '<-- Point to IRQ # in Interupt Vector Tableãã DEF SEG = 0ã CodeSeg& = PEEK(VectorOff% + 3) * 256& + PEEK(VectorOff% + 2)ã CodeOff& = PEEK(VectorOff% + 1) * 256& + PEEK(VectorOff% + 0)ãã DEF SEG = CodeSeg&ã Char1% = PEEK(CodeOff& + 3)ã Char2% = PEEK(CodeOff& + 4)ã Char3% = PEEK(CodeOff& + 5)ã Char4% = PEEK(CodeOff& + 6)ã Char5% = PEEK(CodeOff& + 7)ã Char6% = PEEK(CodeOff& + 8)ã Char7% = PEEK(CodeOff& + 9)ã Char8% = PEEK(CodeOff& + 10)ã Char9% = PEEK(CodeOff& + 11)ãã DEF SEGãã ProgID$ = CHR$(Char1%) + CHR$(Char2%) + CHR$(Char3%)ã ProgID$ = ProgID$ + CHR$(Char4%) + CHR$(Char5%) + CHR$(Char6%)ã ProgID$ = ProgID$ + CHR$(Char7%) + CHR$(Char8%)ãã 'PRINT ProgID$ '*** Test ***ãã IF ProgID$ = "PKT DRVR" AND Char9% = 0 THENã RetNum% = IRQ%ã EXIT FORã END IFããNEXT IRQ%ããTCP.GetIRQ% = RetNum%ããEND FUNCTIONãRobert Fortune ACCESSING COM PORT VIA INT 14 FidoNet QUIK_BAS Echo 08-26-96 (11:39) QB, PDS 239 10367 BIOSCOM.BAS '-> Sorry, but that's the way QuickBasic does it. You have to useã'-> OPEN/CLOSE to read/write to files as well as COMPORTS.ãã'> Actually, I found this in a help file:ãã'>INARY%(AX) = &H3C00 ' DOS function to create a file.ã'>INARY% ' DOS attribute for created file.ãã'> It appears that you can use Interrupts to work with files (andã'>probably devices such as commports). I bet someone here could use the aboveã'>(or they might not even need it) to create their own OPEN/CLOSE SUBs andã'>other SUBs to work with the files such as writing to, reading from, andã'>getting information like LOF and EOF.ãã' Yes you can. Here is some play code I've fiddled around with. It isn'tã' error-proof but it does demonstrate using BIOS Int 14h to access a comã' port. You would use similar code to access a FOSSIL driver (BNU, X00...)ã' The demo code doesn't do anything but reset\init modem, dial out andã' then hang up. It does show how to use interrupts to access a com port.ãã' --------- CUT HERE -------------------- CUT HERE ---------------------------ãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM * BIOSCOM.BAS 8/26/1996 *ãREM * Demo QB code to access a serial port via BIOS INT 14h using *ãREM * QB\PDS. YOU MUST start QB\PDS with the /L command line switch to *ãREM * allow QB to call BIOS interrupt 14H as in: QB BIOSCOM /L *ãREM * *ãREM * Maximum baud rate BIOS Int 14H reliably supports is 9600 BPS. *ãREM * This demo program uses 9600 BPS on COM 2 with NO parity, one Stop *ãREM * Bit and eight Data Bits. Modify as needed. - RAF *ãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãDEFINT A-Z ' All untyped variables default to type integerã'$INCLUDE: 'REGTYPE.BI'ããDECLARE SUB InitPort (PortNum%, BaudRate%)ãDECLARE SUB GetStatus ()ãDECLARE SUB Get1Byte (Byte$)ãDECLARE SUB GetStr (Text$)ãDECLARE SUB Send1Byte (Byte$)ãDECLARE SUB SendStr (Text$)ãDECLARE FUNCTION Dec2Bin$ (b%) ' Useful function for determining com parmsããDIM SHARED Registers AS RegTypeãDIM SHARED ComPort%, BaudRate%, Parity%, StopBits%, DataBits%ããREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM * Example QB code to test BIOS INT 14H to access a serial port *ãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ããComPort% = 1 ' zero-based so 1 is actually com 2 (com 1 would be 0)ãBaudRate% = 9600 ' 9600 BPS (max that BIOS INT 14H reliably supports)ãParity% = 16 ' use NO parity 00010000ãStopBits% = 0 ' use one Stop bit 00000x00ãDataBits% = 3 ' use eight Data bits 00000011ããREM * * * * * * * * * * * * MAIN PROGRAM CODE * * * * * * * * * * * * * * *ãCR$ = CHR$(13) ' ASCII code for carriage return\ENTERãESC$ = CHR$(27) ' ASCII code the the ESC keyãCLSãPRINTãCALL InitPort(ComPort%, BaudRate%)ãPRINTãPRINT "Testing BIOS Interrupt 14H in QB\PDS to access a serial port."ãPRINTãPRINT "Communications Port:" + STR$(ComPort% + 1)ãPRINT "BPS Rate: " + STR$(BaudRate%)ãPRINT "Resetting com port "; LTRIM$(STR$(ComPort% + 1)); "...";ããByteStr$ = ""ãText$ = "ATZ" + CR$ ' initialize\reset modem to use modem profile 0ãCALL SendStr(Text$)ããREM Wait for an OK from the modem that it received our modemãREM reset command.ãDOã CALL GetStr(Text$)ãLOOP UNTIL INSTR(Text$, "OK") ' u might wanna check for error(s) hereãPRINT "done!"ãPRINTãPRINTããREM Dial a number. Best to dial your own phone number here which willãREM ensure a BUSY signal and not annoy anyone.ããLINE INPUT "Enter your telephone number: "; Number$ãIF Number$ = "" THEN Number$ = "555-1212" ' Information please? ãPRINTãText$ = "ATDT" + Number$ + CR$ ' ATDT touch tone line (ATDP for pulse line)ãCALL SendStr(Text$) ' And dial outããREM Wait for a BUSY or CONNECT from the modem to be sure that the modemãREM received our DIAL command properly. In a real world program you wouldãREM need to check for other conditions like NO CARRIER, etc...ãPRINT "Press ESC key to cancel"ãPRINTãByteStr$ = ""ãDOã CALL Get1Byte(Byte$)ã ByteStr$ = ByteStr$ + Byte$ã PRINT Byte$;ã AnyKey$ = INKEY$ã IF AnyKey$ <> "" THEN EXIT DOãLOOP UNTIL INSTR(ByteStr$, "BUSY") OR INSTR(ByteStr$, "CONNECT")ãPRINTãPRINT "Hanging up...";ãText$ = "ATH0" + CR$ ' force the modem to hang upãCALL SendStr(Text$)ãPRINT "All done Bubba!"ãEND ' The End.ãREM * * * * * * * * * * * * * THE END * * * * * * * * * * * * * * * * * * *ããREM * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Converts a decimal number into a binary string.ãREM Called with: b% which is an integer variableãREM Returns: binary value of integer b%ãREM * * * * * * * * * * * * * * * * * * * * * * * * *ãFUNCTION Dec2Bin$ (b%) STATICãTemp$ = ""ãH$ = HEX$(b%)ãFOR I% = 1 TO LEN(H$)ã Digit% = INSTR("0123456789ABCDEF", MID$(H$, I%, 1)) - 1ã IF Digit% < 0 THENã Temp$ = ""ã EXIT FORã END IFã J% = 8ã K% = 4ã DO ' convert from hexadecimal to binaryã Temp$ = Temp$ + RIGHT$(STR$((Digit% \ J%) MOD 2), 1)ã J% = J% - (J% \ 2)ã K% = K% - 1ã IF K% = 0 THEN EXIT DOã LOOP WHILE J%ãNEXT I%ãDec2Bin$ = Temp$ãEND FUNCTIONãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Receives one byte from active port via BIOS INT 14H - Function 2ãREM Called with: AH = 2ãREM DX = serial port 0 to 3 (zero-based)ãREM Returns: AH = Line StatusãREM AL = Byte recievedãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãSUB Get1Byte (Byte$)ã PortFunc% = 2 ' Int 14H Function 2 = Read Char from portã AL% = 0 ' zero-out, unused with this functionã Registers.AX = AL% + (256 * PortFunc%)ã Registers.DX = ComPort% ' com port (zero-based, com 1 is zero, etc...)ã CALL INTERRUPT(&H14, Registers, Registers)ã Byte$ = CHR$(Registers.AX AND 255) ' return string of ASCII char rec'dãEND SUBããREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Reads line and modem status of the specified com portãREM Called with: AH = 3 ' function 3 (Get status) of INT 14HãREM DX = serial port 0 to 3 (zero-based)ãREM Returns: AH = Line StatusãREM AL = Modem StatusãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãSUB GetStatusã AL% = 0 ' zero out AL register halfã AH% = 3 ' Int 14H Function 3 = Read line and modem statusã Registers.AX = AL% + (256 * AH%)ã Registers.DX = ComPort% ' zero based active com port numberã CALL INTERRUPT(&H14, Registers, Registers)ã LineStat% = Registers.AX \ 256 ' extract AH from AX registerã ModemStat% = Registers.AX AND 255 ' extract AL from AX registerãEND SUBããREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Gets a string from the active com port one byte at a time usingãREM INT 14H's Get Byte function (2). *See Get1Byte SUBãREM Example: CALL GetStr(Text$)ãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãSUB GetStr (Text$)ã DOã CALL Get1Byte(Byte$)ã Text$ = Text$ + Byte$ã LOOP WHILE Byte$ <> CHR$(13) ' loop till a carriage return is rec'dãEND SUBããREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Opens and initializes the com port via BIOS INT 14h (Function 0).ãREM Registers set before calling:ãREM AH = INT 14H function we want to invoke ( 0 = initialize port)ãREM AL = Serial port initialization values (Baud, Parity...)ãREM DX = com port number (zero based, 0 is com 1, 1 is com 2...)ãREM Returns: AH = Line StatusãREM AL = Modem StatusãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãSUB InitPort (ComPort%, BaudRate%)ã SELECT CASE BaudRate% ' max baud via BIOS INT 14H is 9600 BPSã CASE 9600ã BaudVal% = 128 + 64 + 32 ' (224) = binary 11100000ã CASE 2400ã BaudVal% = 128 + 32 ' (160) = binary 10100000ã CASE 1200ã BaudVal% = 128 ' (128) = binary 10000000ã CASE 300ã BaudVal% = 64 ' (64) = binary 01000000ã END SELECTã ComParms% = BaudVal% + Parity% + StopBits% + DataBits%ã PortFunc% = 0 ' Function 0 (of Int 14H) which is init portã Registers.AX = ComParms% + (256 * PortFunc%)ã Registers.DX = ComPort% ' active com port to init (zero-based)ã CALL INTERRUPT(&H14, Registers, Registers) ' call the interruptãEND SUBããREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Sends one byte to the specified serial port (zero based ComPort) via -ãREM Function 1 of BIOS INT 14HãREM Called with: AH = 1ãREM AL = ASCII value of the byte to sendãREM DX = Serial port 0 to 3 (zero based; use 0 for port 1...)ãREM Returns: AH = Line StatusãREM AL = unchanged (the byte that was sent)ãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãSUB Send1Byte (Byte$)ã PortFunc% = 1 ' INT 14H Function 1 = write char to port goes into AHã Byte% = ASC(Byte$) ' ASCII value of byte which goes into ALã Registers.AX = Byte% + (256 * PortFunc%)ã Registers.DX = ComPort% ' com port number (zero-based)ã CALL INTERRUPT(&H14, Registers, Registers)ãEND SUBããREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãREM Sends a string to the active com port one byte at a time usingãREM INT 14H's Send Byte function (1).ãREM Called with: Text$ which is the string to send out the com port.ãREM Example: CALL SendStr(Text$)ãREMãREM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *ãSUB SendStr (Text$)ã FOR I% = 1 TO LEN(Text$)ã OneByte$ = MID$(Text$, I%, 1)ã CALL Send1Byte(OneByte$)ã NEXT I%ãEND SUBã' --------- CUT HERE -------------------- CUT HERE ---------------------------ãErik Bruggema REMOTE ACCESS UTILITIES immsstok@worldaccess.nl 08-28-96 (18:27) QB, QBasic, PDS 77 5021 RA_UTILS.BASDEFINT A-Z:DIM SHARED K,S,B&,Z&:V1 'Created by PostIt! 7.2ãSUB V1:OPEN "O",1,"RA_UTILS.ZIP",4^6:Z&=3487:?STRING$(50,177);ãU"%up()%9%%%I-%K'mAF8b1Cb6'7%%#-%%%1%%%%qf%xyhf%qqSg7fx&y1r^jUa95ãU"lC)NGoP^*yRS5sCtz14__QAa(6G?.FJ2U[ZCia/aFxc7wEB-[)w;o&tBqNFGg6sãU"d5Xr8OmVQmnv=mUu%bG^)OuG+N1.I7]3;2_KP>Ur-uW*;p/Vhjx;K*3)t'm&-M?ãU"Ej[V$s#e/mi+/j1ma2WCt#ovoEF98R=eb9)2cI+5^G(lQ7cCZ(Zn8V9\TT3.q;8ãU"#3r#[]/%f8Odmse0D5L^M;m+w*H]RD;$+s#mA8+yC*F0o\M1Z0'bbj1>I]MDm#iãU"Fg9#ifJo8[&4EGmcE700LxYBr:0bbEis?2^DH<.c[tãU"2oEtB#PuwwP5nFaaBoi:55hPJGArLckj0A4&E56IGY4C&QRbwh[$BJsAQ;0QU)1ãU"T,SATHp9Y'bpNrmA3-'M<'$U+%D0/[VJN&LK6iF;S<^e:7)o8c%D/UVqO_(F;7wãU"OSDjBnoS^j?Vr7$V]VhL)V]1iQrI\pK3$vh-pi5+j6*qB,)FOAZ#_ru\B9PuqOKãU"Q]qbMQiN+Ia(r+q7m8mxTcC$6IB6S7DA'/>R2KbI7Z+'Jp9J=cE]th(v&Tc&)qbãU";Fgu59rS&[4rtyoW#pc_l8?n&X[F4etuk/(AHVJTcUdU.Ph>s-?_HAu(RN3_,3b3>N9NaO.aB2%(Pa3#v\6s&=,HhãU"J+a6IP_8nvPn4zn'S'h$B&L&(=1xD]kZ&.%%A'%%%0%#%%x(%xnsk%tSgf^xDvJ+oZny[.)4MkST2?VxpB;FDn=QD7rFPãU">se3C4v4*HcUc&VZg.4Jl3.UVc1u:M(nR+*5HC:i$9]2&.\vF-DwD;l^2Y+7ToPãU"0]o=yg#Gv/27^4#sei*x5]186/92vBV#z]61%mh.7K5:^<5:_GQ8xx:N_kkdMith/p]y[13ToWfok*WdRD48D26$pQ24##$lãU"7Mmm+$FAIlnv0;oaU[KR3kpV9l+W=G;tq4o6l&M)uydEJF$,dBKyrSUU5OX$BqDs;dm.LYi8.[SO3ilja,l9roeTUbZ4<-*HR\_SLQ)UZKNa$jYLrM=g&sV5RaqlRGãU"+9]TIYpqGa3X%ZYRHPDV-&(]48,mkuLj+V.4WcH4b7t5f3SAPD:Ye)AAOQ++ZaQHGDH0ãU"A?)A3*;((HZQAsF.N[OqHgNHC\?((Hxx:ãU"$_\+,G)VYFK71V#5\B2VHa5l2*&pF;=\1Hxg7(xIy.>Yd++r.fx,#IyB(Yd,rBnãU"fxPBIyF0_y_U3h2y_Y1OsuQOD[_9a'kF'$Y9_j^F.ZSNV1dUko7$SZqSWy_pMe$ãU"7;;ZQHtUb:B,#=vGF$0Z3W8Qji,za<#t=eE4D?>qK./GqY-g5T$Gf3>[5Yha+1:ãU"WA>iZa1;V41Y-SQDi7UAvXaeHZL1.G6qQ2.mXU_,2AW'Si6a[MO4[7K?m6[&ãU"'+3=KB+S4m(C<2soBCT;Y['mrqY5)KA=ZSH+A$ZG[-m'tZ5/AhGZS1NAjZ[T3m1ãU"Zu55AQqZS7AitZ[9dm=[5H;A][YS=A*.Q=Z*>0*YRU;[>QE)'=5IS\Cx5xD*QC=ãU"Z*0**oRcTv#2UiMZOiXBgkqAwSv>38z&17bD>5%Qh51Rb>>?)'UhU*mMy1;f41)ãU"^h>k>3i'Ul+UmsyL1n4k7S.x%%up()%9%%%7-%Sg##Fy-(,iI%%%%l%%%%0%%%%ãU"yn%rjqt%lSggax\U)]IZULK.Y24M/3/5NY//1&O%kE/3'1qu9A9<*9YK+%%up(%ãU")9%%%%-%S#&CFpBSU98Ll[d2+4bãU"ki/YM&)J'zz%&'io(hf)zSLY=:nr+4,mBVwvYKfi$A^STotBg27jc#Es?uapfpk=b^^q0g,g'okcGãU"J4+vCp5twE_^$#$k9pn:,$'n4Nmd(H9;H'KK2yt',DA8j[yNde]gNJk1zx7<'flãU"8eZ(t6M\>7a9m70c7ipJ^3#c*,0NGUzd&Sfq\q+FmO/:Ot0#>v)M-$ScfInkTBgãU"5\Ei1EU_iF(p.u&+%N/oqz_d30$f)D2wZQ;xomrugNvWl[J^m*;XDTPqZ7cd]U,ãU"=%U/GT,M?nd5,[K%mXdNxHHY1eChBo)^Eqr)R_5V?78Zj\Rf16Xth)49CKE?:5bãU",h[fJhc1%zMq8'XRiU&+SS$1OtC'\W6p\:wOeA.A[[A_YVVI,eO_SãU"-:8Z;PK^l/d0j.^CcpTdcw7CJfU59&z#&5k[\TG4v#^/2tH>3tT/lLXof8,TX0jãU"s+k6hk6KD>yxGfP?Ndq:NN$wH$2olB5^/P$>xa?a#3$=+cUãU"&o2)B^'130tH7J+TP^tYGx/BfXc,.[-J*6oLh$qAA7%ii?DUfOnj$J(khHrn9$EãU"YX1QoGRKa7-vWdu%p()9%%%%-+%Tg#UFx'),33%%+%O%%%%/%%%%zxj%wtsS#ggãU"x29iRKx=-GDTYNZ%kZ&%(%A'%%%0%%%%%%%%%&%E%%%%M%(%%x&(xnãU"s%ktSg%fxup%&'9%%9%%%%-%X-.6F9a%,eG%.%%w%%%%0%%%%%%%%%&%%E%%%&UãU")%%(x(xn%sktS%ggxu%p&'9%%9%%#%-%o&'AFzhuL1s['%%4%:%%0%%%%%%%%%&ãU"%%E%%+%J)%%%ynr%jqtl%Sgfx%up&'%9%9%%%%-%'Sg#FCy-,i%I%%%%l%%%%0%ãU"%%%%%%%%&%E%7%%m,%%%yn%rjqt%lSgg%xup&%'9%9%%%%-%%S&C:Fp "ok" THEN PRINT "MODEM ERROR": ENDãDOã Modemin$ = "": IF NOT EOF(1) THEN Modemin$ = INPUT$(1, #1)ã ansi Modemin$ã IF ANSIDetect$ <> "" THEN PRINT #1, ANSIDetect$: ANSIDetect$ = ""ã kb$ = INKEY$ã IF kb$ <> "" THENã k% = ASC(kb$)ã IF k% = 0 THENã k% = ASC(MID$(kb$, 2))ã SELECT CASE k%ã CASE 45: CLOSE #1: ENDã CASE 59 TO 68: k% = k% - 58ã kb$ = FKEYS(k%)ã DO: e% = INSTR(UCASE$(kb$), "^M")ã IF e% > 0 THEN MID$(kb$, e%) = MID$(kb$, e% + 1)ã IF e% > 0 THEN kb$ = LEFT$(kb$, LEN(kb$) - 1)ã IF e% > 0 THEN MID$(kb$, e%, 1) = CHR$(13)ã LOOP WHILE e% > 0ã IF FKEYS(k%) = "" THEN k% = 0ã CASE 133, 134: k% = k% = 122ã kb$ = FKEYS(k%)ã IF FKEYS(k%) = "" THEN k% = 0ã CASE 37: QuikCFG FKEYS(): k% = 0ã CASE ELSE: k% = 0ã END SELECTã END IF: IF k% > 0 THEN PRINT #1, kb$;ã END IFãLOOP: CLOSE #1: ENDãBooBoo:ã FError$ = STR$(ERR): RESUME NEXTãDEFINT A-ZãSUB ansi (A$)ãDEFINT A-Z: DEF SEG = &HB800ãSTATIC W, e, L, C, O, M, F, B, V, e$: SHARED ANSIDetect$ãIF W < 99 THEN W = 100: C = 0: F = 7: B = 0: A = 0: M = F + 16 * BãIF A$ = "" THEN LOCATE C \ 80 + 1, C MOD 80 + 1, 1: EXIT SUBãIF e <> 27 THENã IF ASC(A$) <> 27 THEN GOSUB CHRout: ELSE e = 27: e$ = A$ã EXIT SUBãEND IFãIF O <> 27 AND ASC(A$) = 34 THEN O = e: EXIT SUBãIF O = 27 THENã IF ASC(A$) = 34 THEN O = 0ã EXIT SUBãEND IF: e$ = e$ + A$ãIF LEN(e$) = 2 AND A$ <> "[" THEN e = 0: e$ = "": EXIT SUBãS = INSTR("HfABCDsuJKmhlpn", A$)ãSELECT CASE Sã CASE 0: EXIT SUBã CASE 1: GOSUB CursorAã CASE 2: GOSUB CursorAã CASE 3: L = -1: GOSUB CursorLã CASE 4: L = 1: GOSUB CursorLã CASE 5: L = 1: GOSUB CursorCã CASE 6: L = -1: GOSUB CursorCã CASE 7: V = Cã CASE 8: C = Vã CASE 9: COLOR F, B: CLS : C = 0ã CASE 10: FOR L = C TO C + 79 - (C MOD 80)ã POKE L * 2, 32: POKE L * 2 + 1, M: NEXTã CASE 11: GOSUB Colorzã CASE 15: A$ = CHR$(27) + "[" + MID$(STR$(C \ 80 + 1), 2) + ";"ã ANSIDetect$ = A$ + MID$(STR$((C MOD 80) + 1), 2) + "R"ãEND SELECT: e = 0: e$ = "": EXIT SUBãCursorA: L = VAL(MID$(e$, INSTR(e$, "[") + 1))ã C = VAL(MID$(e$, INSTR(e$, ";") + 1))ã IF C > 0 THEN C = (C - 1): IF C > 79 THEN C = 79ã IF L > 0 THEN L = (L - 1): IF L > 24 THEN L = 24ã C = L * 80 + C: RETURNãCursorL: p = VAL(MID$(e$, INSTR(e$, "[") + 1))ã p = p - (p < 1): L = INT(C \ 80) + p * Lã IF L < 0 THEN L = 0: ELSE IF L > 24 THEN L = 24ã C = (C MOD 80) + L * 80: RETURNãCursorC: p = VAL(MID$(e$, INSTR(e$, "[") + 1))ã p = p - (p < 1): L = (C MOD 80) + p * L: C = INT(C \ 80) * 80ã IF L < 1 THEN L = 0: ELSE IF L > 79 THEN L = 79ã C = C + L: RETURNãColorz: e$ = MID$(e$, INSTR(e$, "[") + 1)ã DO: e = VAL(e$)ã SELECT CASE eã CASE 0: F = 15: B = 0ã CASE 1: F = F OR 8ã CASE 5: B = B OR 8ã CASE 8: F = Bã CASE 30 TO 37: p = e - 29ã e = ASC(MID$("@DBFAECG", p)) AND 7: F = (F AND 248) + eã CASE 40 TO 47: p = e - 39ã e = ASC(MID$("@DBFAECG", p)) AND 7: B = (B AND 248) + eã END SELECT: p = INSTR(e$, ";"): e$ = MID$(e$, p + 1)ã LOOP WHILE p > 0: M = F + 16 * B: RETURNãCHRout: p = ASC(A$)ã IF p = 7 THEN FOR t% = 800 TO 1111 STEP 20: SOUND t%, .1: NEXT: RETURNã IF p = 8 THENã IF (C MOD 80) > 0 THENã FOR t% = C * 2 TO (C \ 80) * 160 + 159ã POKE t% - 2, PEEK(t%)ã NEXT: C = C - 1ã END IF: RETURNã END IFã IF p = 13 THEN C = C - (C MOD 80): RETURNã IF p = 10 THEN C = C + 80ã IF p <> 10 THEN POKE C * 2, p: POKE C * 2 + 1, M: C = C + 1ã IF C >= 2000 THENã C = C - 80: LOCATE 30, 80: PRINTã DIM PK%(2): PK%(0) = 32: PK%(1) = Mã FOR L = 3680 TO 3839ã POKE L, PEEK(L + 160): POKE L + 160, PK%(L AND 1)ã NEXTã END IF: RETURNãEND SUBããSUB QuikCFG (d() AS STRING)ã SHARED port%ã DIM buf(4000) AS STRING * 1: DEF SEG = &HB800: F$ = SPACE$(80)ã FOR t% = 0 TO 3999: buf(t%) = CHR$(PEEK(t%)): NEXTã csr% = LEN(d(0)) + 1: macro% = 0: COLOR 10, 0: CLS : COLOR 14, 4ã PRINT " COM "; : COLOR 10, 0: PRINT LEFT$(d(0) + F$, 75);ã FOR t% = 1 TO 12ã COLOR 14, 4: LOCATE t% + 1, 1: PRINT " F"; RIGHT$(STR$(t%), 2); " ";ã COLOR 10, 0: PRINT LEFT$(d(t%) + F$, 75); : NEXTã PRINT : PRINT : PRINT "RETURN exits: ALT/S saves"ã DO: LOCATE macro% + 1, 6: COLOR 15, 1: PRINT LEFT$(d(macro%) + F$, 75);ã LOCATE , csr% + 5: DO: k$ = INKEY$: LOOP WHILE k$ = ""ã k% = ASC(k$): IF k% = 0 THEN k% = -ASC(MID$(k$, 2))ã SELECT CASE k%ã CASE 8ã IF csr% > 1 THENã csr% = csr% - 1ã MID$(d(macro%), csr%) = MID$(d(macro%), csr% + 1)ã d(macro%) = LEFT$(d(macro%), LEN(d(macro%)) - 1)ã ELSE SOUND 999, .7ã END IFã CASE 13: FOR t% = 0 TO 3999: POKE t%, ASC(buf(t%)): NEXT: EXIT SUBã CASE 32 TO 255ã L$ = LEFT$(d(macro%), csr% - 1): r$ = MID$(d(macro%), csr%)ã d(macro%) = LEFT$(L$ + k$ + r$, 70)ã IF csr% < 75 THEN csr% = csr% + 1: ELSE SOUND 999, .7ã CASE -31ã FError$ = "ok": OPEN "quikterm.cfg" FOR OUTPUT AS #2ã IF FError$ = "ok" THENã FOR t% = 0 TO 13: PRINT #2, d(t%): NEXT: port% = VAL(d(0))ã END IF: CLOSE 2ã CASE -71: csr% = 1ã CASE -72ã IF macro% > 0 THENã LOCATE macro% + 1, 6: COLOR 10, 0ã PRINT LEFT$(d(macro%) + F$, 75);ã macro% = macro% - 1: csr% = LEN(d(macro%)) + 1ã ELSE SOUND 999, .7ã END IFã CASE -75ã IF csr% > 1 THEN csr% = csr% - 1: ELSE SOUND 999, .7ã CASE -77ã IF csr% < 70 THEN csr% = csr% + 1: ELSE SOUND 999, .7ã CASE -79: csr% = LEN(d(macro%)) + 1ã CASE -80ã IF macro% < 12 THENã LOCATE macro% + 1, 6: COLOR 10, 0ã PRINT LEFT$(d(macro%) + F$, 75);ã macro% = macro% + 1: csr% = LEN(d(macro%)) + 1ã ELSE SOUND 999, .7ã END IFã CASE -83ã IF LEN(d(macro%)) >= csr% THENã MID$(d(macro%), csr%) = MID$(d(macro%), csr% + 1)ã d(macro%) = LEFT$(d(macro%), LEN(d(macro%)) - 1)ã ELSE SOUND 999, .7ã END IFã END SELECTã LOOPãEND SUBã'_|_|_| end QUIKTERM.BASãBrian Mahocker PHREAK FONE ButtNuggie@aol.com 10-22-96 (18:45) QB, QBasic, PDS 48 3463 PFONE10.BAS 'Phreak Fone Ver. 1.0 By: Brian MahockerãStart:ãCLSãLET Start% = 0ãLOCATE 1, 1: COLOR 8: PRINT "P"; : COLOR 7: PRINT "H"; : COLOR 15: PRINT "R"; : COLOR 8: PRINT "e"; : COLOR 7: PRINT "a"; : COLOR 15: PRINT "K"; : COLOR 8: PRINT " "; : COLOR 7: PRINT "F"; : COLOR 15: PRINT "o"; : COLOR 8: PRINT "N"; : COLOR 7: PRINT "e"; : COLOR 15: PRINT " "; : COLOR 8: PRINT " "; : COLOR 7: PRINT "V"; : COLOR 15: PRINT "e"; : COLOR 8: PRINT "R"; : COLOR 7: PRINT "."; : COLOR 15: PRINT " "; : COLOR 8: PRINT "1"; : COLOR 7: PRINT "."; : COLOR 15: PRINT "0"; : COLOR 8: PRINT " "; : COLOR 7: PRINT "B"; : COLOR 15: PRINT "y"; : COLOR 8: PRINT ":"; : COLOR 7: PRINT " "; : COLOR 15: PRINT "B"; : COLOR 8: PRINT "R"; : COLOR 7: PRINT "i"; : COLOR 15: PRINT "a"; : COLOR 8: PRINT "n"; : COLOR 7: PRINT " "; : COLOR 15: COLOR 8: PRINT "M"; : COLOR 7: PRINT "a"; : COLOR 15: PRINT "H"; : COLOR 8: PRINT "o"; : COLOR 7: PRINT "C"; : COLOR 15: PRINT "K"; : COLOR 8: PRINT "e"; : COLOR 7: PRINT "R": COLOR 15: PRINTãINPUT "THe LoWeST NuMBeR To DiaL (No Dash) : ", LN&ãINPUT "THe HiGHeST NuMBeR To DiaL (No Dash) : ", HN&ãINPUT "PoRT NuMBeR (1/2) : ", port$ãINPUT "RePeaT? (Y/N) :", R$: IF R$ = "Y" OR R$ = "y" THEN LET Repeat% = 1: IF R$ = "N" OR R$ = "n" THEN LET Repeat% = 0:ãINPUT "aRe THeSe SeTTiNGS CoRReCT? (Y/N) : ", correct$: IF correct$ = "N" OR correct$ = "n" THEN GOTO StartãCLSãLOCATE 1, 1: COLOR 8: PRINT "P"; : COLOR 7: PRINT "H"; : COLOR 15: PRINT "R"; : COLOR 8: PRINT "e"; : COLOR 7: PRINT "a"; : COLOR 15: PRINT "K"; : COLOR 8: PRINT " "; : COLOR 7: PRINT "F"; : COLOR 15: PRINT "o"; : COLOR 8: PRINT "N"; : COLOR 7: PRINT "e"; : COLOR 15: PRINT " "; : COLOR 8: PRINT " "; : COLOR 7: PRINT "V"; : COLOR 15: PRINT "e"; : COLOR 8: PRINT "R"; : COLOR 7: PRINT "."; : COLOR 15: PRINT " "; : COLOR 8: PRINT "1"; : COLOR 7: PRINT "."; : COLOR 15: PRINT "0"; : COLOR 8: PRINT " "; : COLOR 7: PRINT "B"; : COLOR 15: PRINT "y"; : COLOR 8: PRINT ":"; : COLOR 7: PRINT " "; : COLOR 15: PRINT "B"; : COLOR 8: PRINT "R"; : COLOR 7: PRINT "i"; : COLOR 15: PRINT "a"; : COLOR 8: PRINT "n"; : COLOR 7: PRINT " "; : COLOR 15: COLOR 8: PRINT "M"; : COLOR 7: PRINT "a"; : COLOR 15: PRINT "H"; : COLOR 8: PRINT "o"; : COLOR 7: PRINT "C"; : COLOR 15: PRINT "K"; : COLOR 8: PRINT "e"; : COLOR 7: PRINT "R": COLOR 15: PRINTãLOCATE 3, 1: PRINT "CuRReNT FoNe NuMBeR :"ãLOCATE 4, 1: PRINT "TiMe LeFT FoR CuRReNT FoNe NuMBeR :"ãLOCATE 5, 1: PRINT "CuRReNT PoRT : "ãCOLOR 8: LOCATE 5, 16: PRINT port$ãStartDialing:ãLET PN& = LN&ãDOãCOLOR 8: LOCATE 3, 22: PRINT PN&: COLOR 15ãOPEN "COM" + port$ + ":" + "9600,N,8,1,ASC" FOR OUTPUT AS #1ãPRINT #1, "ATD" + ""; PN&; ""ãLET time% = 15ãDOãSOUND 32767, 9.1ãSOUND 32767, 9.1ãCOLOR 8: LOCATE 4, 36: PRINT time%ãLET time% = time% - 1ãLOOP UNTIL time% = -1ãSOUND 32767, 10ãPRINT #1, "+++"ãSOUND 32767, 10ãPRINT #1, "AT Z H0"ãPRINT #1, "ATH"ãSOUND 32767, 10ãCLOSE #1ãIF Repeat% = 1 AND PN& = HN& THEN GOTO StartDialingãIF Rapeat% = 0 AND PN& = HN& THEN GOTO End.ãLET PN& = PN& + 1ãLOOPãEnd.:ãPLAY "T200L50MLO4C#DD#EFF#GG#AA#B>CC#DD#EFP8."ãPLAY "T200L50MLO4C#DD#EFF#GG#AA#B>CC#DD#EFP8."ãPLAY "T200L50MLO4C#DD#EFF#GG#AA#B>CC#DD#EFP8."ãPLAY "T200L50MLO4C#DD#EFF#GG#AA#B>CC#DD#EFP8."ãPLAY "T200L50MLO4C#DD#EFF#GG#AA#B>CC#DD#EFP8."ãPLAY "T200L50MLO4C#DD#EFF#GG#AA#B>CC#DD#EFP8."ããScott Turchin BACKSPACE LOCALLY & OVER MODEM nitehawk@tscnet.com 10-29-96 (11:13) PB 127 3288 BACKSPC.BAS SUB XPRINT(Fore%,Back%,StringofData$,LF%) PUBLICã'------------No color--------------------ãIF NOT Ansi% THEN 'Don't add colors in..ã COLOR Fore%,Back%ã PRINT StringofData$;ã PRINT #1, StringofData$;ã IF LF%=1 THENã PRINTã IF Carrier(Port%) THEN PRINT #1,CRLF$ã END IFã EXIT SUBãEND IFãã'-------------color part--------------------ãESC1$=LTRIM$(CHR$(27)+"[") 'esc$ was used publicly in my program, I choseãesc1$ to eliminate problems.ãGOSUB SETCOLORSããIF Carrier(Port%) THEN Print #1, ForeColor$+StringofData$;ãIF Carrier(Port%) AND (Flash% OR Back%>0) THEN PRINT #1,CHR$(27)+"[0;30m";ã'clears flashingããIF Flash% THEN INCR Fore%,16ãCOLOR Fore%,Back%ãIF INSTR(StringofData$,CHR$(8)) THEN EXIT SUB ELSE PRINT StringofData$; 'Doãnot print the backspace...ããIF LF%=1 THENã COLOR 7,0ã PRINTã IF Carrier(Port%) THEN PRINT #1,CRLF$ãEND IFãCOLOR 7,0 'Reset it..just in caseãEXIT SUBããSETCOLORS:ãIF Fore% <= 8 THEN ESC1$=ESC1$+"0;"ãIF Fore%>8 AND Fore%<16 THEN ESC1$=ESC1$+"1;"ãIF Fore%>16 THENã Flash%=-1ã ESC1$=ESC1$+"5;"ã DECR Fore%,16ãEND IFã SELECT CASE Fore%ã CASE 0ã ForeColor$=ESC1$+"30m"ã CASE 1ã ForeColor$=ESC1$+"34m"ã CASE 2ã ForeColor$=ESC1$+"32m"ã CASE 3ã ForeColor$=ESC1$+"36m"ã CASE 4ã ForeColor$=ESC1$+"31m"ã CASE 5ã ForeColor$=ESC1$+"35m"ã CASE 6ã ForeColor$=ESC1$+"33m"ã CASE 7ã ForeColor$=ESC1$+"37m"ã CASE 8ã ForeColor$=ESC1$+"30m"ã CASE 9ã ForeColor$=ESC1$+"34m"ã CASE 10ã ForeColor$=ESC1$+"32m"ã CASE 11ã ForeColor$=ESC1$+"36m"ã CASE 12ã ForeColor$=ESC1$+"31m"ã CASE 13ã ForeColor$=ESC1$+"35m"ã CASE 14ã ForeColor$=ESC1$+"33m"ã CASE 15ã ForeColor$=ESC1$+"37m"ã CASE ELSEã Fore%=7ã END SELECTãIF Back%>0 THEN ForeColor$=LEFT$(ForeColor$,6)ã SELECT CASE Back%ã CASE 0ã 'IS ASSUMED BLACK ALREADYã CASE 1ã ForeColor$=ForeColor$+";44m"ã CASE 2ã ForeColor$=ForeColor$+";42m"ã CASE 3ã ForeColor$=ForeColor$+";46m"ã CASE 4ã ForeColor$=ForeColor$+";41m"ã CASE 5ã ForeColor$=ForeColor$+";45m"ã CASE 6ã ForeColor$=ForeColor$+";43m"ã CASE 7ã ForeColor$=ForeColor$+";47m"ã CASE ELSEã Back%=0ã END SELECTãRETURNãEND SUBããSUB BACKSPACE(I$,Fore%,Back%) PUBLICãCOLOR Fore%,Back%ãCHATX% = CSRLIN: CHATY% = POS( O )ãIF CHATY%=1 THENã PRINT " ";ã LOCATE CHATX%,CHATY%,1ãELSEãLOCATE CHATX%,CHATY%-1ãPRINT " ";ãLOCATE CHATX%,CHATY%-1ãEND IFãXPRINT Fore%,Back%,CHR$(8)+" "+CHR$(27)+"[D",0 'backspace one line, move ãforward one line remotely using ANSI escape sequence.ãIF InChat% THEN 'This backspaces a chat.log file in my chat routine..ã Y=LOF(3) 'chat.log is opened as #3...ã IF Y>2 THENã SEEK #3, Y-1ã PRINT #3," ";ã SEEK #3, Y-1ã END IFãEND IFãIF LEN(I$) THEN I$=LEFT$(I$,LEN(I$)-1) ELSE I$=NULL$ 'subtract one ãcharacter if it is a word otherwise eliminate it...ãEND SUBãJoseph L. Clark SWAP COM PORTS FidoNet QUIK_BAS Echo 11-15-96 (15:30) QB, QBasic, PDS 81 1539 SWAPCOM.BAS '> program, and also, how to re-assign the com ports so I can use com1 asã '> com3 and com2 as com4. ãã'I've got the COM swapping bit (well the one i've got!):ãã'ã' SWAPCOM.BAS - Swaps com ports and resets to normalã'ã' Author: Joseph L. Clarkã'ã'----------------------------------------------------------------------ããDECLARE SUB SwapComPorts (port1, port2)ãDECLARE SUB ResetComPorts ()ãDECLARE SUB ShowPorts ()ããCLSãResetComPortsãShowPortsãSwapComPorts 1, 3 ' Only swap 1 and 3 OR 2 and 4ã ' Make sure the lower number is first!ãShowPortsãResetComPortsãShowPortsãENDããSUB ResetComPortsãã' This routine resets all the base addresses of COM1-COM4ããDEF SEG = 0ããFOR port = 1 to 4ã byte = &H400 + (port - 1) * 2ã IF port MOD 2 = 0 THEN p2 = &H2 ELSE p2 = &H3ã IF port < 3 THEN p1 = &HF8 ELSE p1 = &HE8ã POKE byte, p1ã POKE byte + 1, p2ãNEXT portããDEF SEGããEND SUBããSUB ShowPortsãã' This routine shows the base addresses of COM1-COM4ããDEF SEG = 0ããFOR port = 1 to 4ã byte = &H400 + (port - 1) * 2ã PRINT HEX$(PEEK(byte + 1));ã PRINT HEX$(PEEK(byte))ãNEXT portãPRINTããDEF SEGããEND SUBããSUB SwapComPorts (port1, port2)ãã' Please note: this doesn't actually swap the com ports, it justã' places the base address of port2 into port1.ããDEF SEG = 0ããport = port2ãbyte = &H400 + (port - 1) * 2ãp1 = PEEK(byte)ãp2 = PEEK(byte + 1)ããport = port1ãbyte = &H400 + (port - 1) * 2ãPOKE byte, p1ãPOKE byte + 1, p2ããDEF SEGããEND SUBãMike G. Stewart DIAL-UP CHAT (CONNECT) mikegs@juno.com 04-22-97 (21:08) QB, QBasic, PDS 116 2856 CONNECTT.BAS'Connectt.bas: Dial-Up Chatã'Program written by Mike Stewartã'(C) 1997 M Stewartã'Public Domainã'I changed the program CONNECT.BAS a lot to make this program.ã'This program can be changed a lot.ã'Use it to start your own network.ã'Just include my name in the program that you write, in the credits or something.ã'Have Fun! :-)ããDECLARE SUB Keyscan ()ãDECLARE SUB Delay (td!)ãDECLARE SUB dial (Num$)ãCOMMON SHARED ModemIn$ããPRINT "Call Mike Stewart at (509) 292-8751 to Confirm Dial-Up Chat is Active."ãPRINT "Press any key to continue with Dial-Up Chat."ãSLEEPããINPUT "Is (509) 292-8751 Long Distance? ", l$ãINPUT "Do You Have Call Waiting? ", c$ãLET c$ = UCASE$(c$)ãLET l$ = UCASE$(l$)ããON ERROR GOTO HandlerãON COM(2) GOSUB GetBufãCOM(2) ONããIF l$ = "Y" AND c$ = "Y" THEN dial ("*70,1-(509)292-8751") 'phone numbers according to line settingsãIF l$ = "N" AND c$ = "Y" THEN dial ("*70,292-8751")ãIF l$ = "Y" AND c$ = "N" THEN dial ("1-(509)292-8751")ãIF l$ = "N" AND c$ = "N" THEN dial ("292-8751")ãããDOã CALL Keyscan ' You're online now. Stay in this loop forever.ãLOOPããHandler:ãRESUME NEXTããGetBuf:ãInStr$ = INPUT$(LOC(1), #1)ãã DOã BackSpace = INSTR(InStr$, CHR$(8))ã IF BackSpace THENã MID$(InStr$, BackSpace) = CHR$(29)ã END IFã LOOP WHILE BackSpaceãã DOã LineFeed = INSTR(InStr$, CHR$(10))ã IF LineFeed THENã InStr$ = LEFT$(InStr$, LineFeed - 1) + MID$(InStr$, LineFeed + 1)ã END IFã LOOP WHILE LineFeedãã ModemIn$ = RIGHT$(ModemIn$ + InStr$, 10240)ã PRINT (InStr$);ãRETURNãããSUB Delay (td!)ã TimeDelay! = (TIMER + td!) MOD 86400ã WHILE TimeDelay! > TIMER: WENDãEND SUBããSUB dial (Num$)ããOPEN "COM2:9600,N,8,1" FOR RANDOM AS #1ããCLSãLOCATE 25, 40: PRINT "ALT-X to exit.."ãLOCATE 1, 1, 1ã PRINT #1, "ATZ"ã CALL Delay(1.25)ã PRINT #1, "ATS7=45 S0=0 V1 M0" ' modem initialization stringã CALL Delay(1.25)ããDOã CALL Delay(1)ã PRINT "Dialing ....."ã PRINT #1, "atdt" + Num$ + CHR$(13)ãã TimeDelay! = TIMER + 40ãã DO UNTIL TIMER > TimeDelay!ã CALL Keyscanã test = INSTR(RIGHT$(ModemIn$, 20), "CONNECT")ã IF test THEN result = -1: EXIT DOã test = INSTR(RIGHT$(ModemIn$, 5), "BUSY")ã IF test THEN result = 0: EXIT DOã test = INSTR(RIGHT$(ModemIn$, 12), "NO DIALTONE")ã IF test THEN result = 0: CALL Delay(2): EXIT DOã test = INSTR(RIGHT$(ModemIn$, 11), "NO CARRIER")ã IF test THEN result = 0: CALL Delay(2): EXIT DOãã LOOPããLOOP UNTIL resultããFOR t = 1 TO 5 ' It answered! ring the alarm!ã SOUND 750, 2ã SOUND 550, 2ã SOUND 650, 2ã IF INKEY$ <> "" THEN EXIT FORãNEXTããEND SUBããSUB Keyscanãa$ = INKEY$ã IF a$ = CHR$(0) + CHR$(45) THEN CLOSE : ENDã PRINT #1, a$;ãEND SUBãMike G. Stewart DIAL-UP CHAT (ANSWER) mikegs@juno.com 04-22-97 (21:08) QB, QBasic, PDS 105 2353 ANSWER.BAS 'answer.bas: Dial-Up Chat Serverã'Program written by Mike Stewartã'(C) 1997 M Stewartã'Public Domainã'I changed the program CONNECT.BAS a lot to make this program.ã'This program can be changed a lot.ã'Use it to start your own network.ã'Just include my name in the program that you write, in the credits or something.ã'Have Fun! :-)ããDECLARE SUB answer ()ãDECLARE SUB Keyscan ()ãDECLARE SUB delay (td!)ãCOMMON SHARED ModemIn$ããON ERROR GOTO HandlerãON COM(2) GOSUB GetBufãCOM(2) ONããPRINT "Press Any Key to Answer Phone."ãSLEEPããanswerããDOã CALL Keyscan ' You're online now. Stay in this loop forever.ãLOOPããHandler:ãRESUME NEXTããGetBuf:ãInStr$ = INPUT$(LOC(1), #1)ãã DOã BackSpace = INSTR(InStr$, CHR$(8))ã IF BackSpace THENã MID$(InStr$, BackSpace) = CHR$(29)ã END IFã LOOP WHILE BackSpaceãã DOã LineFeed = INSTR(InStr$, CHR$(10))ã IF LineFeed THENã InStr$ = LEFT$(InStr$, LineFeed - 1) + MID$(InStr$, LineFeed + 1)ã END IFã LOOP WHILE LineFeedãã ModemIn$ = RIGHT$(ModemIn$ + InStr$, 10240)ã PRINT (InStr$);ãRETURNããSUB answerããOPEN "COM2:9600,N,8,1" FOR RANDOM AS #1ããCLSãLOCATE 25, 40: PRINT "ALT-X to exit.."ãLOCATE 1, 1, 1ã PRINT #1, "ATZ"ã CALL delay(1.25)ã PRINT #1, "ATS7=45 S0=0 V1 M0" ' modem initialization stringã CALL delay(1.25)ããDOã CALL delay(1)ã PRINT "Answering..."ã PRINT #1, "ata" + CHR$(13)ãã TimeDelay! = TIMER + 40ãã DO UNTIL TIMER > TimeDelay!ã CALL Keyscanã test = INSTR(RIGHT$(ModemIn$, 20), "CONNECT")ã IF test THEN result = -1: EXIT DOã test = INSTR(RIGHT$(ModemIn$, 5), "BUSY")ã IF test THEN result = 0: EXIT DOã test = INSTR(RIGHT$(ModemIn$, 12), "NO DIALTONE")ã IF test THEN result = 0: CALL delay(2): EXIT DOã test = INSTR(RIGHT$(ModemIn$, 11), "NO CARRIER")ã IF test THEN result = 0: CALL delay(2): EXIT DOãã LOOPããLOOP UNTIL resultããFOR t = 1 TO 5 ' It connected! ring the alarm!ã SOUND 750, 2ã SOUND 550, 2ã SOUND 650, 2ã IF INKEY$ <> "" THEN EXIT FORãNEXTããEND SUBããSUB delay (td!)ã TimeDelay! = (TIMER + td!) MOD 86400ã WHILE TimeDelay! > TIMER: WENDãEND SUBããSUB Keyscanãa$ = INKEY$ã IF a$ = CHR$(0) + CHR$(45) THEN CLOSE : ENDã PRINT #1, a$;ãEND SUBãMichael G. Stewart BBS DIAL-UP mikegs@juno.com 06-24-97 (21:26) QB, QBasic, PDS 203 5085 BBS.BAS DECLARE SUB checkname (name$)ãDECLARE SUB checkpass (name$, pass$)ãDECLARE SUB Keyscan ()ãCOMMON SHARED ModemIn$ãa% = FRE(-2)ãCLEAR , , a%ãCLSãPRINT "Press any key to activate Arrowhead BBS"ãSLEEPãOPEN "Com2:9600,N,8,1,BIN" FOR RANDOM AS #1 LEN = a%ãPRINT #1, "ATA"ãSLEEPãPRINT #1, "Arrowhead BBS"; CHR$(13)ãPRINT #1, "(C) 1997 Arrowhead Corporation, Inc."; CHR$(13)ãPRINT #1, "System Operator: Mike Stewart"; CHR$(13)ããlogin:ãPRINT #1, "Input Name: ";ãLINE INPUT #1, name$ãcheckname name$ãIF name$ <> "Guest" THENã PRINT #1, CHR$(13); "Input Password: "ã LINE INPUT #1, pass$ãEND IFãcheckpass name$, pass$ãPRINT #1, CHR$(13)ããmainmenu:ãCOLOR 14ãPRINT #1, "Welcome to the Arrowhead Bulliten Board Service!"; CHR$(13)ãCOLOR 12ãPRINT #1, "This BBS is still under construction!"; CHR$(13)ãCOLOR 3ãPRINT #1, "Thank you for your tolerence."; CHR$(13); CHR$(13)ãCOLOR 15ãPRINT #1, "Arrowhead BBS Main Menu:"; CHR$(13)ãPRINT #1, "1) Sysop Chat"; CHR$(13)ãPRINT #1, "2) E-Mail Menu"; CHR$(13)ãPRINT #1, "3) Quit"; CHR$(13)ãPRINT #1, "Your Choice: "ãINPUT #1, a$ãIF a$ = "1" THEN GOSUB sysopchatãIF a$ = "2" THEN GOSUB mailmenuãIF a$ = "3" THEN GOSUB quitãGOSUB mainmenuããmailmenu:ãCOLOR 15ãPRINT #1, CHR$(13)ãIF name$ = "Guest" THEN GOSUB mainmenuãPRINT #1, "Arrowhead BBS E-Mail Menu:"; CHR$(13)ãPRINT #1, "1) Read E-Mail"; CHR$(13)ãPRINT #1, "2) Write E-Mail"; CHR$(13)ãPRINT #1, "3) Delete E-Mail"; CHR$(13)ãPRINT #1, "4) Main Menu"; CHR$(13)ãPRINT #1, "5) Quit"; CHR$(13)ãINPUT #1, a$ãIF a$ = "1" THEN GOSUB readmailãIF a$ = "2" THEN GOSUB writemailãIF a$ = "3" THEN GOSUB clearmailãIF a$ = "4" THEN GOSUB mainmenuãIF a$ = "5" THEN GOSUB quitãGOSUB mailmenuããreadmail:ãOPEN name$ FOR INPUT AS #2ãDO WHILE NOT EOF(2)ã DO WHILE rec$ <> "End of Message"ã LINE INPUT #2, rec$ã PRINT #1, rec$; CHR$(13)ã LOOPã IF EOF(2) THEN EXIT DOã PRINT #1, "Press any key to view next message."; CHR$(13)ã INPUT #1, a$ãLOOPãPRINT #1, "End of E-Mail File"; CHR$(13)ãSLEEP 3ãCLOSE #2ãGOSUB mailmenuããwritemail:ãPRINT #1, "Users to write to:"; CHR$(13)ãPRINT #1, "1) Jerred Bell"; CHR$(13)ãPRINT #1, "2) Mike Stewart (SysOp)"; CHR$(13)ãPRINT #1, "3) Internet E-Mail (via Juno.com)"; CHR$(13)ãPRINT #1, "4) Main Menu"; CHR$(13)ãPRINT #1, "5) E-Mail Menu"; CHR$(13)ãPRINT #1, "6) Quit"; CHR$(13)ãINPUT #1, a$ãIF a$ = "1" THEN file$ = "Jerred"ãIF a$ = "2" THEN file$ = "Mike"ãIF a$ = "3" THEN file$ = "c:\juno\bbs.txt"ãIF a$ = "4" THEN GOSUB mainmenuãIF a$ = "5" THEN GOSUB mailmenuãIF a$ = "6" THEN GOSUB quitãIF VAL(a$) > 6 THEN GOSUB writemailãOPEN file$ FOR APPEND AS #2ãPRINT #2, "Arrowhead BBS E-Mail From: "; name$ãPRINT #1, "Subject"ãLINE INPUT #1, SUB$ãPRINT #1, CHR$(13)ãPRINT #2, "Subject: "; SUB$ãPRINT #2, "Date & Time: "; DATE$; "&"; TIME$ãPRINT #2, ""ãPRINT #1, "You have 20 lines to write on, press enter to go"; CHR$(13)ãPRINT #1, "to the next line. You can't go back to another line!"; CHR$(13)ãPRINT #1, "Type 'End of Message' on one line to end!"; CHR$(13)ãDOã a% = a% + 1ã IF a% = 20 THEN EXIT DOã LINE INPUT #1, mes$ã PRINT #2, mes$ã IF mes$ = "End of Message" THEN EXIT DOãLOOPãPRINT #1, "Message Sent"; CHR$(13)ãPRINT #2, ""ãCLOSE #2ãSLEEP 2ãGOSUB mailmenuããclearmail:ãPRINT #1, "All E-Mail Cleared"; CHR$(13)ãOPEN name$ FOR OUTPUT AS #2ãCLOSE #2ãSLEEP 2ãGOSUB mailmenuããsysopchat:ãCOLOR 7ãPRINT #1, "Please Wait...."; CHR$(13)ãDO UNTIL INKEY$ <> ""ã BEEPã SLEEP 1ãLOOPãPRINT #1, "Sysop Chat Active"; CHR$(13)ãPRINT #1, "Press [ESC] to Quit Sysop Chat"; CHR$(13)ãCLSãON ERROR GOTO HandlerãON COM(2) GOSUB GetBufãCOM(2) ONãDOã CALL Keyscan ' You're online now. Stay in this loop forever.ãLOOPããHandler:ãRESUME NEXTããGetBuf:ãinstr$ = INPUT$(LOC(1), #1)ãIF instr$ = CHR$(27) THEN GOSUB quitsysopchatã DOã BackSpace = INSTR(instr$, CHR$(8))ã IF BackSpace THENã MID$(instr$, BackSpace) = CHR$(29)ã END IFã LOOP WHILE BackSpaceã DOã LineFeed = INSTR(instr$, CHR$(10))ã IF LineFeed THENã instr$ = LEFT$(instr$, LineFeed - 1) + MID$(instr$, LineFeed + 1)ã END IFã LOOP WHILE LineFeedã ModemIn$ = RIGHT$(ModemIn$ + instr$, 10240)ã PRINT (instr$);ãRETURNããquitsysopchat:ãCOM(2) OFFãON ERROR GOTO 0ãGOSUB mainmenuããquit:ãPRINT #1, "Closing Connection..."ãPRINT #1, "Thank You for using Gascan BBS!"ãCLOSE #1ãENDããSUB checkname (name$)ãIF name$ = "Jerred" THEN EXIT SUBãIF name$ = "Mike" THEN EXIT SUBãIF name$ = "Guest" THEN EXIT SUBãPRINT #1, "Incorrect Login"; CHR$(13)ãPRINT #1, "Login Name";ãcheckname name$ãEND SUBããSUB checkpass (name$, pass$)ãIF name$ = "Jerred" AND pass$ = "kc7psi" THEN EXIT SUBãIF name$ = "Mike" AND pass$ = "2928751" THEN EXIT SUBãIF name$ = "Guest" THEN EXIT SUBãPRINT #1, CHR$(13); "Incorrect password"; CHR$(13)ãPRINT #1, "Input password"ãLINE INPUT #1, pass$ãcheckpass name$, pass$ããEND SUBããSUB Keyscanã a$ = INKEY$ã PRINT a$;ã PRINT #1, a$;ã IF a$ = CHR$(27) THEN CLOSE #1: ENDãEND SUBãBrian Mahocker PHREAK FONE V2.0 Kain121182@aol.com 07-03-97 (12:01) QB, QBasic, PDS 578 22226 PFONE20.BAS DECLARE SUB EndReport ()ãDECLARE SUB delay2 ()ãDECLARE SUB EndSounds ()ãDECLARE SUB NumbersLD ()ãDECLARE SUB delay (Seconds)ãDECLARE SUB CloseCom ()ãDECLARE SUB BadModem (which)ãDECLARE SUB WMS (Status)ãDECLARE SUB PrintDScreen ()ãDECLARE SUB MakeZeros ()ãDECLARE SUB SelectInput (x, y, which)ãDECLARE SUB OpenCom ()ãDECLARE SUB DialNumber ()ãDECLARE SUB CoolPrint (x, y, text$, delay, Cursor)ãDECLARE SUB Inputs ()ãDECLARE FUNCTION TinyInput$ (x%, y%, Original$, Length%, AutoCap%, Allowed$, highest%, lowest%)ã'$DYNAMICãRANDOMIZE TIMERãDIM SHARED Prefixes(2), Port, NumOfPrefixes, Sounds, Sec, Corr, Digit4, Digit4D$ãDIM SHARED FoneNumber$, ND, NL, NumOfBusy, HangUp, TotalFN, Quit, NumSkippedãCLSã'LET Prefixes(1) = 485ã'LET Prefixes(2) = 485ã'LET Port = 1ã'LET NumOfPrefixes = 2ã'LET Sounds = 0ã'LET Sec = 30ã'LET TotalFN = 1000ã'LET ND = 399ã'LET NL = 600ã'LET NumSkipped = 1ã'LET NumOfBusy = 23ã'LET HangUp = 0ããInputsã'DialNumberã'EndReportãModemNotOn:ãBadModem 1ãENDããREM $STATICãSUB BadModem (which)ãCOLOR 15ãIF which = 1 THENã PRINT "Modem not on or connected. Please check all connections and make sure"ã PRINT "it is connected properly and is turned on. After you do that, restart"ã PRINT "this program."ãEND IFãEND SUBããSUB CloseComãIF Port = 1 OR Port = 2 THEN CLOSE #1ãIF Port = 3 THENã CLOSE #1ã DEF SEG = 64 'point to BIOS data areaã POKE &H0, &HF8 'restore "com1:" address in BIOS data area to com1:ã DEF SEG 'return to DGROUPãEND IFãIF Port = 4 THENã CLOSE #1ã DEF SEG = 64 'point to BIOS data areaã POKE &H2, &HF8 'restore com2: address in BIOS data area to com2:ã DEF SEG 'return to DGROUPãEND IFãEND SUBããSUB CoolPrint (x, y, text$, CPdelay, Cursor)ãRANDOMIZE TIMERãFOR CP = 1 TO LEN(text$)ã LOCATE , , 0ãGetCoolPrintColor:ã LET col = INT(RND * 3) + 1ã IF col = lastcol THEN GOTO GetCoolPrintColorã IF col = 1 THEN LET co = 7ã IF col = 2 THEN LET co = 8ã IF col = 3 THEN LET co = 15ã LET lastcol = colã LET coo$ = INKEY$ã IF UCASE$(MID$(text$, CP, 1)) = "A" THEN COLOR co: LOCATE x, y: PRINT "a": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "B" THEN COLOR co: LOCATE x, y: PRINT "B": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "C" THEN COLOR co: LOCATE x, y: PRINT "C": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "D" THEN COLOR co: LOCATE x, y: PRINT "D": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "E" THEN COLOR co: LOCATE x, y: PRINT "e": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "F" THEN COLOR co: LOCATE x, y: PRINT "F": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "G" THEN COLOR co: LOCATE x, y: PRINT "G": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "H" THEN COLOR co: LOCATE x, y: PRINT "H": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "I" THEN COLOR co: LOCATE x, y: PRINT "i": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "J" THEN COLOR co: LOCATE x, y: PRINT "J": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "K" THEN COLOR co: LOCATE x, y: PRINT "K": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "L" THEN COLOR co: LOCATE x, y: PRINT "L": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "M" THEN COLOR co: LOCATE x, y: PRINT "M": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "N" THEN COLOR co: LOCATE x, y: PRINT "N": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "O" THEN COLOR co: LOCATE x, y: PRINT "o": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "P" THEN COLOR co: LOCATE x, y: PRINT "P": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "Q" THEN COLOR co: LOCATE x, y: PRINT "Q": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "R" THEN COLOR co: LOCATE x, y: PRINT "R": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "S" THEN COLOR co: LOCATE x, y: PRINT "S": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "T" THEN COLOR co: LOCATE x, y: PRINT "T": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "U" THEN COLOR co: LOCATE x, y: PRINT "u": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "V" THEN COLOR co: LOCATE x, y: PRINT "V": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "W" THEN COLOR co: LOCATE x, y: PRINT "W": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "X" THEN COLOR co: LOCATE x, y: PRINT "X": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "Y" THEN COLOR co: LOCATE x, y: PRINT "y": LET y = y + 1ã IF UCASE$(MID$(text$, CP, 1)) = "Z" THEN COLOR co: LOCATE x, y: PRINT "Z": LET y = y + 1ã IF MID$(text$, CP, 1) = "(" THEN COLOR co: LOCATE x, y: PRINT "(": LET y = y + 1ã IF MID$(text$, CP, 1) = ")" THEN COLOR co: LOCATE x, y: PRINT ")": LET y = y + 1ã IF MID$(text$, CP, 1) = "=" THEN COLOR co: LOCATE x, y: PRINT "=": LET y = y + 1ã IF MID$(text$, CP, 1) = "-" THEN COLOR co: LOCATE x, y: PRINT "-": LET y = y + 1ã IF MID$(text$, CP, 1) = "@" THEN COLOR co: LOCATE x, y: PRINT "@": LET y = y + 1ã IF MID$(text$, CP, 1) = "." THEN COLOR co: LOCATE x, y: PRINT ".": LET y = y + 1ã IF MID$(text$, CP, 1) = "^" THEN COLOR co: LOCATE x, y: PRINT CHR$(34): LET y = y + 1ã IF MID$(text$, CP, 1) = ":" THEN COLOR co: LOCATE x, y: PRINT ":": LET y = y + 1ã IF MID$(text$, CP, 1) = "/" THEN COLOR co: LOCATE x, y: PRINT "/": LET y = y + 1ã IF MID$(text$, CP, 1) = "#" THEN COLOR co: LOCATE x, y: PRINT "#": LET y = y + 1ã IF MID$(text$, CP, 1) = "?" THEN COLOR co: LOCATE x, y: PRINT "?": LET y = y + 1ã IF MID$(text$, CP, 1) = "0" THEN COLOR co: LOCATE x, y: PRINT "0": LET y = y + 1ã IF MID$(text$, CP, 1) = "1" THEN COLOR co: LOCATE x, y: PRINT "1": LET y = y + 1ã IF MID$(text$, CP, 1) = "2" THEN COLOR co: LOCATE x, y: PRINT "2": LET y = y + 1ã IF MID$(text$, CP, 1) = "3" THEN COLOR co: LOCATE x, y: PRINT "3": LET y = y + 1ã IF MID$(text$, CP, 1) = "4" THEN COLOR co: LOCATE x, y: PRINT "4": LET y = y + 1ã IF MID$(text$, CP, 1) = "5" THEN COLOR co: LOCATE x, y: PRINT "5": LET y = y + 1ã IF MID$(text$, CP, 1) = "6" THEN COLOR co: LOCATE x, y: PRINT "6": LET y = y + 1ã IF MID$(text$, CP, 1) = "7" THEN COLOR co: LOCATE x, y: PRINT "7": LET y = y + 1ã IF MID$(text$, CP, 1) = "8" THEN COLOR co: LOCATE x, y: PRINT "8": LET y = y + 1ã IF MID$(text$, CP, 1) = "9" THEN COLOR co: LOCATE x, y: PRINT "9": LET y = y + 1ã IF MID$(text$, CP, 1) = " " THEN COLOR co: LOCATE x, y: PRINT " ": LET y = y + 1ã 'FOR de = 1 TO CPdelay: NEXT deã IF coo$ = CHR$(27) THEN ENDãNEXT CPãNextL:ãIF Cursor = 0 THEN LOCATE , , 0ãIF Cursor = 1 THEN LOCATE , , 1ãEND SUBããSUB delay (Seconds)ãLET T! = TIMERãLET SpeedDelay! = SecondsãDOãLET DNKey$ = INKEY$ã IF UCASE$(DNKey$) = "S" THEN GOTO SkipNumber1ã IF UCASE$(DNKey$) = "Q" THEN GOTO Quit1ã IF UCASE$(DNKey$) = "P" THENã DOã LET Pause$ = INKEY$ã LOOP UNTIL Pause$ <> ""ã END IFãLOOP UNTIL TIMER - T! >= SpeedDelay!ãSkipNumber1:ãLET NumSkipped = NumSkipped + 1ãLOCATE 5, 33: PRINT " "ãCoolPrint 5, 33, LTRIM$(STR$(Sec)), 0, 0ãGOTO EndOfDelay1SubãQuit1:ãLET Quit = 1ãEndOfDelay1Sub:ãEND SUBããSUB delay2ãLET TempSec = SecãLET Sec = Sec - 1ãDOãLET T! = TIMERãLET SpeedDelay! = 1ãDOã LET DNKey$ = INKEY$ã IF UCASE$(DNKey$) = "S" THEN GOTO SkipNumberã IF UCASE$(DNKey$) = "Q" THEN GOTO Quitã IF UCASE$(DNKey$) = "P" THENã DOã LET Pause$ = INKEY$ã LOOP UNTIL Pause$ <> ""ã END IFãLOOP UNTIL TIMER - T! >= SpeedDelay!ãCoolPrint 5, 33, LTRIM$(STR$(Sec)), 0, 0ãIF HangUp = 1 THENã INPUT #1, SeeIfBusy$ã IF SeeIfBusy$ = "BUSY" THENã LET NumOfBusy = NumOfBusy + 1ã WMS 5ã delay 1ã GOTO AfterD2Subã END IFãEND IFãLET Sec = Sec - 1ãLOOPãAfterD2Sub:ãLET Sec = TempSecãLOCATE 5, 33: PRINT " "ãCoolPrint 5, 33, LTRIM$(STR$(Sec)), 0, 0ãGOTO EndOfDelay2SubãSkipNumber:ãLET NumSkipped = NumSkipped + 1ãLET Sec = TempSecãLOCATE 5, 33: PRINT " "ãCoolPrint 5, 33, LTRIM$(STR$(Sec)), 0, 0ãGOTO EndOfDelay2SubãQuit:ãLET Quit = 1ãEndOfDelay2Sub:ãEND SUBããSUB DialNumberãPrintDScreenãLET NL = NumOfPrefixes * 10000: LET ND = 0ãLET TotalFN = NLãLET Quit = 0ãCoolPrint 7, 33, STR$(ND), 0, 0ãCoolPrint 8, 33, STR$(NL), 0, 0ãOpenComãFOR Prefix = 1 TO NumOfPrefixesã LET Number3$ = STR$(Prefixes(Prefix))ã CoolPrint 3, 33, LTRIM$(Number3$), 0, 0ã FOR Digit4 = 6402 TO 6402ã MakeZerosã LET FoneNumber$ = LTRIM$(RTRIM$(Number3$)) + "-" + LTRIM$(RTRIM$(Digit4D$))ã CoolPrint 4, 33, FoneNumber$, 0, 0ã CoolPrint 5, 33, LTRIM$(STR$(Sec)), 0, 0ã WMS 1ã PRINT #1, "ATZ"ã delay 1ã IF Sounds = 0 THEN : WMS 4: PRINT #1, "ATM0DT" + FoneNumber$ã IF Sounds = 1 THEN : WMS 2: PRINT #1, "ATDT" + FoneNumber$ã delay 3.5ã WMS 3ã delay2ã IF Quit = 1 THENã CloseComã EndReportã ENDã END IFã LET ND = ND + 1ã LET NL = NL - 1ã NumbersLDã NEXT Digit4ãNEXT PrefixãCloseComãEndSoundsãEND SUBããSUB EndReportãCLSãCoolPrint 1, 1, "Phreak Fone - Ver 2.0 - By: Brian Mahocker - Contact me at ^Kain121182@AOL.COM^", 1, 0ãCoolPrint 3, 24, "--== Phreak Fone end report ==--", 200, 0ãLET ERNOP$ = "Number of prefixes :" + STR$(NumOfPrefixes)ãLET ERNOFN$ = "Total number of fone numbers :" + STR$(TotalFN)ãLET ERNOFND$ = "Total number of fone numbers dialed :" + STR$(ND)ãLET PNND = TotalFN - ND: LET ERNOFNND$ = "Total number of fone numbers not dialed :" + STR$(PNND)ãLET ERNONS$ = "Number of fone numbers skipped :" + STR$(NumSkipped)ãLET ERNOPOP$ = "Number of pissed off people :" + STR$(ND - NumOfBusy - NumSkipped)ãLET ERNOBS$ = "Number of busy signals :" + STR$(NumOfBusy)ãCoolPrint 5, 22, ERNOP$, 200, 0ãCoolPrint 7, 12, ERNOFN$, 200, 0ãCoolPrint 8, 5, ERNOFND$, 200, 0ãCoolPrint 9, 1, ERNOFNND$, 200, 0ãCoolPrint 11, 10, ERNONS$, 200, 0ãCoolPrint 12, 13, ERNOPOP$, 200, 0ãCoolPrint 13, 18, ERNOBS$, 200, 0ãENDãEND SUBããSUB EndSoundsãFOR s1 = 500 TO 1000ã SOUND s1, .1ãNEXT s1ãFOR s2 = 1000 TO 500 STEP -1ã SOUND s2, .1ãNEXT s2ãFOR s31 = 600 TO 750ã SOUND s31, .1ãNEXT s31ãFOR s32 = 600 TO 500 STEP -1ã SOUND s32, .1ãNEXT s32ãFOR s31 = 600 TO 750ã SOUND s31, .1ãNEXT s31ãFOR s32 = 600 TO 500 STEP -1ã SOUND s32, .1ãNEXT s32ãFOR s31 = 600 TO 750ã SOUND s31, .1ãNEXT s31ãFOR s32 = 600 TO 500 STEP -1ã SOUND s32, .1ãNEXT s32ãEndReportãEND SUBããSUB InputsãStartInputs:ãCLSãCoolPrint 1, 1, "Phreak Fone - Ver 2.0 - By: Brian Mahocker - Contact me at ^Kain121182@AOL.COM^", 1, 0ãCoolPrint 3, 1, "HoW MaNy PReFiXeS? (Prefix = XXX-6402) Max 15 : ", 200, 1ãLET NumOfPrefixes$ = TinyInput$(3, 49, "", 2, 1, "123450", 15, 0)ãLET NOP = VAL(NumOfPrefixes$): REDIM Prefixes(0), Prefixes(NOP) 'ReDIMãCoolPrint 4, 1, "Which modem port? : ", 200, 0ãSelectInput 4, 21, 1ãCoolPrint 5, 1, "Modem sounds on or off? : ", 200, 0ãSelectInput 5, 27, 2ãCoolPrint 6, 1, "How many seconds for each number? : ", 200, 1ãLET Sec$ = TinyInput$(6, 37, "", 2, 1, "1234567890", 0, 0)ãCoolPrint 7, 1, "Hang up modem if fone number is busy? : ", 200, 0ãSelectInput 7, 41, 4ãCoolPrint 8, 1, "Are these settings correct? : ", 200, 0ãSelectInput 8, 31, 3ãIF Corr = 1 THEN GOTO InputPreãIF Corr = 0 THEN GOTO StartInputsãInputPre:ãCLSãCoolPrint 1, 1, "Phreak Fone - Ver 2.0 - By: Brian Mahocker - Contact me at ^Kain121182@AOL.COM^", 1, 0ãCoolPrint 3, 1, "INPuT PReFiXeS:", 200, 0ãLET x = 4ãFOR IP = 1 TO VAL(NumOfPrefixes$)ã LET IPT$ = "#" + STR$(IP) + " - "ã CoolPrint x, 5, IPT$, 200, 1ã IF x = 4 THEN LET TempPre$ = TinyInput$(4, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 5 THEN LET TempPre$ = TinyInput$(5, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 6 THEN LET TempPre$ = TinyInput$(6, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 7 THEN LET TempPre$ = TinyInput$(7, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 8 THEN LET TempPre$ = TinyInput$(8, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 9 THEN LET TempPre$ = TinyInput$(9, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 10 THEN LET TempPre$ = TinyInput$(10, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 11 THEN LET TempPre$ = TinyInput$(11, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 12 THEN LET TempPre$ = TinyInput$(12, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 13 THEN LET TempPre$ = TinyInput$(13, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 14 THEN LET TempPre$ = TinyInput$(14, 11, "", 3, 1, "1234567890", 0, 100)ã IF x = 15 THEN LET TempPre$ = TinyInput$(15, 11, "", 3, 1, "1234567890", 0, 100)ã LET TempPre = VAL(TempPre$)ã LET Prefixes(IP) = TempPreã LET x = x + 1ãNEXT IPãLET NumOfPrefixes = VAL(NumOfPrefixes$)ãLET Sec = VAL(Sec$)ãDialNumberãEND SUBããSUB MakeZerosãIF Digit4 > -1 AND Digit4 < 10 THEN LET Digit4D$ = "000" + LTRIM$(STR$(Digit4))ãIF Digit4 > 9 AND Digit4 < 100 THEN LET Digit4D$ = "00" + LTRIM$(STR$(Digit4))ãIF Digit4 > 99 AND Digit4 < 1000 THEN LET Digit4D$ = "0" + LTRIM$(STR$(Digit4))ãIF Digit4 > 999 AND Digit4 < 10000 THEN LET Digit4D$ = LTRIM$(STR$(Digit4))ãEND SUBããSUB NumbersLDãCoolPrint 7, 33, STR$(ND), 0, 0ãCoolPrint 8, 33, STR$(NL) + " ", 0, 0ãEND SUBããSUB OpenComãON ERROR GOTO ModemNotOnãIF Port = 1 THEN OPEN "COM1:9600,N,8,1" FOR RANDOM AS #1ãIF Port = 2 THEN OPEN "COM2:9600,N,8,1" FOR RANDOM AS #1ãIF Port = 3 THENã DEF SEG = 64 'move QuickBASIC segment pointer to BIOS data areaã POKE &H0, &HE8 'change com1: address in BIOS data area to com3:ã DEF SEG 'return to QB's DGROUPã OPEN "COM1:9600,N,8,1" FOR RANDOM AS #1ãEND IFãIF Port = 4 THENã DEF SEG = 64 'move QuickBASIC segment pointer to BIOS data areaã POKE &H2, &HE8 'change com2: address in BIOS data area to com4:ã DEF SEG 'return to DGROUPã OPEN "COM2:9600,N,8,1" FOR RANDOM AS #1ãEND IFãEND SUBããSUB PrintDScreenãCLSãCoolPrint 1, 1, "Phreak Fone - Ver 2.0 - By: Brian Mahocker - Contact me at ^Kain121182@AOL.COM^", 1, 0ãCoolPrint 3, 16, "Current Prefix : ", 100, 0ãCoolPrint 4, 11, "Current Fone Number : ", 100, 0ãCoolPrint 5, 18, "Seconds Left : ", 100, 0ãCoolPrint 7, 16, "Numbers Dialed : ", 100, 0ãCoolPrint 8, 18, "Numbers Left : ", 100, 0ãCoolPrint 10, 10, "Current Modem Status : ", 100, 0ãCoolPrint 15, 1, "To skip the current fone number, press ^S^.", 200, 0ãCoolPrint 16, 1, "To pause the count down, press ^P^, then press it again to continue.", 200, 0ãCoolPrint 17, 1, "To quit the operation, press ^Q^.", 200, 0ãEND SUBããSUB SelectInput (x, y, which)ãIF which = 1 THEN GOTO SI1ãIF which = 2 THEN GOTO SI2ãIF which = 3 THEN GOTO SI3ãIF which = 4 THEN GOTO SI4ãSI1:ãLET SI1Cur = 1ãLOCATE x, y, 0ãCOLOR 7: PRINT "["; : COLOR 15: PRINT "1"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "2"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "3"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "4"; : COLOR 7: PRINT "]"ãPrintSI1:ãLOCATE x, y, 0ãIF SI1Cur = 1 THEN COLOR 7: PRINT "["; : COLOR 15: PRINT "1"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "2"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "3"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "4"; : COLOR 7: PRINT "]"ãIF SI1Cur = 2 THEN COLOR 7: PRINT "["; : COLOR 8: PRINT "1"; : COLOR 7: PRINT "/"; : COLOR 15: PRINT "2"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "3"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "4"; : COLOR 7: PRINT "]"ãIF SI1Cur = 3 THEN COLOR 7: PRINT "["; : COLOR 8: PRINT "1"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "2"; : COLOR 7: PRINT "/"; : COLOR 15: PRINT "3"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "4"; : COLOR 7: PRINT "]"ãIF SI1Cur = 4 THEN COLOR 7: PRINT "["; : COLOR 8: PRINT "1"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "2"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "3"; : COLOR 7: PRINT "/"; : COLOR 15: PRINT "4"; : COLOR 7: PRINT "]"ãDOãLET SI1$ = INKEY$ãIF SI1$ = CHR$(0) + CHR$(77) AND SI1Cur = 1 THEN LET SI1Cur = 2: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(77) AND SI1Cur = 2 THEN LET SI1Cur = 3: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(77) AND SI1Cur = 3 THEN LET SI1Cur = 4: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(77) AND SI1Cur = 4 THEN LET SI1Cur = 1: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(75) AND SI1Cur = 1 THEN LET SI1Cur = 4: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(75) AND SI1Cur = 2 THEN LET SI1Cur = 1: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(75) AND SI1Cur = 3 THEN LET SI1Cur = 2: GOTO PrintSI1ãIF SI1$ = CHR$(0) + CHR$(75) AND SI1Cur = 4 THEN LET SI1Cur = 3: GOTO PrintSI1ãIF SI1$ = CHR$(13) THEN GOTO SI1EnterãLOOPããSI1Enter:ãIF SI1Cur = 1 THEN LET Port = 1ãIF SI1Cur = 2 THEN LET Port = 2ãIF SI1Cur = 3 THEN LET Port = 3ãIF SI1Cur = 4 THEN LET Port = 4ãGOTO AfterSI:ãSI2:ãLET SI2Cur = 1ãLOCATE x, y, 0ãCOLOR 7: PRINT "["; : COLOR 15: PRINT "oN"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "oFF"; : COLOR 7: PRINT "]"ãPrintSI2:ãLOCATE x, y, 0ãIF SI2Cur = 1 THEN COLOR 7: PRINT "["; : COLOR 15: PRINT "oN"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "oFF"; : COLOR 7: PRINT "]"ãIF SI2Cur = 2 THEN COLOR 7: PRINT "["; : COLOR 8: PRINT "oN"; : COLOR 7: PRINT "/"; : COLOR 15: PRINT "oFF"; : COLOR 7: PRINT "]"ãDOãLET SI2$ = INKEY$ãIF SI2$ = CHR$(0) + CHR$(77) AND SI2Cur = 1 THEN LET SI2Cur = 2: GOTO PrintSI2ãIF SI2$ = CHR$(0) + CHR$(77) AND SI2Cur = 2 THEN LET SI2Cur = 1: GOTO PrintSI2ãIF SI2$ = CHR$(0) + CHR$(75) AND SI2Cur = 2 THEN LET SI2Cur = 1: GOTO PrintSI2ãIF SI2$ = CHR$(0) + CHR$(75) AND SI2Cur = 1 THEN LET SI2Cur = 2: GOTO PrintSI2ãIF SI2$ = CHR$(13) THEN GOTO SI2EnterãLOOPãSI2Enter:ãIF SI2Cur = 1 THEN LET Sounds = 1ãIF SI2Cur = 2 THEN LET Sounds = 0ãGOTO AfterSI:ãSI3:ãLET SI3Cur = 1ãLOCATE x, y, 0ãCOLOR 7: PRINT "["; : COLOR 15: PRINT "y"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "N"; : COLOR 7: PRINT "]"ãPrintSI3:ãLOCATE x, y, 0ãIF SI3Cur = 1 THEN COLOR 7: PRINT "["; : COLOR 15: PRINT "y"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "N"; : COLOR 7: PRINT "]"ãIF SI3Cur = 2 THEN COLOR 7: PRINT "["; : COLOR 8: PRINT "y"; : COLOR 7: PRINT "/"; : COLOR 15: PRINT "N"; : COLOR 7: PRINT "]"ãDOãLET SI3$ = INKEY$ãIF SI3$ = CHR$(0) + CHR$(77) AND SI3Cur = 1 THEN LET SI3Cur = 2: GOTO PrintSI3ãIF SI3$ = CHR$(0) + CHR$(77) AND SI3Cur = 2 THEN LET SI3Cur = 1: GOTO PrintSI3ãIF SI3$ = CHR$(0) + CHR$(75) AND SI3Cur = 2 THEN LET SI3Cur = 1: GOTO PrintSI3ãIF SI3$ = CHR$(0) + CHR$(75) AND SI3Cur = 1 THEN LET SI3Cur = 2: GOTO PrintSI3ãIF SI3$ = CHR$(13) THEN GOTO SI3EnterãLOOPãSI3Enter:ãIF SI3Cur = 1 THEN LET Corr = 1ãIF SI3Cur = 2 THEN LET Corr = 0ãGOTO AfterSI:ãSI4:ãLET SI4Cur = 1ãLOCATE x, y, 0ãCOLOR 7: PRINT "["; : COLOR 15: PRINT "y"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "N"; : COLOR 7: PRINT "]"ãPrintSI4:ãLOCATE x, y, 0ãIF SI4Cur = 1 THEN COLOR 7: PRINT "["; : COLOR 15: PRINT "y"; : COLOR 7: PRINT "/"; : COLOR 8: PRINT "N"; : COLOR 7: PRINT "]"ãIF SI4Cur = 2 THEN COLOR 7: PRINT "["; : COLOR 8: PRINT "y"; : COLOR 7: PRINT "/"; : COLOR 15: PRINT "N"; : COLOR 7: PRINT "]"ãDOãLET SI4$ = INKEY$ãIF SI4$ = CHR$(0) + CHR$(77) AND SI4Cur = 1 THEN LET SI4Cur = 2: GOTO PrintSI4ãIF SI4$ = CHR$(0) + CHR$(77) AND SI4Cur = 2 THEN LET SI4Cur = 1: GOTO PrintSI4ãIF SI4$ = CHR$(0) + CHR$(75) AND SI4Cur = 2 THEN LET SI4Cur = 1: GOTO PrintSI4ãIF SI4$ = CHR$(0) + CHR$(75) AND SI4Cur = 1 THEN LET SI4Cur = 2: GOTO PrintSI4ãIF SI4$ = CHR$(13) THEN GOTO SI4EnterãLOOPãSI4Enter:ãIF SI4Cur = 1 THEN LET HangUp = 1ãIF SI4Cur = 2 THEN LET HangUp = 0ãGOTO AfterSI:ããããããAfterSI:ãLOCATE , , 1ãEND SUBããDEFINT A-ZãFUNCTION TinyInput$ (x, y, Original$, Length, AutoCap, Allowed$, highest, lowest)ãStartOfI:ãCOLOR 15ãLOCATE x, y, 1ãPRINT Original$ + SPACE$(Length - LEN(Original$));ãLOCATE x, y, 1ãLET CursorPos = x + 2ãDOãDOã Ky$ = INKEY$ãLOOP UNTIL Ky$ <> ""ã IF AutoCap THEN Ky$ = UCASE$(Ky$)ãTinyInputColor:ã LET col = INT(RND * 3) + 1ã IF lcol = col THEN GOTO TinyInputColorã IF col = 1 THEN LET co = 7ã IF col = 2 THEN LET co = 8ã IF col = 3 THEN LET co = 15ã LET lcol = colã SELECT CASE ASC(Ky$) 'integer compares are faster thanã 'string comparesã CASE 13 ' time to goã TinyInput$ = total$ 'Function returns our stringã IF total$ = "" THEN GOTO AfterBlankStringã LOCATE , , 0: EXIT DO'off cursor; exit loop to exit functionãAfterBlankString:ã CASE 8 'Backspaceã IF LEN(total$) THEN total$ = LEFT$(total$, LEN(total$) - 1)ã LOCATE x, y: PRINT total$ + " ";ã LOCATE , POS(0) - 1ã ã CASE 27 'Escape (doesn't exit??)ã IF AutoCap THEN Ky$ = UCASE$(Ky$)ã total$ = "":ã LOCATE x, yã PRINT SPACE$(Length); : LOCATE , yã IF AutoCap THEN Ky$ = UCASE$(Ky$)ã ã CASE 1 TO 8, 11 TO 255 'all other keys (exc. tab & lf)ã IF LEN(Allowed$) THEN IF INSTR(Allowed$, Ky$) = 0 THEN Ky$ = ""ã IF LEN(Ky$) AND LEN(total$) < Length THENã total$ = total$ + Ky$ã COLOR coã PRINT Ky$;ã END IFã END SELECTãLOOPãIF highest <> 0 THENã IF VAL(total$) > highest THENã LET total$ = ""ã GOTO StartOfIã END IFãEND IFãIF lowest <> 0 THENã IF VAL(total$) < lowest THENã LET total$ = ""ã GOTO StartOfIã END IFãEND IFããLOCATE x, y: PRINT total$ãEND FUNCTIONããDEFSNG A-ZãSUB WMS (Status)ãIF Status = 1 THENã LOCATE 10, 33ã PRINT " "ã CoolPrint 10, 33, "Initalizing Modem", 0, 0ãEND IFãIF Status = 2 THENã LOCATE 10, 33ã PRINT " "ã LET WMSFN$ = "Dialing " + FoneNumber$ã CoolPrint 10, 33, WMSFN$, 0, 0ãEND IFãIF Status = 3 THENã LOCATE 10, 33ã PRINT " "ã CoolPrint 10, 33, "Waiting. . .", 0, 0ãEND IFãIF Status = 4 THENã LOCATE 10, 33ã PRINT " "ã LET WMSFN$ = "Dialing " + FoneNumber$ + " (With Sounds OFF)"ã CoolPrint 10, 33, WMSFN$, 0, 0ãEND IFãIF Status = 5 THENã LOCATE 10, 33ã PRINT " "ã CoolPrint 10, 33, "Fone number is busy, hanging up.", 0, 0ãEND IFãEND SUBãPaul Maunders MODEM CHAT Cyberax@hotmail.com 08-04-97 (01:22) QB, QBasic, PDS 210 6372 MODEM.BAS ' This program can be used to dial up a friend and talk to himã' You can also send files to each other.ã' The file sending routine needs a little work.ã' If anyone has a better version of this type of program please mail meã' Cyberax@Hotmail.comã' Come to mention it if anyone has any qbasic modem programs please send meã' them.ã' Written By Paul Maunders (Pyrosoft 1997)ããOPEN "COM2:9600 ,,,,BIN,,,,RB32767" FOR RANDOM AS #1ãCLSãCOLOR 14, 1ãPRINT SPACE$(80)ãLOCATE 1, 2: PRINT "Modem Software V2.0"ãLOCATE 1, 64: PRINT "By Paul Maunders"ãCOLOR , 0ãPRINTãPRINT #1, "ATZ"ãã100 DOã a$ = INKEY$ã IF a$ <> "" THEN GOTO 200ã110 IF LOC(1) <> 0 THENã in$ = INPUT$(1, 1)ã GOTO 500ã END IFã LOOP UNTIL a$ = CHR$(27)ããCLOSE #1ãCOLOR 7ãENDãã200 IF a$ = CHR$(8) THEN GOTO 250 ' BACKSPACEã IF a$ = CHR$(13) THEN GOTO 300 ' ENTERã IF a$ = CHR$(0) + ";" THEN GOTO 1100 ' F1 : Helpã IF a$ = CHR$(0) + "<" THEN GOTO 1200 ' F2 : Dialã IF a$ = CHR$(0) + "=" THEN GOTO 1300 ' F3 : Modem Infoã IF a$ = CHR$(0) + ">" THEN GOTO 1340 ' F4 : Modem Typeã IF a$ = CHR$(0) + "?" THEN GOTO 1350 ' F5 : Modem Speedã IF a$ = CHR$(0) + "@" THEN GOTO 1360 ' F6ã IF a$ = CHR$(0) + "A" THEN GOTO 1400 ' F7ã IF a$ = CHR$(0) + "B" THEN GOTO 800 ' F8 : Send Filesã IF a$ = CHR$(0) + "C" THEN GOTO 1550 ' F9ã IF a$ = CHR$(0) + "D" THEN GOTO 1600 ' F10 : Soft Resetã IF a$ = CHR$(0) + "" THEN GOTO 1700 ' F11 : Factory Resetã IF a$ = CHR$(0) + "" THEN GOTO 1800 ' F12 : Hangup (+++ATH)ã COLOR 14ã lin = CSRLINã IF lin > 23 THEN CLSã PRINT a$;ã total$ = total$ + a$ã GOTO 110ãã250 REM Deleting Routineã l = LEN(total$)ã lin = CSRLINã IF lin > 23 THEN CLSã IF l > 0 THEN LOCATE lin, 1: PRINT SPACE$(l);ã l = l - 1ã IF l < 0 THEN l = 0ã total$ = LEFT$(total$, l)ã LOCATE lin, 1: PRINT total$;ã GOTO 100ãã300 REM Enter-key Routineã PRINT #1, total$ã PRINT #1, CHR$(13)ã PRINT CHR$(10);ã total$ = ""ã GOTO 100ãã500 REM Input Checking Routineã COLOR 13ã IF in$ = CHR$(13) THEN GOTO 600ã IF in$ = CHR$(10) THEN PRINT CHR$(13); : GOTO 600ã PRINT in$;ã Totali$ = Totali$ + in$ã GOTO 100ãã600 'COLOR 15ã 'PRINT "("; Totali$; ")"ã IF Totali$ = "OK" THEN SOUND 200, 1.5: SOUND 600, 1ã IF Totali$ = "ERROR" THEN SOUND 600, 1.5: SOUND 200, 1ã IF Totali$ = "RING" THEN GOTO 700ã IF LEFT$(Totali$, 7) = "CONNECT" THEN PRINT CHR$(13); "Connected...."ã IF Totali$ = "SEND" THEN GOTO 900 ' Receiveã Totali$ = ""ã GOTO 100ãã700 REM Ring / Answer Procedureã PRINT #1, "ATA"ã GOTO 100ãã800 REM Send Filesã PRINT "Requesting Permission to send!"ã PRINT #1, "SEND"ã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã INPUT #1, in$ã LOOP UNTIL in$ = "OK"ã INPUT "Filename : "; file$ã OPEN file$ FOR BINARY AS #2ã size = LOF(2)ã PRINT #1, sizeã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã INPUT #1, in$ã LOOP UNTIL in$ <> ""ã IF VAL(in$) <> size THEN PRINT "Size Checksum Error": PRINT #1, "ERROR": GOTO 100ã PRINT #1, "OK"ã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã INPUT #1, in$ã LOOP UNTIL in$ <> ""ã IF in$ = "OK" THEN PRINT "Ready"ã send$ = SPACE$(1024)ã lin = CSRLINã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã GET #2, , send$ã PRINT #1, send$ã sent = sent + LEN(send$)ã LOCATE lin, 1: PRINT sent; " bytes sent"ã LOOP UNTIL sent >= sizeã PRINT "File at "; sent; " bytes sent"ã CLOSE #2ã GOTO 100ãã900 REM Receive Filesã INPUT "Filename : "; file$ã OPEN file$ FOR BINARY AS #2ã PRINT #1, "OK"ã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã INPUT #1, in$ã LOOP UNTIL in$ <> ""ã size = VAL(in$)ã PRINT #1, sizeã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã INPUT #1, in$ã LOOP UNTIL in$ <> ""ã IF in$ = "ERROR" THEN PRINT "Size Checksum Error": GOTO 100ã IF in$ = "OK" THEN PRINT "Ready"ã send$ = SPACE$(1024)ã lin = CSRLINã PRINT #1, "OK"ã DOã a$ = INKEY$ã IF a$ = CHR$(27) THEN CLOSE #2: GOTO 100ã IF LOC(1) <> 0 THENã in$ = INPUT$(1, 1)ã in = in + 1ã PUT #2, , in$ã END IFã IF in = 1024 THENã ks = ks + 1ã LOCATE lin, 1ã PRINT ks; "/"; (size / 1024); " : "; FIX(ks) / size; "% Complete"ã PRINT #1, "OK"ã in = 0ã END IFã LOOP UNTIL LOF(2) >= sizeã PRINT "File received at "; LOF(2); " bytes"ã PRINT "Original file size "; sizeã PRINT #1, LOF(2); "bytes recieved"ã CLOSE #2ã GOTO 100ãã1000 GOTO 100ã1100 PRINT "** Help : Command List **"ã PRINTã PRINT "F1 : Help"ã PRINT "F2 : Dial"ã PRINT "F3 : Modem Model"ã PRINT "F4 : Modem Type"ã PRINT "F5 : Modem Speed"ã 'PRINT "F6 :"ã 'PRINT "F7 :"ã PRINT "F8 : SEND FILES"ã 'PRINT "F9 :"ã PRINT "F10 : Software Reset"ã PRINT "F11 : Factory Default Reset"ã PRINT "F12 : Hangup"ã PRINT "ESCAPE : Exit"ã GOTO 100ã1200 INPUT "Number to Dial : ", Number$ã IF Number$ = "" THEN PRINT "Aborted": GOTO 100ã PRINT #1, "ATDT"; Number$ã PRINT "Dialing "; Number$ã GOTO 100ã1300 PRINT #1, "ATI3": GOTO 100ã1340 PRINT #1, "ATI4": GOTO 100ã1350 PRINT #1, "ATI": GOTO 100ã1360 GOTO 100ã1400 GOTO 100ã1500 GOTO 100ã1550 GOTO 100ã1600 PRINT #1, "ATZ": GOTO 100ã1700 PRINT #1, "AT&F": GOTO 100ã1800 PRINT #1, "+++ATH": GOTO 100 ' F12 : Hangupãã'Added chr$(10) recognition (when modem fucks and puts picture instead of cr)ã'Added escape options from send routine (PRESS ESCAPE)ãBert van Dam TSTHOST ADVENTURE GAME CREATOR bd1rsd@usa.net 12-29-97 (18:22) QB, QBasic, PDS 185 12291 AGC.BAS DEFINT A-Z:DIM SHARED K,S,B&,Z&:V1 'Created by PostIt! 7.2ãSUB V1:OPEN "O",1,"AGC.ZIP",4^6:Z&=8961:?STRING$(50,177);ãU"%up()%9%%%[-%o4\mH[D2#Xz.%%%L#%%%,%%%%fl%hSgfOxN(<,BSm7fwA&rgdCãU"'PBSy-6c9GKGUKJQ/A*:>'X5Bf,Gy'+8)OXJ2$J[q1;.NVXYIGgSQLuLdnh76PHl9NV>Nh?(?:6g+QP5mehQ'=+:qW2g(_#1/P>VãU"y\#?eA'[E9V,VRqBOO'i?2m9'096)69j/*17&UzG<1.Z/H4xi(1=64^YRme'2G/ãU":B^2Di?ECnTmga-:B)ãU"$W>N;ssRudjj_U1?2TK)eL?6.2.Zz^IcG*%iAt])x4eW('ry>GA1Tbl9Gqke7BRãU"2g-H8+0;B#uRZ_,R*m^NS2cW%FlHBQP&hdGk9%GCOS3#[vmU7HK3,q6R6i^WX\NãU"nuEfAfDJl,wa>RV4d71cQ3HEM?Sz:QpVVjs[Wr97qjA6'&H=Se;atCmE?O6O'GGãU"M3/Q6ZBRVU31rLkr:H;88uao\R-iOo_vau+(%Xs:q(c?urTYt]\reM]ON?P9m%hãU";%M^X.kOZj07NBo1xS0rjzCrOIw&E=?&B9;93b6nqx+oITNa&Jp-/d17g9PWBv/ãU"m.Nf^fmK7cB1hUI[<#O4U=)7Ah]IiDfArQ(r9+qXXk1\M+et7_mpri__=C'd-5PãU"K[]eH-%V5yi_io#BHvpW*RuUr0a?iElSS)FdUSr9fTJ/^)3&<+E6cC5K#We*3;CãU"T=GDV)Kj:K+A:*2Q5mk:)9dma$mK2'Lfz^QSUILKk01smo+[[UpNqshm1FLbjx$ãU"C1G)9XR-8s/a\n\BZk+167BR6/)I]6Cz+Q1$ih.--Q7X\:9Cmb3tMct+bLNHzqdOH2FNI:UNs(ktMurihlog)18Ac2om^pPefu,oãU"dLQ8vAIWU;69)g\G[uV_5PI?tINnns3FFfX(9(JBD:Xv5aWDp+-bPUJ56Ave9+KãU"E(xBLoy[t%ya3=EK=JgsMQXdonTUgf14bb=^m8.abCo>2$I-l.A]?+s,*+VZ-tvbL*7ba^DOF91a\VfhSOU'UpIA=I])ãU"IDna]kP-uY-:2hSNAfij*tbD;3R9dHD3iRaRfPtaorTxWE.>]+t_WnWOS[eFxkwenX]FCRhn#>/dx&9qnãU"uF=e9rt9M%HJ*#OF?cq0I,[hdr^W_J.gR;=xN[5N]_W5V7ugF\DerQcDaYrLzJOãU"/I=<4$[9]W3G]fZGi3<8$-#PKJ==zSrdLpK%otI,Ki'9nt*##Fndy.h-qrTU6^vãU"L2Qh^Ql5ki_SRnaReB8zFMSL4.%uF]ToV3JP3>6P]n:v0/oA[.>Knvs<;ju'HISãU"OzAhc[o+=k1TeBUAA\Ef*[.Q(L-9'mUZM#7rbasKYLA?rNUkrVT#7\NNn)\hA4:o&ãU"-=yB-HIh#2)q8-^-Z+1F8K2uCWG1_&vW4fS^CTDC.qI[Lt#RG\L-4LaUf8\SbãU"i9B+aD6ccB&lfDorR27YY0b[KKa3Vr3VY'z[Ob[Pb3d;mCe$w1-.hcs6c\kcXsbãU"\[/eP*2?t(\Lu4b$v>H,[UjNgzip,LlY;vXrc3FM]5byqM*/D>LbeCg##\G,ZxreBovud$N[:X*qZ?47lcpgd%Sp;#'28/v&Ot7PNjleZVãU"Dq%#nt3Wlg)t=tTAHEgiWDH>6PsRg/)i\)H2c1(mtpnY-88vmtnMYCmsOm$JYhCãU"msA*Bb9^*rmGL(dsm>ai>:l2;N^GMJq#1n0($alNd>BnsZL$t?0g6iR[.jFIb1=ãU"Ohblk]whrcVZNVUYrJe:6)i*)0X#qg<\M0,Vi;[)TT$R\BL$]y&o\e\<93/rWG;ãU"$*kj<(on:aq_g2QE6+S-#L;v\GnkrN76Gqxsr\Tx]seTC)&skt1J6?Z#[q;lKOEãU"P\sV#C.KzU+dmHHi.5L#PiX9cdP%l7$+v=&aIW.BrB4j7%sr2UIASosTm+Bg3SqolvjSG_k]kM7=TVAxe:BVk%)7s7w0%up()%9%%%ãU"[-%'3SmH/A=YYklo=9kL977:kW\bx:k+8,:wlklZm#9A:Y=XLl9Bk7XB%wx9o'ãU"k:oW+w:w/i>Xd>&%EST2&9-/(mBnkG5*gIn1SIAh1TqEEm[7T5sM[q/oI'+D1/mãU"1Fs/g11wM8.uI+-=9[7)3pj_$;#X7pOAy9OPm3pB01,I*ff:xp1+I*wFFH.-7J^ãU"6Wn2._i,&F*%u%p()9%%%%-U%J3m4Hw24*wz%%%%e&%%%,%%%%VUZ%SutxB&tf]ãU"];U15alcD_X&-Sed,E#TX<%o7I?hr%2Ddu)DM^BSBY&]a;tG?Xl\/AfLt6<.:^JãU".scc(y^*w4(jB?Q>ce_+UI%-T7#FArQY$Vd8O&QRFFeVYcH4iWBi\gP:nj[VA&0Evn?utK/:_C(+$[?aVpB*hSãU"uoajãU"*lSA?I1SqedMxhiO(H$/&AKxOgk0?\;d%.v.km\F3naP0K[3/t-a=6yl]-o&.NvãU"kU=?XrFgY+HFqQ4p?[y]SVI9$\46x5$&Zq>-KDe>%Mh#bX9X.V=*LmZ%Ve$BZUCãU"\?tn%[tup%()9%%%%-%4(3mHJI0PE'A%%%&7&%%%,%%%%VU]S[utx&%uVs)7V1eãU"HT^4L,/DP]+7vvLHJpPL:9XKe7br=&j;JkNF0j%1N+?>XC#tsVkogC#nO5jjeQWR$>.N4-H04q6=^/MD9H;E9Kq6n+1R32Fr:y&*]QIz8u6rZ2$PD[WQeQ\%cFgu'Mr%4y0%y.^M),4Q&t$HWDDe2ae4ãU")fic)GX?-]5lljVG=a4/9#'xA$ãU"()<;J,6kEx;>Z+y2'ba)*A9j/8BTk7NXL9x0BãU"k9,_X=DryNvCEktu7oKP+^-?UeP6uP<#Bo-tãU"oou#0$)BR]es5dPq3;G71HwLi%[96TVp7)Aj&Lsn79-I;*'LMN.[>+*^EX\QZe9ãU"dy^kB+C$gkjaM'nQOo0&)I.Az40-i'Gf.l/[0XT9&0E&;uMCLey9dp+W[a1Gb)PãU"#0yyj284r7ySpB%%Tw^4j=KEs.ibF2A#.d8&<'mXEAXMekh0.9$YDImE;\ãU"'%y?7FAa8Y4v5V>i%D]\(jLjuA$\Sw]5w[\;mg&uz#9>r(#UQJ#DRKQNQS9N;G3ãU"PW,(DB4W_v<0dK[hb?GPI[^x2fF9Z/(E9wK*YzKTBBgg=%R.u]oa?F1Y*#w\li8ãU"QG*.um8azP2_ki,RwglLrfSUqH,W62(D5g:y2eo,Xo,HY-=pUiim/701EJB'hoUãU"'TM<$BIL'8-.iPYe%kARU9Znr8.vu;nZlJ;/-3>H8vvb0&L6Ljd5HrlgF#/&G$8ãU"ge^[0Z^^XMM.m6nLc+R:lA)k;Ce0KkSzBMS^+UCQ)ZZJiF3Ap4pRhscS\ãU"%vj;B;(w/5KpAVPm>i=?kfQC'Tu/l^o/f*,$hb5seLmT4w$tks2VUMo9oC:BvP-ãU"]hcCf,_:bu(cwKio=ln4?O/Y4N]w(BkcO\,DaZq(')JPQAXMrqh=M\0>)CoMaM,ãU"*.JA)mQ-.kfo?h>,1Cc1-[hAn3E/$K3PTP,,%b]5NmtI&lO+-';mSwl%1GoG(orãU"-TCV;og3f-O[pln=9alOkPPZ;_;foL:qbWCX'$2#m8<3SiM)\;63gCs3/q=B#sUMT:rE5alELh]b?hS0ãU"N['.1l\%tA.$3gobJ59Mkn.UboO8k21[Ui?9^JV'q$-W;9Q<$]ue'qbC^0BIn3YãU"D0lG?1.bke-O/js*m-6n&tm\wQQK;W*?1SF(KFb=^C5*js5x3:pd*-re]JBM4?5DYlmAWsVSAA3>J?&lb=d?K:>dm>LmWjW.*#ZuwumaQE:bbZJ6Z^PU:2$^?kãU"kfqwauU+n:RM)1$k3s3g:FHouUW+#fu/[g2A1IK8g)/),f*lO?>SuM=%IK,07GVãU"k8(8[Gt07v:2yS/uSGS=q.y4>+^a:X1255NGL'g#[8<$_hFf+FRYNpvObcAMXqZP>j1VZ?q#_3LN&[RFr\%=_ãU"Wj&q,a.AA$Lb+^T[m'94RTvGK2r4&:Z.&Di[Q$%dxEi/ljn)5B%lruOgC3]LFH5ãU"4lC>Z\>\3KlK8uVmlvbClNlkuauoT_.3'56\i_qoJBE>FlpJ^4>]IUcq4ZK8-.MãU"dM]BrbX8koru#9k$]qd&u^jlk+&$Db0Dy=Q++:HnF8C.-^#5Hp6Fici(/ãU"hG&dN6xdtT1kHaxS14Orui#AdF1+'_N6XxrIZO=/MD'XLKj5?$aC9SV>(sPoRU1ãU"Lx'6lN5K]$ScHl?(^e8p29GfmN3a^-ISK$ODL+o>#Vv[=O&wnDuGpX/fFrRKXy;ãU"pSX%vGD^b0dr/PQH[Nx7-r+?4<*y<3P]AN2GEjThliOP(pz]wR/Z=Usn*PoG7n,whukZI1KAa9=]8a=UI9uPlk\\OAfc_OãU"4F=Ql\3lN/dO>Q.NO?$/*3s5+H8sSt4G;.LPGX]B^FJTF/b:KA,I^t2ãU">Cr.wRsj17cvXCSP4VvãU"3M=C3+9kO/AgQi6mPqYk$d4uMa^w'#fYteaS5fT,6SSo8)N2XY'B0GT,9DQu[hUãU"]S9?d'o'7]24QeHQ3VYS4cPRRTFTt\=7b>h^nzOFXnAN8HAVQ86qN1NdlOGGkUYãU"SdN%&up(%)9%%%%-%($3mHU,lORg#%%%e%%%%,%%%%V%UXSu%txXY6Y^Qf.ExfOãU")OfPW]8yF*[MzF*(ipIH7zF.G',iFV[TjF8%EZ4QMaan.VsvY(Mq_([Lu$hfMaiãU"iq-AD*%%up()%9%%%[-%(3/mH.p(gZw%.%%'%%%%,%.%%&n%sSutXx\^Y.qR%y,ãU"WETz'AmQp+zArq7nzAQRvMB&+MBmz=m&AQdvy?G'HpTo7RNFnsQBEHFPOvw\SNtãU"G9HRAn%Rnr&>x_^oXnFF&7mtEr'N(%u%p()9%%%%-R%(3mjH&^x*ov%%%%-&%%%ãU",%%%%VVY%Sutx=XY^W%YU(64K5+E_w:-=Ry&5+5$rt/EBXjx)8t^^nd/2r)4x/eãU"D+suaM$y_bMiamy^ua4_Ms%3eKaNS6,s_Ny3_fy(oNJ_]0_P=&Zp7P2PEt;At'^X'2%up%()9%%%%-%4)3mH.I^zs&ãU"y%%%%$&%%%,%%%%VVUS[utx&dtV=<7U1U*Ta40H8Yv#4-aU<9LBXWe/SO5eoJVuãU"tRmnJxA2^AGOIhWJNl=iuq.g6lugMSLN8cF.l+Zq-:I??SCB&R/pWJl$d0N(&#iXAGc*UfQ?tl1ev(J/im1xbQdQRK#KW)HãU"Ji*H>+&TXi.fZtA)bP7x?iguX98o,;OjZ)puv;4rr(,Z>%Cup(%)9%%%%-%)*3mãU"HXo2nk4%%%%D%&%%,%%%%V%VVSu[txXY'^WYY%'6e;+-c?'%Vz%TM&3MxCgAv1)ãU"H]gnLvM8IJUg#M/=O_M7OvAt7xMAQamNxi7QvAQ&%MpR&yymn4QC%mBEpvwa)bpãU"E%xTvMmsr^^4oEzQ?BAEp'Px%?Mw-cyM_eiij(]RM.:NcLJ%Oc6De3eGm>ev>JIãU"E^S/6IeM5s]R2=pB0,JI67h:gI7gA#nv1D5IkXCg1k9A1/Tf%6ya\LD7CMA$gs9ãU",#*g6%m*T<%%up(%)9%%%%-%)$3mHQ^kg36%%%%D%&%%,%%%%V%VWSu[txXY'^WãU"YUd(7U?E5+Ew8:-=yO&5+$$rt/B:jX^^[/Jjr,tb>/Z>r2x1eqwi#Fdrp+E,Ez=ãU"t:,iOF,'p4Q.ww7FJ*M&*FVTCjp7s[TVt6(ip]Z)dfPV-(+IH.XT,tL&7oICvygãU")D993_I4w&sLum'xLum(a4&Z4%TnJgjãU"Xhb#>J/X1>xXN*5+kuQjUKo-Jrj/p^x>>%/jE:*5+%u%p()9%%%%-R%)3maHCf;ãU"*Sz%%%%W&%%%,%%%%VVX%SutxB&tf=]utu%p()9%%%%-U%ãU"J3mIH_Xa%i-&%+%a&%%%,%%%%VUV%Sutx'&vbt]Wsh^F$mD/mp>WVitY^OdAD.SQ$RiE^4YAwr^'l_I/r:[X\UkYG4&ãU"&=2EkyeX':$+1+k(9pkd[K.qmhPJP*HpXyZ%X#Q7.rn1Sr?Iq_Nw^o(TXs(7gSBãU"::ttXTNNJgo9Kpr*5PTHQLs$B;0YZ:'l+*D%f;C8AVci_A6TcD*G31fFmPp:),,ãU"Th&qL%%1qJLRrcnXbE[^Zuvlm*I$[,:FOvu#(6&7OpzT/MQvn.8Br2^DeRVZ]5:ãU"LARu;IW_CAkMpYztuyf(+kYPHOl_pH(lMnOp]dVWD:.;R%j<%up()%9%%%m-%h1ãU"emH[+2YJc%7%%i%%%%,%%%%VU%\SutmxX^^%WYU'X6_5+1Ew:-]=y&5V+$rt4/BãU"Xj(jd/J(>x/^AXNNx#j/nXHBReMLvM8IU+'5s%YTTZ(lpID9EPAQBJx%8%qQoz%ãU"mtRNcBEp$o^OGH7rRHm[QvMB[QorJ%(^YAT=rB&/w)yrHB0,I7ff:x[F$Z.%eFdãU"t&paVL=#%L-LI)c)M+q_w2_c('%%up&%'9%9%%%%-R%o4mRH[D#)Xz.%%%L#%%%ãU",%%%%%%%%%&%E%%%%%%%%%f%lhSg%fxup%&'9%%9%%%[-%'3SmH/A=Y%%%VU%^SãU"ut%xup&%'9%9%%%%-R%)3m#HI^z(sy%%%%$&%%%,%%%%%%%%%&%E[%%%c%>%%V%ãU"VUSu%txup%&'9%%9%%%[-%)3\mHX2=nk4%%%%D&%%%,%%%%%%%%%&%%E%%%'2?%ãU"%%VVVS%utxu%p&'9%%9%%%%-%)$3mHQ^kg36%%%%D%&%%,%%%%%%%%%&%%E%%(%ãU"h#%%%VVW%Sutx%up&'%9%9%%%%-%4)3mHoCf;S&z%%%%W&%%%,%%%%%%%%%&%E%ãU".%%JA%%%VV%XSut%xup&%'9%9%%%%-U%J3mIH_Xa%i-&%+%a&%%%,%%%%%%%%%&ãU"%E%%%%p%B%%V%UVSu%txup%&'9%%9%%%m-%h1emH[+2YJc%7%%i%%%%,%%%%%%%ãU"%%&%%E%%%&GC%%%VU\S%utxu%p*+%%%%%7[%7%3%(%%V%D%%%%%ãEND SUBãCLOSE:IF S=236AND 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ãBert van Dam SIMPLE NULMODEM CHAT PROGRAM bd1rsd@usa.net 02-21-98 (20:31) QB, QBasic, PDS 98 3560 CHAT.BAS 'CHAT.BAS feb 1998ãã'Simple chat program for two PC's connected with nulmodem cable.ã'This is meant as an example for the technique, not as a fool proofã'program. This source is donated to the public domain by Bert van Dam.ã'I can be reached at BD1RSD@USA.NET or in the Fido QUIK_BAS area.ãã'Connect two PC's with a nulmodem cable on com port 2. Start thisã'program on both PC's at the same time (more or less). Now you canã'type something to the other PC, and receive at the same time. Thisã'program has been tested on a 486DX4 and a 386SX with QB4.5ãã'Have fun!ãã'Go to a subroutine as soon as something is detected on the com2 portãON COM(2) GOSUB BufferãCOM(2) ONãã'Pepare the screen layoutãCLSãPRINT " ---===[ simple nulmodem chat program ]===---"ãPRINT " (pres q to quit)"ãCOLOR 15, 0ãXpos = 6ãYpos = 10ãXp = 9ãYp = 10ãã'Open com port 2 for communicationsãOPEN "com2:9600,N,8,1" FOR RANDOM AS #1ãDOã 'Loop which displays the time, normally this would be theã 'place for your own programã LOCATE Xpos, Yposã COLOR 15, 0ã PRINT TIME$ãã 'Check wether the user wants to write somethingã AnyKey$ = INKEY$ã IF AnyKey$ <> "" THENã 'New entry started, erase the previous lineã LOCATE Xp, Ypã PRINT SPC(70);ã DOã SELECT CASE AnyKey$ã CASE ""ã 'Nothing received yetã AnyKey$ = INKEY$ã CASE CHR$(8)ã 'Backspace key detected, make the stringã 'one position shorter, erase the line andã 'print againã Entry$ = LEFT$(Entry$, LEN(Entry$) - 1)ã LOCATE Xp, Ypã PRINT SPC(70);ã LOCATE Xp, Ypã PRINT Entry$ã AnyKey$ = ""ã CASE CHR$(13)ã 'Return detected, sent the string toã 'the other PCã PRINT #1, Entry$ã Result$ = Entry$ã Entry$ = ""ã EXIT DOã CASE ELSEã 'Simply add the character to the string andãprint againã LOCATE Xp, Ypã Entry$ = Entry$ + AnyKey$ã COLOR 4, 0ã PRINT Entry$ã AnyKey$ = ""ã END SELECTã LOOPã END IFãLOOP WHILE Result$ <> "q"ãCLOSE #1ãENDããBuffer:ã'Get the data at the comport and add to a temporary variableãVino$ = Vino$ + INPUT$(LOC(1), #1)ãIF RIGHT$(Vino$, 1) = CHR$(13) THENã 'If a carriage return has been received print the variableã 'to the screen, clear it and put the cursor back at the placeã 'the main loop expects it to beã X = CSRLINã Y = POS(0)ã LOCATE 12, 10ã PRINT SPC(70);ã LOCATE 12, 10ã COLOR 2, 0ã PRINT LEFT$(Vino$, LEN(Vino$) - 1)ã Vino$ = ""ã LOCATE X, YãEND IFãRETURNãViktor Rootselainen SMODEM LOG FILE VIEWER viktor@pcb.mpoli.fi 04-19-98 (16:21) QB, QBasic, PDS 162 5704 SREAD.BAS 'SREAD.BAS v1.0 Smodem log file reader by Viktor Rootselainen 1998ã'If you use this code please give credit.ããDEFINT A-Zã'$DYNAMICãDECLARE SUB BigFile ()ãDECLARE SUB GetFile ()ãDECLARE SUB PrintText ()ãDECLARE SUB SaveText ()ãCOMMON SHARED lastrow, Slog$, LongFileãDIM SHARED TxtLine$(2000), LineColr(2000), Filebuf AS STRING * 160ãSlog$ = "Smodem.$$$"ãIF LEN(COMMAND$) THEN Slog$ = COMMAND$ãLOCATE , , 0: WIDTH 80, 25: usecolor = 1ãCLS : GetFile: CLS : row = 0ãFOR i = 1 TO 20: k$ = INKEY$: NEXT 'clear keyboard bufferããIF LongFile THENã OPEN "I", 3, "smodem.txt"ã REDIM SHARED Seeks&(1 TO 16384)ã CurSeek& = 1: lastrow = 0ã DO UNTIL EOF(3)ã LINE INPUT #3, text$ã lastrow = lastrow + 1: Seeks&(lastrow) = CurSeek&ã CurSeek& = CurSeek& + LEN(text$) + 2ã LOOPãEND IFãããprintscr: COLOR 7, 0ãIF LongFile THENã IF row < 1 THEN row = 1ã SEEK #3, Seeks&(row)ã FOR i = 2 TO 24ã IF NOT EOF(3) THEN LINE INPUT #3, text$ ELSE text$ = ""ã Strg$ = SPACE$(80): LSET Strg$ = text$ã LOCATE i, 1: PRINT Strg$;ã NEXT iã ELSEã FOR i = 2 TO 24ã LOCATE i, 1: PRINT STRING$(80, 32);ã IF usecolor THEN COLOR LineColr(i + row - 1)ã LOCATE i, 1: PRINT TxtLine$(i + row - 1);ã NEXTãEND IFãCOLOR 15, 1: LOCATE 25, 1: PRINT " "; CHR$(25); CHR$(24); " Home, End, Page down, Page up - move| ESC - exit| P - print"; : IF LongFile = 0 THEN PRINT "| S - save text"; ELSE PRINT SPC(17);ããmain: DOãk$ = INKEY$: inkey = INP(&H60)ãIF k$ = CHR$(0) + CHR$(72) THEN IF row > 0 THEN row = row - 1: GOTO printscrãIF k$ = CHR$(0) + CHR$(80) THEN IF row < lastrow - 23 THEN row = row + 1: GOTO printscrãIF k$ = CHR$(0) + CHR$(71) THEN IF row <> 0 THEN row = 0: GOTO printscrãIF k$ = CHR$(0) + CHR$(79) THEN IF row < lastrow - 23 THEN row = lastrow - 23: GOTO printscrãIF k$ = CHR$(0) + CHR$(73) THENã IF row - 23 > 0 THEN row = row - 23: GOTO printscr ELSE IF row <> 0 THEN row = 0: GOTO printscrãEND IFããIF k$ = CHR$(0) + CHR$(81) THENã IF row < lastrow - 46 THEN row = row + 23: GOTO printscr ELSE IF row <> lastrow - 23 THEN row = lastrow - 23: GOTO printscrãEND IFããIF UCASE$(k$) = "C" THEN usecolor = usecolor XOR 1: GOTO printscrãIF LongFile = 0 AND UCASE$(k$) = "S" THEN SaveText: SLEEP 1ãIF UCASE$(k$) = "P" THEN PrintText: SLEEP 1ããdat$ = MID$(DATE$, 4, 2) + "." + LEFT$(DATE$, 2) + "." + RIGHT$(DATE$, 4)ãtxt$ = dat$ + " | " + TIME$ + " Smodem log file reader v1.0 " + "line" + STR$(row + 23) + " /" + STR$(lastrow)ãCOLOR 15, 1: LOCATE 1, 1: PRINT txt$; SPC(80 - LEN(txt$));ãLOOP WHILE NOT k$ = CHR$(27)ãCOLOR 7, 0: CLS : ENDããfilerr: LOCATE 1, 1: PRINT "Can't open file - "; Slog$ãINPUT "Input Smodem log file: ", Slog$: : IF LEN(Slog$) THEN CLS : RESUMEãENDããprinterr: LOCATE 1, 1: PRINT "Printer error:"; ERR: SLEEP 1ãCLOSE 1: RESUME printscrããprogerr: CLS : COLOR 7, 0: LOCATE 1, 1: PRINT "Program error:"; ERRãENDããREM $STATICãSUB BigFileãrowstotal = LOF(1) / 160 + 1ãPRINT "File Name to save (Enter=Smodem.txt): "; : INPUT "", File$ãFile$ = LTRIM$(RTRIM$(File$)): IF LEN(File$) = 0 THEN File$ = "Smodem.txt"ãLOCATE 4, 1: PRINT "Please wait - converting "; UCASE$(Slog$); " to "; File$ãPRINT "Press ESC to abort": PRINT : PRINT "Line"ãOPEN File$ FOR OUTPUT AS 2ãDO WHILE NOT EOF(1)ãGET #1, , Filebuf: a$ = Filebuf: row = row + 1: tmp$ = ""ã ãFOR i = 1 TO LEN(a$)ãb$ = MID$(a$, i, 2): z$ = LEFT$(b$, 1)ãIF ASC(z$) >= 1 AND ASC(z$) <= 15 THEN GOTO skip2ãIF z$ = CHR$(0) THEN GOTO skip2ãtmp$ = tmp$ + z$ãskip2: NEXT: k$ = INKEY$ããtxt$ = RTRIM$(tmp$): PRINT #2, txt$ãIF k$ = CHR$(27) THEN PRINT "Aborted!": CLOSE : EXIT SUBãLOCATE 7, 5: PRINT row; "of"; rowstotalãLOOP: lastrow = rowãPRINT "Smodem log file ("; LTRIM$(STR$(LOF(1))); " bytes) converted to Smodem.txt ("; LTRIM$(STR$(LOF(2))); " bytes)"ãCLOSE : SLEEP 2ãEND SUBããSUB GetFileãON ERROR GOTO filerr: OPEN Slog$ FOR INPUT AS 1: CLOSE 1ãON ERROR GOTO progerrãOPEN Slog$ FOR BINARY SHARED AS 1 LEN = LEN(Filebuf)ãrowstotal = LOF(1) / 160 + 1ãLOCATE 1, 14: PRINT "Smodem log file reader v1.0 by Viktor Rootselainen 1998"ãIF rowstotal > 720 THEN PRINT : PRINT "The file is too big to load it in memory.": LongFile = 1: BigFile: EXIT SUBãLOCATE 3, 1: PRINT "Please wait - loading "; UCASE$(Slog$): PRINT "Line"ãDO WHILE NOT EOF(1)ãGET #1, , Filebuf: a$ = Filebuf: row = row + 1ã ãFOR i = 1 TO LEN(a$)ãb$ = MID$(a$, i, 2): z$ = LEFT$(b$, 1): C$ = RIGHT$(b$, 1)ãIF ASC(z$) >= 1 AND ASC(z$) <= 15 THEN GOTO skipãIF z$ = CHR$(0) THEN GOTO skipãTxtLine$(row) = TxtLine$(row) + z$ãLineColr(row) = ASC(C$)ãskip: NEXTããLOCATE 4, 5: PRINT row; "of"; rowstotalãLOOP: CLOSE : lastrow = rowãEND SUBããSUB PrintTextãON ERROR GOTO printerrãLOCATE 1, 1: PRINT STRING$(80, 32)ãOPEN "LPT1:" FOR OUTPUT AS 1ãIF LongFile THENã SEEK #3, Seeks&(1)ã FOR i = 1 TO lastrowã IF NOT EOF(3) THEN LINE INPUT #3, text$ ELSE text$ = ""ã txt$ = SPACE$(80): LSET txt$ = text$: txt$ = RTRIM$(txt$)ã PRINT #1, txt$ã NEXT iã ELSEã FOR i = 1 TO lastrowã txt$ = RTRIM$(TxtLine$(i))ã PRINT #1, txt$ã NEXTãEND IFãLOCATE 1, 1: PRINT "Smodem log printed"ãON ERROR GOTO progerr: CLOSE 1ãEND SUBããSUB SaveTextãLOCATE 1, 1: PRINT STRING$(80, 32)ãLOCATE 1, 1: PRINT "File Name to save (ENTER=Smodem.txt): "; : INPUT "", File$ãFile$ = LTRIM$(RTRIM$(File$)): IF LEN(File$) = 0 THEN File$ = "Smodem.txt"ããOPEN File$ FOR OUTPUT AS 1ãFOR i = 1 TO lastrow: txt$ = RTRIM$(TxtLine$(i)): PRINT #1, txt$: NEXTããLOCATE 1, 1: PRINT "Smodem log file saved to text file "; File$; " ("; LTRIM$(STR$(LOF(1))); " bytes)"ãCLOSEãEND SUBãEran Meuhas COMMUNICATIONS LIBRARY FOR PB meuhas@surfree.co.il 03-06-99 (13:59) PB 80 2307 COMMLIB.BAS 'ãdim BaseAddress as shared integerã'ãport%=0ã' port% is zero based (0=1, 1=2..)ãBaseAddress%=GetComAddress(port%)ã'ã'ãendã'ãsub SendStr(byval s$)ã for i%=1 to len(s$)ã do: Status%=inp(BaseAddress%+5): loop until bit(Status%,5)=1ã out BaseAddress%, asc(mid$(s$,i%,1))ã nextã i%=0ã do: Status%=inp(BaseAddress%+5): incr i%: loop until bit(Status%,6)=1 or i%=32000ãend subããfunction Carrier%ã for i%=1 to 3000: next 'A small delay, for the modemã function=inp(BaseAddress%+6) and &h80ãend functionããsub DropCarrierã delay 0.1ã d%=inp(BaseAddress%+4)ã bit reset d%, 0ã out BaseAddess%+4, d%ã delay 0.3ã bit set d%, 0ã out BaseAddess%+4, d%ãend subããfunction GetBuff$ã s$=""ã doã for i%=1 to 50: Status%=inp(BaseAddress%+5): nextã if bit(Status%,0)=1 then s$=s$+chr$(inp(BaseAddress%)) else exit doã loopã function=s$ãend functionããfunction DataWaiting%ã Status%=inp(BaseAddress%+5)ã function=bit(Status%,0)=1ãend functionããfunction BaudRate&ã 'returns the current baud rate of current portã BaudRate& = 0ã OUT BaseAddress% + 3, INP(BaseAddress% + 3) OR &H80ã LSB% = INP(BaseAddress%)ã MSB% = INP(BaseAddress% + 1)ã OUT BaseAddress% + 3, INP(BaseAddress% + 3) AND &H7Fã Divisor& = (MSB% * &H100) + LSB%ã IF Divisor& THEN BaudRate& = 115200 \ Divisor&ãend functionããfunction GetComAddress%(byval port%)ã p% = Port% * 2 + &H3FEã DEF SEG = 0ã GetComAddress% = PEEKI(p%)ã '! push DS ; save DS for PowerBASICã '! mov BX, port% ; put port number in BXã '! shl BX, 1 ; multiply it times 2ã '! add BX, &H3FE ; add 3FEh to itã '! xor DX, DX ; access bios data areaã '! mov DS, DX ; put segment into DSã '! mov AX, DS: [BX] ; get port addressã '! mov FUNCTION, AX ; return to calling programã '! pop DS ; restore DS for PowerBASICãend functionããsub PurgeBuffã if BaseAddress%>0 thenã do until DataWaiting%=0: s$=GetBuff$: loopã end ifã do until inkey$="": loopãend subãDavid A. Wicker DOOMDAYS: COMPLETE BBS SOFTWAREtopaz817@fastlane.net 06-12-99 (01:26) QB 754 49838 DOOMSDAY.BAS' DoomsDay Full-Fledged BBS SoftwareãDEFINT A-Z:DIM SHARED K,S,B&,Z&:V1 'Created by PostIt! 7.2ãSUB V1:OPEN "O",1,"DOOMSDAY.ZIP",4^6:Z&=37125:?STRING$(50,177);ãU"%up()%9%'%7-%D+TEK5?>i0$W[%%L8%%%1%%%%it%trxi(f(SgRfx^L;:BTk?/YãU"py$2YDh_M:H%P:Ku32aa;n**d'nRug=&+mA?J6G&Qm5'[gGSC&I]W/=V.Vf..nsãU";$m4rJo]Eq3E0O^Zr5vjaVLsumblc^hr>n+ãU"(&07bLmLttpce4<]LW(5(9-KP4JsB;1aVk.IsãU"e\Cpw==H+T]H]w<1(=8F[';Eh0S,Whiknj^ouX2FUlj0_ox\HEX#Fl^ãU"ldILHQdtrOo1$8]J9Y#gTd>VqC)+UlrQap>SPVG0H3*1.+vvm[n[4X3jO7SSlY+o,]NãU"EBkj(emf9vj+bg6W:U.//b2+4.%h+\Df8/B:v+6xQe.:E%^RY%flu7LZK[Iij_DãU"aqa_+fUmB9tC\N&&F'iE;_/7MU:7MOPHpFaXDlh%:l5aLa8c?$^l/L3#oDbe9Px?k=CrãU",*^S3B-fIGcqNu?X]/ETlE6kj6:J+LJD?3v3_aFL\HN^;;?poI)*A&MX3.Dot%,ãU"R1W>y*eZM:/n#_xtz\:q9(0f+CG)mLlm_vi\Z=]ilQNBNM?m,/If%_;?Sh(]gPCãU"bhOjW(m,dp]A0pmz2^.MDL\iI]lOkqbugHS;3)96UEZ$Q:0TZQMãU"UTD_(mS_8K9TJ+))BwLTMGN$5>sUlM-HiG6\fL9gdJ&9Bk5n;DdK3CUX_Jn1<_VãU"n[dAn[PFeBXZg6#l;9bNbjl]5gP(K)l-aoSU?F0MEJAg;kev.'Ms--B'.-k#qqnãU"agWAGM3Z[vim&*wWUr\TDA)P8GUfg>i5M*Ob>TP&Cy6&\Um?SVnãU"nlq,E=c1Tt[O$AVaB4fQN+S,zI37I0KXc;]BCT)jãU"(X)X5p$RLYH5aF,3LhmS2.BtXt^vIqWQK2hI_=^4:c#3Hhe>fpmM$)i]NKfrKA1ãU"j&$Y)wRFuV:eRhFR#Pm2aKWh>_%w%dmDjo8XwktgkrHPn,P[4l=js$l=s#8HKW-\HmãU"]o:?sREYVq0DrM=_xr:E4gkCcJLembJOWMJ2wEt->\olU4y+L2ivk45#pãU"#Ucg3rcRI4kiM2Qa4C9=]W(YVk;TfZWDRZ4%8gqZsDRgc\9;jp[aqcd9^G\L]81ãU"9q(BSH;7c8&dt73P9wYY22jYRO8FY*xW::$;VNuqC-Kg)V^*.DLSg*\cQE_l%G2OasXr?7a3XE()$vg,%ãU"0/D8q=WWqe\K6L]89?'lc42qa'A],:SZXn5Y-YMB_ãU"'jt(Wm0eF(bt7,(z.5q1vF]m0YDW.De$M,k\tLQL?)65_F6RWWXng%jf\iK)JFaãU"?)H,cdje=3W)/K_CEJk_#$Zku/(1__m*d;cnN-%f.=SOW;o]OeS^7+u9T$282DjãU"v8=^;KHb(xz4sI^\8\*65x%#F=IweGy&I&T:[0faL9Wd',RnZl;3M6?+dve)s4^ãU"J#SwIOph'pXNVT7$wH+kAn^T6P=8/H.<2qt2?f8B\g0+PEeLqSppuls<\:K#V^VãU",mnJjG?N,OK8KhCa^o(dKWPu+7zNV;a],JJHxCA+3mNPRR?/EVhql6R[Em'\i4PãU"cDqDEiYpeV:3-Mdkc4],,C4K2)K$i/3BLJ'0v7bd\$%HI5OKHToB/JF;'exkW4:sfvz,GVlD8,v1gEEBR9?Zm0B$U2u?t\=4-'ZWKjb+uFER[*&9G#T-$F5Y/ãU"D]?hqpd58Br&1*P(gG5bZ#gu<_2ODaTN2Ah=$c^u9rX[3qOãU"V6CAJKB:&>J),>^CW+**6FãU"$$%I0dlm)Ik)WD-5N':zBMk:H1WoI0kQl84?6+f>%z>2]&J\#/e^8rGpE$k.d6OãU"VIn_orKF[r4KeT4kaQy7'l>x3GeZm3gJTOLr',v.fKfzM4YwoDteLyIGB'rRHqIãU"#7mm?2aiq5'&e0bl#l)BL1qA&^hKhfq9Y3uC^>[tvg6#R9[#s'k-++T5iK]A+8nãU"p?7jNTQBtvj1Z0=hkc&s#LnUYvpFI.E4&,Og]/S$UsT)RcpxfMrv+LEC;&N)k[SãU"?HYORWDX%ãU"4)UHZ^vItva67:P6mUjZ52%[bs\GX;1EuMA4]8Tu6IqgR57MrAB^1q^+9;UVeh?+5DV?d['2q4E#pJKaãU"^s,1L9MmorykE-WM._ud(D<:Epp[ybaN$e0mL[x&]lfIaLBBtLEb[fdCBda[x60ãU"j,iBiOiQn7:VXQ?dWKf(r7&L8$CRu3B5S5K.(i)OOFMpAnPFiS^F>./^8C^u#$Hlj_j&+d)b?/Q592*^[ce*=//'/(\TrMLUdwBhO^I+T[j$+Y+=1C:ãU"+q->g')Pbw=1CHW3+]q*_EE2-S::&>$+*op'oFz^#$x2poRmw7[nXu8SvãU"NrD]c*oEQH:<2sA?SwnHHLNQV\cBi$aRHQZf^u-.6\Erm>NNSe)<^d1'ãU"6^JD]?6UHWi&9g$?,U1sEQfw(lZCt)6\(zo-R%p=AJ?d$x'L7z-^/ndNs>uWI#bãU"E5N2^?.qB<=lFSH#LCP4Q[6'Jf%:rg*(T)QZ+gsEDjZXEPC(o$W+['o)WmwZZktãU"Vd$=GL5h1Nu8P#UISc(pdc?VBOD4Q]xU?sVSACoVl8%xux2MYN,4y?pe(zIdWQYãU"tbfAo'pv:Ui#jAP-[z$jwEonPO1k^RD,RVW[vWfeQbeeE65JY=WWi$me\D[QbK<ãU"qGlV7$gT4(E(qU#j/peM)w*yC)]S1Z'6IãU"RQWmW1B[zF>HQXLY+ERYA7#j=nsDhO2>a5aF6kzJnh%ePn*8aW2,rBJmpm:CKe7ãU"LuFhSRO2Ao9WjBHM[vIGpLJ\->QsZc]fl2+A,0#-.j]yrHy,^#h-\[KdJb\$RsvãU"56>gGU\m'DK/SP=%*O;Mw9mn1%Si($&?daa-lAGv^$h3:H0<:(QcLtzqCeqIX8bãU"y8>'qNZV4(o/bk^9QfmpikW%xU'Yf()&s%6zAEjF,H+73CgH0/FZ'jO2,TCQ&=9ãU"*bR:A[&:,Ye83+bnU2?T^zY%14Q592XV8+Z8bO6'_*yWRIzq9RãU"F,m\C(V:aL744,3mR3U#cz9G7yYh4Ob/6I6iVB(3w\jo)-sB785MUBI)xN'W&pKãU"h)$^%n=,Pm,;cH?)tiXLkSJa8]JU,/XPWfYpmfGu[7]FG$RSVKSh0C[\dWbt%BfãU"e43T5+raeRipIJiGWfGqn\+(:0QEWL?AQ$fLQrequcW:EY+(-*neftxXs4UngWaãU"BGKTn[RNc8XupWGA)G%KRf-WgQJq]pKR0q'8.^QYJut8BIiT-Ll?vB_$w)K,(lDkoiEEKMBo?8ãU"TypKG+'0xlLa-A.8>D8I;];']/0E(dspYs-sFt96S2'T;[QS2S^W:s1%F['XYfIpWqf/2BM9P7DR%(;/603rezWukEO,JHKt4?]eMãU"gh_h,cu9T0QP3o.q,V5aRS$]md/(Pz<:zi&dnklk,762_smPm7_Zu=X$oqJ-A;9ãU"Mgn'a*UoG$iT[hY0W35x2/W/:f<=V'aV[h?LãU"=O?kAyDOJ2S+svcWJ2Us-_jsoLW2Ln6i)B'X[j_E/e3mhl;Q/%a[6kQr3lQ\[vOãU":*NwqmKJ6G=Qc)_jpc0PO$iFixY9V70+4jwj-d8mNn(FPjchYkm58,)bh&>_I3fãU"'Qv''cPq)vpaX4?+\eiVMcRIu[]XjOEo#jWv7ruOSL*S\WeQ?DY>f[;3kT]GY__ãU"8a+SUcw$:F=MmCWO0Fd[*6.AmuB?X+lf0;s\vQ%fs49F42s/zyRC8wQP=2ZW%O]ãU"&C41LrjsfL9g&6_V91xqc7Ww(C-\CZ;4PS%^v:jI%V7tOxj9R&cyU\3#iZ]:eQ(ãU"()l$_*wIZ+FHvtj,CxRN1beTooBjw-hkOqC5QqWJc0'uu8eYeR:3svojn1_MASEãU"),(Ky&Px=_a/7CNf8KeN,sDO'lfa]M_r\_UJi*9*I#yNI.VPu^;;6KPPYDgnZk&ãU"D]Z-Y.Ljc()zwppO&XKZJq9C'=20H.T/T^n6/]6MsEjAU91?uSaPD9k>rORTe(+ãU"\IciKQTy[1q-XW#8s;c0)U*IGG:I8]smPr;k(LãU"^PGi=onM6mnM4<=C4\Fl5#ie'Zm-S8b]7h8QIUvI1k3VB3a^clTQd0#fj+G'g4+ãU"tBRI*x/v9\A):Y;c<56XNK+Cj7.lkV]+8[,IKl3]\#KãU"Yvfg%l&G'4,DfC59B>AT)oP>J7,zY5#'lPbq:cFq;#I1b47)mRA,S&iIr6OWnqCãU"F3^uR124S5qOlDGQOw8$kXLd%]-,&SD2obh;'b&D^$mSw,WE^^ãU"YZ-0E:gi.q]m&zt0J/lga=^_a?627HsF-,]*l>j6EWJSF8+A(rnILjab.87+r+ecãU",5Gb7dls*]U4ni*LjT2l?L?[2VXLY[VJ#mUK=:\okzUd?Eefk;SnFjW-g;s]?&(ãU">HC=kgNv8]ICgg8Y6W4^Tcy2I:(S>,[aãU"K0MqJC^J(mN?#]dWr6T.8DVd),[?S9.9f+?]k+(r]d6ji))f3c,kyV3^42j.1t#ãU"GG?.h4;2'kt\Etf\br:Sc5GIh4ijbI45U\Py3JQCpT;itTA95m??'$kHxU1vGf$ãU"gTFoL(nG(cCGAiHN,Her)(KWbFmJzwaJGvgpYQr\SZ61xnQ0SgS*Xv\;m+[SdgBãU"+9\21jH[/0P6-_ashC>i+pf=7Zf#ZznnJ[oHI_dnTiEkrW-<779b(wDV*hM,?du18X2=_mb&hs9knDytTaguikEd\r(BMãU"Zy4h[GF\'4$YcmRs#'i&h$J>[Idm\BNu,E:[vZ(Nx_y.9PQ5cQNOCas/mo#e)^RãU"i>OdqkI4kXtahB(T&B:Y_]_&v[2'QqB3W)OWmx28apQRt6MSCyLy_7R3lz;QJ;%ãU"i'(s9eTR_(8zdN3SClMGrlW+Hm;uDãU"+w-(XzytcGxN;jTDSegaY]FMA5Za?#?>Jnt9aJ%O8_MzE7jled8FcS-g+b4'8;YUR#bHS.NbK7rxsD?%wãU">#id%Qqq]bbESwdr8dOLsDxml*f.y4SkyKj'f8r:.P<0eR,()(7r>DNNbEGn2A*ãU"d+W,q3\JOL>\UmqZ%<2ci6pStu6'^*4F5:g$QPfTgc+iJ(X]9+V<.3\xq7:20*ZãU"[K5>Q%\'5n-/0ChOaT9egQhMIB0o5#ZTJ9()2c:anXXWGchmoqX\_T4o+#ar-ngãU"iz+.;B5/1Hc1DVjlrH&LW,68Aw>Tf\iH[gGcnf9B]EUSuWnW1TuDQ$N?Ecc(8DbZw0/;c:TwM4&1Z8X2/(6ps.fQq>Amr1HHl/C-jl:m4(0fhUsDBx>BblCwMdf,V*\'tM.6)jH%D;?E%Y$XãU"^lWut5?W5j_6ws^a([ctt,iHFvQ93F)klRq6ãU"/bw%ZMIav?*:kg%-me$-plJ%t&vGXeazoWo7O0S:n[L>;,;Y(5GAL%dEbRKXh20ãU"CT1,w?)13Zh-La2pm-u>Ow5bs9/YU=_pLFhB.JpiJ.5Zns*7j:G'D.2W+K'\(cgãU"7N\oX_DeP3e_-7-XX(3E)$]uLLp4L#Z8;0lj9[vHR]mO,Y?27EmRHxD&dX6H*_kãU"pMh?4]5ZfSLNhf:\Kbsslwam:^p]nL5ãU"J-X_i+2voJjYFUuAskZpH4$)E[75;]MW9'EA3U3kE0Gs=-;Q-*>(coHSkJ>As'RãU"(/*)C7Bm>wm>oN9pyub_8pR.]8or>N;j*+q/rQ>Y[z1[?4jdibqj#F20b+/)7m;ãU"Ju/4-36aHRYR00*BbK(c1h\2?naJ$\W[Z_e5AKwtO>Z#c$v9ZYaltUxkBãU"Iohq3SDn,DuzyUdO+Hs,f59jvW&W+p\50AIhwtL&1nLD&KGWUAbRh40M2uc&N#SãU"D\uf\W%/LwW:*1WSF=;9h=[DZeLãU"PxLWS007vrNnrtw)N,q-Z9]3AR4t()A7[zN=p->w\vF*0[Z8=7Iw11iu2c,.L71ãU"IE:]C2<-[G076SS%v,i+Y1\0RKze\WlYiYC8]3mmPUDEQ]WtK9nvv,_'vD]YvO?ãU"0e,a[;37ZO$Jhmh)eJ2-H_zoqw,:jD^ovTj,,j;U7<=0>5Y\[/&lw*qR+uh2,XiNiYãU"3Ts7\/KCfzrJk_p&)ELU3m&B>3?>>#]1T1xOVVIXJ/^T1DQ^1Z^[kZOo?'=aQSIãU"?;ZlDSQw;=f%#C2N73UK\v\G'=Mn:U)=;l^53+fMn[6?giX%TO-R>*P,oQn5AkcãU"c),/76hvGib+TSVFKq=8TOgaDz$P.PFlg-AmV*t^wA[%(-^1Z<(gzi]YL4o/ZieãU"_iS3D:Vk^ryAN0F[4>68Our9,rCs/Gj-ty=*+2O+Aq&ãU"i\Z6$rBOgOXsld4SxmOH(Y0=kSFaDi&ojvKJtXEle_CMvF+G5>bd3Gl/LkM'yeVR#Z4PI9Uxe_#ãU"U89x2gc.lJFD(X.zM+Ol\%Pm/?(*]F5C*WY^WTh:=+1_:ooB*Y4ud.k%?$\]/Z7ãU"Ol8NFT:yi](PlCe*U9GjqFx-EID7+\tv,Eomdoa8;RYeZ6Ze';;*=KhD2Ama7PLãU"N_'eD3YfDt7u:4SVfVj*p7IH\TXv;R+>DA_8aP[i<=JRJC?biB$#;DyrI43#[BIãU"lW_qw-)KQuN%cqF4&jDj((T1'JDI[f,;FX#^hF0/z:Zr&$&k;IJ[+i*Ngx5yj)DãU"]l_oM%Cbe=V%K^;,^(oL;+I(\n^DBo\u]g+,LXKM&8<.&i$L'i,ãU"[,Fmm&8%tOY18yG_20[1qm]jsI?tIGg'P2pqr7fWãU"V)Dxq>[Md0-u,17ib3be%pTKA_d'Ke\-Xqx3J%v7y'<1/gJieW7F)HqHp3<7QnKãU"Xs9%)YLmM#ZjSV.n:WGfE'>ggE)S/:VQ87LyYX2miX$bgAvQ/1I2)=p?*n>SPA.ãU"dhNM<_fAH8l:$u'rdc>N-#$#qVYaQXP>(i#JZ\Kz7+M;Fl7g+jG7E?*k(O/:VFs\H+8^pMS3:uãU"8\dkO0S?w,m+7/%>QMKhP[')$9im[VNNScqeU_GG?o*lt:*>(YS_rDU#/ãU"LKQ/PKfvh*XQ(IB#L%W4<,wSK5BUOG+ov,KT;ZnDQkF>0L3nVC?^euHx1#,Y7gZãU"&)&eU^4^F/qrwC=F#gBjTp7eekL.Y%'/3dr^&G538fbHD_CvX#%-xãU"f4i-FT.JbliS>GTK2a+SQTsrH1Jaq^5$nVyWgd5Uo2DIi&\&\lwE[_Qj,*vaMBVãU"fEYOCdNO;W5ZRb4_ehB$;_k*lZ361ME9\i/&1f>Mal&d=JKgoR(CQ,OC==$h*843c=l-/M8rjfa5ãU"?vj\(hX:Y#+5(.g1p%AK_p4^\QK1:o,c[689yi)Hv(S;'>,OD1V4])8ãU"Zi8hzG>86b19yJ()*dTe$+FE*8vg0$>cTby#^8y%\_O$l>.rp#:n?4*s;ON'OMcãU"S*-)9\s((b5%gt7sRWb(jQfG2Qu&D?J>l&_c>K=Q>%kNHa,ux\nc&0p]LRq%O9YãU"H02R%MzgKFuksuE*iKb*9r79e(uD$EI$;nXS+gmDalwk#l.Kq*55N0bW5*H/d0QãU"sSaU3bAHvEa^WhK[_y\2#/=*Y7RClZ3>YU1\1AC^Z8+AY2'=7%gnn6.525HUV>FãU"1dasz\liP7VGl4RPjm3COcE(JqlaQ*02t&XMjNJTgW\Slu17cs?SnNdeje:c%JbãEND SUBãSUB V2ãU"mXxQ;*ehVO#yq*.DFS&L-;LuA44ãU"H4CM2*)m$$S&:sdec=C13Vtkn*Vl'gZ;Z]1Z71+Cz&84/B^Aj4UszWwjK#DsAbOãU"*Evj6bm2af^Rr_Rh3)Q$cG[bmPdld%b?r>Bm5.;'Wf51160E3s'[jI$i5krãU"]G:9hjRLH5S-ll[_OF>Jr;ZC;jdKqq\o:+Qcz>ãU"E8UI]Zh3T2,Qbz8,%80wB*q'&jH0;ToN,ec+l>.,S6,VsDF/5ReqS?0a8>3w#csBl:qAãU"d:-)8Y[K$WV?g)XuMh);X9c.ovy$2t1FTgeF5McZC<>Ag5l[J^?M-;9(is[M?yiãU"1vyhGt$O=Pq?#migNm%\VBOSCV=oC6F'fAc5&ScN%fP,^L#gxKTlK8PyTK(?R#S)AyD8y82P3hN]t9di_^dãU"v$pdKIQ7CMlF]3)zntn)SlcYhfJyVCI,VeGA#d_%IV,?QU+m4MLs[]N3[92.NDHãU"hNmg1'xT&Um:$=z5q^wV\d4*pIK10MLRD?EOh_yhqueA#&'EvMv6>t)Y5#OQ?ei6qnQkb7eIãU"q,NUgt-MNlUv5POur85LcCmCn[wXuEoh9.k3gSmãU"3G)sDi+0:\[ri-M0*sOO6mE:v-ib(t:=F;,+pxqRb^>%XU&Or.CND5#9Qf>k;<^ãU"yGyO31F-ea[LsSiLYJ]'oLsAJ$(dW^TVy(2n$J:gq>'>Pb0+[WjRV_IQ#'47&mnãU"TXr0(M(q8?TcR\4&9?r8&(vH7;I$2T(4Wvy+qQqMS7%$h*0-a[Omf_2Is1wO:$vãU"SP.hT5Q+fJ1r%esQ;](_#CdPHk#/UXXoA]ARw5NLE_n+=#8k=J?'RM;Hz.jxEesãU"9Fqd5d:2-7#jw'Lz-kAh%c3JA?tC#c6RY?uJdo).]gHKs]>m?qVGq/ãU"*(]Coq..H3&HN90B08l;.k03coXA%3[e,z>IVgo[/6?ãU"ap2[G'oI\G2QCI9yc$,sd*x.]E?4upotMlwpyuVWJlBe0[0[/-;y)GOP'dL9Z'qãU";h'SVZ\n.jA)VApi#sAiud/Z58%X^h%aYA'W]#?o3VsãU"[&N.xRt.%,DM3:eT#K+%[SpXgSDT7*qtE3%]0=A9NC:.dSB0%Z>73P,H)Q:sWb(ãU"jTgO5V.m\Ti'(&T0-I/5xr7oJQOYVd.CXãU"(:g.eOAXax1&Dq/v\6=P?kLr;(eQ^4H5<;_)Nt(56Av8s/LG9ib^eXB)K_z<)1(ãU"*,h3C\Vt6CeT:)xUj3%[]^J;ãU"l&&Kgx]TNMq*9gRKz:3J>GUrI6EkxRYDJ[wwb0[TyjxxãU")2IRh<zrsvBwb'7O\]L5k_%PGghXeACCDvUrs)IL*[b)AzDãU"$=UQu4<=[wN1'dHk\0#*\cdz^dp=$%r9q3mb3#q5HT)S+sZwfAHmfPd*ãU"8&%VgQd9)#:RzJGV)ZF3Ez2oK;di[gO6/'lY]b+S,+[BX\V1HB3WVi#]D0WãU"5I;xGAb0UZU^c8#T;OiKEv&(.O(,9tL0GmbOQvpZUZk+\T\e_0[eU799?G[$f\rãU"\$%762%3V,,prYG;)cCekZCT2Y+WL]fc^)9#ga/y8jLa1S3+QCGAqsw>45cYOgrãU"4'293=avc6+tqMZNY\EBHzw$S(m//B?P2pJ/ut=ihVG%bcT=l:T[#4oQ%Kh$x(uãU"'G:kuD(zDxHtKz43xDt.KwpK??T>^g8UH%uUk]Is&m<>xiN'):o'M3h]LX\xg4KãU"Daj<$b*s%Aq)C-E+T&Golxt>+O)#i&%0u=vMWk8Pc?EpHgVUJ'SvXUMke(_ySIZãU"R]BGB24VOD/IpNHsmd,WJrZb&wk.%2Xyws;-aO#-1.gHcr#FtNVTBcPYk?5'W(AãU"q*m9]H.O$t$1COJh=3-_jamri\5En]lm8783HidRUsi9-3;=P$*td=6v29UetFmCjbm_YPãU"J:p^E+y-T6x^Xc;f8kZcak4U]=joQr05LTd-DjFb1K#Ha?uãU"&ORY0PZBd,G\[ovb5E&t)2K1iZ,-iil##eUEQe/SunV_H3cXmP%a1Z*kbLj4:ZOãU"o:t__K1uHS6iw95b&<5PJYF;jW1y.Bj^/i#JU>HV\Xr6ãU"#))*GN.PYrE]ISigSO0A82g+V\Myebt.%#MuP?,U*B9p7[i#3GJ[bHY3Jm7k&)eãU"h1aDG)6Rlp3vic%,#YgPzs\>-m-O:*v2LCA1yD6'3yOON)5Y;Mlr%liy]BSJWS3Be/aV^U[pXR.Ew%aoqCcJ3bqjs6?VN[)ãU"a%gxZQ_]kuz_S_6B92,d6c0fXm^=]fYT^Jo7DueCU'AtvxE.4to:-Qcl)3&T_aXãU"y9sm^]N];=O?s];%f6f,uh:qEu.tyi3:xCp'ob7l<;F,=ukIM+^,%xD=Nv74spWãU"zP=V9J.:hrs(L,7:2%gvXm>ZI/8uK*c1WmqiC9P0Ch&IMC*?jKI_1.[dU;YMd.9ãU".>OI*<7z8ODb1ml5L7miPv8%&up(%)9%'#%-%^\J>D(K+uqI%'%%o%.%%1%%%%rãU"%fnsi%ttrS#fsxle%v]S7U5vlT[)rh(CoOFW9y^:,XQzPl*&y&)%9yzFu%/d/0JãU"oDVJsofU(S'Ad.m)'=wHQV/E7';[pva/sXhFl\[BTc\q):(iI2?35-^?q1I&<6bb;9a)bUn+ãU"108s3de(:#5#Ma'd4(Jy/<%<;2i]7Oj3Pg5Vq0Z;+:r6gvM*ycPi-w0GgUSnv=]Bt$1$,j#ntHeeVCM1nX&s(.82AA?tM]dãU"?nJpijd;72=7jY*vEOT9Wo>cbYl[VAhhE$COe,bR'eMS^u:S^9sOj$WMq]K^Fp_XKD0LmI6Bg9>,N2Y3-Q)HfM^u_cPAME;Z$ZF&6]ZgeãU".KmzhA-'su6(?ni7dV$usnm&r]]^K94B*]Y:qlBg0hG+w7LPcdqZ(g_b)tOc3.LãU"x*Mg]csg/8#%,_=dzj8GXZhG4J+p]fc]RDNiDRYtQ(yHd,d*/Y^+.[VC28ivO2*ãU"MzmCnob8\)V$ntyTqwTE5X3V;ofR&9ZeYNei$b8bV$g(ZqT0;7H78D^+C=0C&zQãU"1rjljxqjj)wj&u_nr01fMtXcVE\>jX-.d(I?#3OkvL3c9(Si>[q9a6HbioC\)x;ãU"]LIokAT9d:Y>\RN]&ekAJtkO9c4Y(#>r[iAGnkZJ\;MesT%Pw%(up(%)9%'%%-%ãU"Oa(EKM642:^[&%%J%&%%.%%%%g%fxjR%VSri;,$Jp]N-;Y2[BlD*SUãU"gCu0'y-Z2as7g?5*k2&%./b%]K/s?rYgF-^,UX?bs^MqD$mWqcFhf%ArpX??=h)ãU"4(*?CglgRc%6vbCIImZ#bSa.k]ãU"j'B(a>hiRYs\[jbm90N32ar]*kb[yS9vGwGfR/8SS0nKc]xRHT#4=-#d9$-tJv$ãU"Pq;E\cLcE:genmsSRCe+EaaD[#<7WkjHE&ga+KW[Ju.jcl%WD\/'x%up%()9%%'ãU"%-%*b$j#ue&D4'Z.%%%47%%%.%%%%vgxj%wSqnFg^<:n;x$nrU:tS%sA8?d9MwYãU"'iw#KGeIFp\NPP58.?mon.1QlO8Y_7_jY&S3N&rãU"q**L%xhAJDUU1o'vG9&wTZDzGi(K4s19sFWrgl.lQv\nyPpkm#Fg6rGFC>.Gr_aãU"0909shcPZMP[v9&jJ^?h='(0-8T2U]YU>(\F0%-S/l^48UA\olBvVh7(5CCqyy%ãU"W5k.tI-a(OTfWMUun*hoK9CW8h%QP3:?TRDv))(61QR>a/WIUHvplk)7WH0,B&<ãU"1$)L3PJe&0%sL,f:U&M+=]JfB*KKGe-LH\A92.n#aHR-ed]d:\C[Gj]>y&mq$MkãU"1>1HjEA.v+Q+J^cSjv^4*wY57LS#2HbT8Y-L6#v'&%s[+7p5FYHR:u#Jw_Ws4lUãU"SKh>ioVp;lw%$-Ax2txFM)6BM_J#[ZiuP=d0[1Nn4U&IgarGt0l9fKUf1sNUu,_ãU"aw'.*UB,W*i7fn=N(S'hr>H9TVMfyG:S6eBJ;dnS'?%+5Cmol30B(5]m3&%fzp:Vuts&H6,1n%gx&I&\sAjNZUe:#sA:&O7cgq#=;eãU"v%.w#F#>b2MLP,Q6h23=rjfaYg_VtTu9xEiTuIqG:TRLuUDHitA&fOqMefLmaB*ãU"HrmD4Vlko04c^h4e^\JaYZ1R$2nE]Xp+%3P(2^_]1/o6*oB%/cYVZCa&dãU"s:b1-+V3Y9=qLfQAENtXBnrWbWf/?ueHobQ%QZk=JNTo:.RTZQ4'F,%=<3f%r(?ãU"T]OQcq7604%YXmC5[x*QE[Cn?VI#Eqra*)Y4='B_0UEP6tg#2ãU"??DSdwarSa>^C])/o2+TS&n4R3NcI<^]nVZT^0Pc6XVX2N3:(nwUY3=_P9$9kd/ãU"f^$;s/615f%._zJt69^?&jom%1(s?r)ãU"2?;1175A8idI/s(4Ze]_Rz:IuZH3Dp/KpYH'dehXJY)_++V:^5EhCbLrHa-)GGQãU"=8^o,8BE_[JS3eYGm7,6p(b=[p%:VLBRcc*$:[BHLv5r^0\0Fhf0XX3/ag&o25HãU"66e%r;J8mG%:qpL'2N##nA8V3eI+$^Bq$',fHãU"j#DJ,CdlQ_y'.RAlj,OP^2.1QVV%R8yEULpJY)(xVi-%nTXãU"2Stsly7din]NKJX,n>L,mh%ap0/_Q,KO36$G*nnGd4qn5tL+P?9HEo&txãU"q=?nirHk2jT&qgp&IHdED0QNQ(SU8]+\QRU#b+r5Q2z7bWãU"P-jDVGQN(H?BP6WWf1V+^\.t\)?RVE655LaX&x4Xf2aesPDQ4t%1ae>;2sV<3fPa-4E=m;>/\otIWi&h)('YMj7RKqFeW^UP+,5Yd(o8HXOc%UNAl^Ih(Z^T3fna3>yVQ:cR&E=M_K\s,ZãU"xcH0S\^PP+5O0;2Waa(i=%q:ydQ*IEãU"'=(:#%)i%'prPLQ$7f9J27,L#R-gOH1rs-:ãU"7'D^ch'KcO,'FXNGDcceRK9_^SzBjFj)8#cF]Am6nO.%CO,b5/SNY;6qeuEOR+NãU";^q,n]$SUPHB,d1%[3*2,9u8(a5IPolqna14fv(BV^Aml]1rLmRy,nQ+EB4^Y1NãU"xaPY4qFu9TafAotIf9+ab.)7$OISeu)QUgRlQqtXj&66'e\C_a\6wt/lKGJRI7PãU">]o&2wo#IydOSqGo3KDu0FZ//5-&#uyBlT43hqo#d-%ãU"wIb$&JVB5Q/4pRRED51';MIfKm-tDhqr\8uE,&g]/*-_u/QjJZ>*5J;ao2x.tStãU"J;]%F32>8j%^5E[E[vCTSWpWWC&RJ+:Q0o)b&4mT]/$jCf#:]O,4v60ãU"Z:wP)1a8$qG3Oms3qqN]d?t_PtYhT7UbBx2^EHoadKek:RR&s(2=gOGãU"nkFKl:C>l3aw0QLE5.QcV?jAeITM?ibUU.MhE*JkD8ãU"8W\R(CH?CRzX2pkw&u8sm'U[Nrk9PfWvfiA3Nm08=n&l)O+[eyT/b)WVT/*GbnbãU"U;C&VOLa+D<6CaQUfe$$E:uHK8L)I=V/GNwYE.(,q[$w97HFl7'vu0O.pAof$_FãU"CtIbEDlg,^8UbD[)\C875f6IpgE]7.TY+#Av/C_2&[1*^[_(#orLp0paLE*QC'\EjRB<8^rLCDp8?Op+f/ãU"d6iMF$p9_'Xa&U-l=rUIy^H-'G+uTHz\dIsSFBZkWD6:Zl'u(up%()9%%'%-%(eãU"J>DkGPZp'5%%%&>&%%%1%%%&&wny#tuf)%SfsxCb_V]';e1jAJIs_[Kl=T1XS;OãU"I)*qPd'.Xb5%S10[xeM1e.3Uf7DM_tl7fH*eMxBKtuk:G4etuoA73RpGzISC4BSãU"VwK;jG$,C2U,[/&hY%5e)7I&j/#38<9?VSC+iqZWd1]:-AQ6i3>+Cg2%up()%9%'%I-%ZJm>D9p1QE,&%%%.)%%%1%%%%rf%nãU"sit%trSr.xl\x8,p7qKTZ:bR>IdãU"?HhVW&_=zM6[rXn?]=>#>pCSOz0f4:WlSSo;3Yf:r:sphbZC't_[J]X#E8Fd$x=ãU"p^*c)5FRATD=.ãU"[1W>.Gl/dDd5u>DyNTP/zedclaWSymvDD,E[Y(d-BteUhlT]y0Jt.(tHlvlIAp$ãU"n$PorcXhO>Ag0m95SoB-*6xg-8:6cgFKFC/CT/ãU"f4S7PiB&o<]-/+)AyD47d?a6q1Au\CILB9Xeh93163EU^3pO:99o+5qmxSU'94BãU"Y0%8ED_Cg[yBg8fZ3pxFt#_H6K8llnasG_'^dbYUG6dx?-LonV]Er[4LqL'sg-RãU"8/L+a;Z94Cv=d:h;%yM]#S9A&DNKip.2TIF0$6l'QJZ=c]r(e7*$SvCx:BqhT6,ãU"p&6umnG*o:y:RaLq^/=TMv?dy59K&j'2F*x#rp3/-zlf60<&QrsRy7XDfXrTI_QãU"kI\;6?*/WM?TCW>u/W]Mnm]TCPd6B<_o)Zc.rqdr8#[xVUrZB170<.Rhu7tAE0gãU";t-Crv6TrKi/=%BrKf2Iy>Wm[I1TWPAvaL\TnpKts0UlA7SaCG;t203CTA60S=kãU"6w#:^My&nHq35:U.?v9jYw/aV_)G]+atvW-HR;QCjZf)<,\LLbj\]TLd'ri=ZKsãU"eB,./JU^*Pcq;]+Ja.&[Raa<[RF$X;9AY/ZhCqPH9O;wC:*oCEA50j24e.sCKWd3BPAc3>K52%;kyXY]lLY&%\Jm8mG#7Z_NXBDkLn-cRPiHiH-a-ãU".8>Vi0J7=R5zHK+;rytIwO:6a$'dJcOTFm'/0H*eTj][&DJs0fH[0xot5PFE)Z$ãU"&K-0Xx+cw)4_923#h.QSrG&e;_Zmn-h$A6]:>FJ&=3RmE4SqH4/Wl%bI'xq-GKG[DQãU"oh+lw^:lUQ$%[W*83dHnHSB*.(GWl<^Hed-t0gx#=VE&3vTRYDu,1ji?1EcVkki\5RVu(:1+=o2U*z0&RtdN+1cC_c>*#vVsUWd'Hm04VXTkJ1Tz_(T=vI,[&4cx)#-cLãU"KXRZ+RXskxP.PXh=XPtpDJvd;yGcASU;fo[YãU"b5*Ubth=lY-?_1PntM[8L$%YVsc4^]oV3mOh2:*lY=Ibr]c#JSs]9j,nYI1dU:mãU"]sW:g:eKw2+HhTa=0ydBtYAlaa+F)jh&RD=/eg_/nUImPBoqIk7q_3]xJFi.X9GãU"4?&*?hm%O5+0K36geLr>rW0*baKuZ<#G*p[fãU"ccSG.PjE)66>yvxFj>N&MO\]$So0cXHK#MXh%h88rC82kTS?_STVr;]R05/j^^gp3gãU"c0t$=bTq%YNhri:]/YPTYn1aG?_CbVJv-[#cKnmRnd,Gtnjsrn8LsiM8L3l-7k-ãU"jc1I?hN]]ciSR.e1a$ynL/L<3-$*:?$rKwa8jFD5(7Vhn]8l#NV8y>y5hc6^:HSãU"t;U?THFKG&SQ'h^,]:9K#^nof:L'G&C*[t^,m:MGU^n/i:X%$,GvH)X^/Fg:l8:O^E#E2,LG>aY85aAsãU"[)p-'Uv+%up&YT]gC(M[en-aG2\cR3BZZ;vxCOc5GQ&D)#-W7jYh+)HG]Mh/P/=ãU"#:p8<5SY,^--oi1WQ&7/ks?+i:EQ,^.-ji29QB-9GJqf,Ql.SjE1_Y(GQB)8f5eãU"I<1cYWbQP85GPY/Q7P.'G0Qr?Z$:j.'OFq0Q005+pS?b:\L)Nf/O4:-Q1JQL)R\ãU"65d$Y<)x>gY#-9Wji8j)xSY2EQNo$ib)hFKqNQ7$.w>$:,)pj75nYJ6.M]$Y.5uãU"=':8K9q5:Ta7Uli20QNp'ip)DFJq:Q&^6aioiU:#g.M\YKP.UK'6nUF0qRQl[.cãU"hi;(QXFiq,QHg6KmY.0)^6ouC:ha8u&:7D7u6B:D8K,$Yt.9wX:8#),.maGq/:nãU"NHqhO)XO[&:%R%8H3b&:mEA-KU*gOeJL=9[C#fZhVbN4j6re;e4EfaoZ62Sev0cãU":SdDEfDf;izqtJYo2Kfk*&n:qJhPdwUu4=x3>5$mki]T6*G^h4TSm3wjGK:dK?pãU"aQFAGMA-jr_H?sxYWU5C.rjoLwE./OBG5,Ze>tuxr17gQ^RH_r0X7(PN4KTCm5nPNb/50wU$<0ãU"TC=nH,KILR-3iF;7Ur_xR-b(+SEiueDjr+4BOVYjPLO;F;TDJ7idqtDdt5:ft*^>t*olKE[K1qJ8s1k8]b5BfiZk:lHm>eãU"iXhos?t4bBU^g1AF]$r#l\Gt#$q8[D8virZklNTGl*ytKqbdGLq.qja[LOup7krãU">4.oW2K0pgO*S.?myp.\W%-'tCLzud^[*p#rrcwfJ)$:>jzsnKZ_+wLfSNEWC&<ãU"a:?hL_XSLz*FM+*pu6\G7xb't,S^]u&&mlhT83M=6?6B0Ay$&KQLji7b.OT_zgtãU"ujBeE5;cim<[cwjnX(qJOV9O$of'jnjch5hf9UãU"ye=kC4(88(\#kNNy*hgoDPGcAGtKJ3rq6v37[Ltj]2NnvClc%7tP?GmP_>mFp$$V(;HA_3VLIh\Z\\NlãU"cq\aCJd;rS*n^lEG=v7g[XCuvl%wc%w%LlXaN>?e8%ãU"4E$Dm>t3n0mKBK)NP*8T\Ktu^'eJun5k$/.Ja?IEfmtWiEKG(UGj[G=I<,I7F,$N\=rs(6SoiMLh^?EUVh075seSF$&M>vpPãU"-Np=;6*sN?qagwOoi#Owhy0Q>$vUF9TmB<^G't,UFb%cxlQ89aq1D&j6#%=W5U$ãU"Z[sc4+Zs-J4G#]Y)0DHcOM\sXI*;&t,foIT/+(*N%;wzDRHI7qw>qãU"cgY5-kf1?$QZIa'&p+HU'>yCFSHanm-7I_Uw#svFArQZPRsperMMv[qD6roqGsIãU";2n-W3?.c_pUPi0I99U$E+'rhz&&uUe'UPQ+BkLjTT;U[>FuDI&RYarHi*5(i%FãU"H'DP#)H/CmD.%ktYz//1=0-3bhm)ir0?+^i\L0\22yw0=t&NYVfS=EXc^VgLtV=ãU"K.rrq4Wmzvd'^g1k3r<-)/j-5DP_&Tt'Kpf?_0nZ]1=I_]CHuO%F+c(BQGSRYN%DPTa9gF+3?1O>>1kFQfEP1#<.Z;dZãU"y4'$hH&D2zQ>=#/_DVJ8AR9d1i#s,+>#tyyi2d-ksi6>yj#YeG7%%2mQG%SjfhzãU"%QF?MI=W:'j06BUt4vMh%tY&**\iX9gr9l4UA&o:LVkRrQEOJ>r9+3.15:TTrCUãU"^9t+J10(s.&u[Pb,aHptK7b-y;x2PgD4DrLCZG..YR])lW[y%z5y&&/n-\VU#S-ãU"N+Vy=%B1nj(8n+*)T0cFSq7J)1gMy9i7GXgH>'FH5jps%1,DABrVEh0$Y=wCuM*f]'3Jg$ãU"NO_Kx#2V3A1hx<4K+Nz8/(ZpIa%-EXyBgãU"Le_''%KE,$rn;r?S^aG3w%&=EXUãU"#UEg0)D32/%up()%9%'%I-%y8dn=7H-P.OK#%%aJ%%%1%%%%vg%xjwn%fqSiRthãU".L)r)wYd&c$$5o:NQa>qmduFan05Q&ZXoZ;g6'k+:St4#;Fp;;*Eo47hDlzd,(ãU":Kh$-#Lyb]YQZqM'44pOwoMK>I]<>BAQszgi7EuZo]m76ACFN-'tFP4KLGãU"PBjZ$51Jnwl7KleDUD&cJo:Z60r:g2V,i/aTGbF>VwEmvd&R*:fo9>*u\%eVCKFãU"ax>8s:I9,OA045WN$p_4.NWqiK#V9CKG.ZgngkKRbADzX#klA=Y%2_tnL?p=KJ#ãU"kAr6/QNd39^2_(OLJmHrV[2)>rlioaGPK>a1RG>=,LA7cp[6Q]kBI(Q>]W*Tvu#ãU"+(,etx+2)Y;*np_H&+Heg:Qd=?:sx,+%f=*rY\l&-mz%*jki&0DocdL#a$GdQjuãU"d4.Quoapr_^bWZDX$p9LLSãU"jTo0BoR:h-t\XTP32DNgsGd5+Af*lg4Ni84=+,0.^td;dbPXZkB4cwTZD8-GnXsãU"6QPe*\ej].lE[T&1NOMu2:N.e>/KHG7k[V\db<:X6_$40NWKKu,VfTE%FZ7ER,NãU"SXTQ)E>+5enW<^ROnvcNp,sHgYNSTGx:Z=Niu.?+uGC3O.NlPhil3Z;LIG#vmv+ãU"nWw=fsZ?mVop)8uo7qrcHYtXce,uXaUU5R;62UF=C+TPt'D<$Uc94*dQQ.[Z'T#ãU"Pf5*T);I,R;EZ:12l-pGarj.wS]/dmu#LGsHJ0Z.r-)iYJUk.(#$DAJ,[7ZC[4n3r:8(*&ãU"+T2jr3Jccr9E*tqT&*gyT(V1-%+d=5;JE(N\h)b>JF[QM,)aIEu+:NQ6ãU"7_S]'c=&mNOhm;RC3HQj55+catdx?,_=b<1V*3R>ymbW#[U_d&n:4pjA)A+XãU")Qe2#z'9wDHuUERsM-HLoiA;o0q;2enw^usp)R;glqlr$3]&n)-58rk9ukSa:38ãU"3wNUc2g,pK8T>5/;%Utd(yOOtoR:Nueuec)OãU"-+sdJ>5rIc]B-w4ALvLHoL\pk)TAH(m'GT8XHja1tln%-.U?k)3E([X;Yf(<]#6ãU"C:ykR$pGb8%[]n)G(G)WeBt)Y^EU5tO0ukyW,Nw6$t1xB'56PfãU"H;E+x[c41=*t#vD^W(fPKumB7c.]l8Mhk0QIoowj7n&njO'601$]DRH[4?LI%V4+*d9hH/2zt.2*X[3m$SãU"q8H0FGFg5j+S_&Rge?=)ãU"HId]1h.%X3;Z#[/Nbl#A6o28Z]L^WH6e,c:HLZ>g[i=KoJSYK/P_0SA[v3Nbk_dãU"gt9w7XK3On*<$LNuT2W]4Scsu>ãU"NK2)2>KNxx-dC#T?&[9j,V+lf8]k5PI:jT3Ja3:+3KaãU"I9x&(GiMug5fPS)0,Te$$zy9.BQG10O+<%?qcs[3:H[3:?j,fbRefpI1qsTojCOãU"IGzI[=H_-K9A/^>a[kYAA=6AmZ\8:c%UfLA6WTHb(b*Y;;.Ul)'6P$($xDm[GYsãU"\vRs0nOnbh%Nn]=j=='s_/ol4dCCH#DWiryUy-\j&WJUe(&IqE,EGFi5sK3i7F#ãU"sz.:2#=jtTsK/*#0&/gk*<5^+;F/6A&=%T(Bzt5e\P\zP%s?re_;d]d'=%?uJz'UCG2=&xm0C(6+RNGãU",.D7;\rxSdãU"KjHqX0*+BY^#KU*lgEp-69fUNS*2\,t?#UzpVpP'XS/OYSOAfX2lCO5?3ks>k4ZãU":_XM=q'Qn:ZN#,w*#Y+f82+YL%cQ].:Pt&BE\2899jG&Dj>qcM13qW'\2=H1Sd+ãU"H$8roU)ukc;2fAQW-Q/gy\:azZL$o7/Za>)DuFmiHBbD\DDãU"l-K:JL6zM'(A71U^8^w\3[KO8#-D?9&DI?-hJdPrU0a))>g)2jQkY.U0E5r($+9ãU"7*^vhSJh'9r^.MCS-H+6-;M*o>5;<9Ml^x?'YU??L/##w:VA9-n^=21mQ*2:8ODãU"vOJ[f+=*^rI+pW\ZN#v1JqoN1/42M0=Gx/,PP3sF1b6SN.G?>]9'6z/?FOA*B310arO>&UXDIhft2[*##n2K/bHU4.sI.vq[3HE?p$;_&q9Nkw?,21LasPL&l7ka%Fl'mãU"/H+,M1gu,de.OlXkqQMo1q*BiNWqeOgg'2qv_:4?^.2G+*g>/d\dh3k,<%>[?vjãU"2?94+v#i&uNji0lRnw*:2:UL-,TtUTGIkG376BXJWfTXUHc$_%?WplJkd'7j7?UY2:tLK.Y?>2fv0N1Hwo_[^sW?,>/9cs2[0&X]X#ãU"onKN2BOC]S&e+-8zQm*2-Q92T/D1D%DuxQ;4%ãU"H2I1>7kMR6xcsVWe5LOAt\dsoP'aC68n,4]WBMc'dt#5mGN4V1wu?aWgWaaJPY^ãU".KX?oS91oCcEB5m4A*xjw>N,t2sH1bt7Y'jEG=86FQ/ad),bgZ:W%zrjy.g'6z4ãU"ne#l1]bUFZ$M2cK1jLO6INJVAd/u&nV\0ku0Nb#UaaDq6Re$(JJk*r-$?0lZML1ãU")ux6.f[f+0t1EN&u97nd;S]U[P/s0EalyabHg+ãU"_+JeRf(%F0as83RTp'5?h)c_2&91>9):5^hI7JI\Wg2+1#evzX///q,;0/.BFocãU"XHBsR;k1L3B>==xGXeSqNY2[e]N7_ImRVAOP^cLqt3g?NXEgiQZ;:Sx*?ZJooC]ãU"_%Z4nUE?[B5&$A:LQ4[Q473RW\vgiT*HFDMR8*)E2e#h\at1rk\T'jg=Zk98'j:ãU"LLu+?/mT%*$J%_FCRB\8t:FjfL_f\NQ8:*/qE\ejZ9P>AR3:;PC)VBzoNiYj(XGãU"o=Mi33VVI#/puhWl4Gey-T+PF3Ed%4mE,eH/E?(dHK3fuy,M4$wwU'OY%BaO)&-ãU"Mn9=b%>]$mYyF[OqdqQAV[vY&*yWR,jET<'6ejcb1L2qM,ãU"H%MOU_/jRamNvApk9QN'y1d_U*i_A8QExQQanPa3Q:F-?sqx,_7eV;QA<#)2OynãU"Gq2;jJQad1H$>\S[n^Mos&EV/Y]v'DAFW4)2i)?,lSãU">81jPi*Ipy+PMF[*fh*Zx<#Fpz8)fIc=RllsOB)&z]1t^/:R+TKmp.67G>r^W,GQ,$hVU7ZW)ãU"%b025W*j]jn;QP>z[v-Yw+yo_jW&3FL7CuH^2R'5H+N3+].=zW&W[\_d0'L^6[BãU"FN*(xjX%3<*$JP:VCA(aãU"XNInec9<&v/m9FK0vwhUHs39<$aT5<0FUPYI*x7hLQX:ASxx?VxmT5NfU5em=2eãU"$9*wKT3n=Baq^])62=o:*CN0A=?H*o5)NlHa5bts+3%HT'qEaNUiRZLO5ãU"lcBAY1%'Tb*E^)[/H$EqIC;*:KB*%fU(Ol7IUCRYX:;4YvG9/(t#&cexWA.H=Y=ãU"d8&:wJr.3+wfTD&/.g65j6w(NGiRVLua#uV+:>]frPj6Yk-9$TTo/H=3f[$\0,JãU"uSR$D\:m.FH5kUsJrGWzFSrkuea<\k*_9y2)vPwyM*eIe6$U76H'EQOOKKa_/QvãU"sJ23w%S()=VAo]7U4IsA(rMX+YmQ)H7X14:TP.iM4FNbgoI76Amy7Z.G0cEsI$,ãU">PdqYR:JgzE;ãU"6x1=Fhl_k>;gjTH_/MCq9?bT.Fwn;=E85&P8Mp\&4V3F9sG]\'dk'YUhIGdPzC5wCsWãU"X2cOo0Z)42CxJE2]kh81m]yyL#-iWtvh0^G4<$8?8VR5Q9WLY&+;+^ad6HekI0EãU"]FfoBCI2LIe_E#Hw\weD8[z1xem+\0lY04Ay9$63y):-IuI1CevU#ac$*\tUJ%$ãU"K)qVxg)PZlTR6Dj^iM:9CqgdN/'d0b;RdFFt%l0Ye4yLf]2K0(1qYW))04=d%w*ãU"eD#q9Pm)C\PR.w$5t/*Y\'KoqHm(7kOH5__hx%yUkH*_D^,ZIhVU#X0d72?tV/$ãU")[=ic4K]IFu22ogJv.>PIR2&:9#9ji03]kE_T(&3Op24(ukGAQI)VvQaePdMAuOãU"e3+-T(,\B<=-U2cb/RICGtu4ngFNq+4#E5i+k4^'E>TpQ9,:Q&c]i+l;Qm-_?F;o(pzkv1ChG8:Mq*=$*d/F8xJKb7NãU"9AqMPoO3rbc&b'79Ax&*wxmG2CLQa#W9.EgcpO_lbpq#lpSL0lj$,Bj.vSXP/kvãEND SUBãSUB V4ãU"o\7wlVqwZz;P=PH_Y=$;:,?RJq#INv;vSHS&Xxt7jQl8Z>REe.AP8_ekFDmVE[uãU"^u,O^aJ)HI48FwRRJC/d0Y%.>B4QoOb?LuZwn1FuwyPiv9KDmgd>3duFO&Cf[,+ãU"UN=r3vUc?.LOD2n#%vM3Sqx/2LG9x:7xl9XM#=cGe+8d#un:*U#e_T7SA//%1:-ãU"AWck$7KaByQP#b^ND^\>3s3d)RJEx2Pnp6lt%bTI7h)\.MDP5Cqb)o,Q=z+,7;9SãU"=p[YY1,V7ypm)lwgS$s&?3cA)Pc?bN3xZxL(mi\CoyySQ6;/g8D=TG]s-d.)ãU"-UUbYZS:_*\D)G)Z23(WST1yEgec)%i=-GcãU"T[sFplrt&.9o%7H,]8irwn;9xb)=f&iA,^VvcJ5hvc;U^*]-k#emB>o%?I(be_5ãU"O>&*ZHPvo]=Hk$E.&ZVUPQN8W)r+'#idcNluVnDUD6eY>?clH1,[Q/(vlx)/7-*ãU"$t\Q]u(BHGd2.K8GK+f,_l2Bso%#O\Kk]F7d:Y><8j2s<:uOY:/]M7=gk[*ob,fãU"$t1QK19cdRQx6FUJxoocVIuY8M'=Xf-ctq*7&T>D4Ff/4H9[\(+k/DEK/xUwFnFãU"_Fc.n\P2_:51Ut;X9L+#o:KYC+ZLIC$?F>f+$r4&(h)+BKce7E:u7qEWãU"v*nwm8#XKwOãU"g2A.pVpNgrA.SIF-+,oL4*xbHVDg4]YuB.SbFisYe+I\'(cS)%lTUF50T?wK99=ãU"W<*^aOAUjzC=PV&=eHy\w)3nUHQiRSb(*SLpxbLqbG.aãU"?\K,.'KLM^VNCBEhm-\qT4YECG0DgXL/q09vCZql[apG2sbCHn[\v'ir)aDbEPBãU"cn[#JPw>-Z]8k:a'q>0uAt&OD4Q;i\lMoo3VS6e/PiV24]ilQ8IaUAqnJH2^jP[e7Xn%>aVbXlQIv&%Tf/f6\KtG.&xwFH7K[:+dcy,o0-Ga)ãU"WP;-_L*L8u*:]u9VPf8Qm),g'KV=?.3\Oi:7wwUmQCb[KwYIKe;suVBw5-GN1bwãU"W03lrvP\UfzHBZDNC4nY&K8F)rLkJaYjOV,G?I;Dr1/zcMWZxJ#TU30A>p5FFN>ãU"DELNnJjym'&ZEG#UROY#rT42+d7Xj%:Ds_)(t2%wHL(dU6cKU_a=fJ5Z-Gi)x+mãU"KNID8dKM1tr*yAtLdtYg85cGzZR';8laE^;:?q0>rW\0KunYbF#h,DZ6bXp*B=vãU"Uq*dDE?S+5=0XDw#-hB\^h*R)a+?F+3(u?W(V:&>3(WWG8-1c6U8q>UD7^>IwIlãU");]cF^Av1Ly%zNg$>cl\sQhO.PXye[l4k?B)mx(O:0.T)SvMWjO31%>Rr0VãU"Y^+S6%nMm'#wenm*t_#fz/'J=%M3&ARVn;'jadBZBZtLQP7K%uQs^,lbW=k0mH1ãU"A?9(OFIvO&kKx'6Vmn?v-AOF^LH=/1%#QãU"%?SAcxJuL#\,FM-W$4NMdqhpr\'W4BaBQU2;1);/10W:Cia^?$.Lt5U1w.6C4zsãU"9T/'/0Fas27I/T>y&Fv7Sq52BKuMp?;XpUA:&_OhxyOeal%viMlmc*MyAJX9ZTHãU"/uqbma<2j8Y5lKjBQ>lGFO?rV*MD*ZN\/xU>+$Ws9qt6P8)J=vo0qIrqezY8,YlãU"sBt%QNdL]T+ZZB'IBa[*1zeF-)1c4*/c=-E9]igN%yQ%k$Sok?L+TqA3TWh#ba\Eoc*,e\,ãU"\P$_K]kR$Tf_C0c03kD_Kti0eF9J?61#*oyY1^oqU9$TUA%)M1J?.G3bmo5VOtYãU"]2TQ(?+hw$g21OKKtv$V8).D9Fe.-%B2&6)wyI\dR5Y7?,Fxr=EJTzJgP$TkWDCãU"T0f)Yi1fq]'\HeNZ;xGn;PZ&\L]'z6nkon(OWUWLE?#d[wR$p6H-K_P7J1^LdgUdJLMhãU"*f;SJyDRb_*ZY0A]:)RoU?MPJWryd)E%k.qP#-p*C,bGãU"lyJElu+is0g1hteIb'4JJ.g)I;K6NQa$b;LO.A:Q6>%UTHãU"cVi$J?F':$s0N*PtYs5L\qYY:O,dYKPu1v%AMvhz1Dxfwj$$r'>-c&8ES,K\UjTãU"11,;;*SCrS7w^_;C6pO8>L(ft_+DvR^p#u]C'=?A4jBqPgJw^M-OAtEkR$.ãU">VNY^a$F$8'No^h>l.Cp_?GqjruZSaXgC>Q^&6Am4G$a,]FNdm]qgB_350_GTK^)xE8]VwwsO8N<_oãU"sVbE7h6Th:76RJ6Bz5L1G:raR,rWrCC]Q#hxj6#bãU"_b.%U7]:euec,/LY:UPm+^QOLC]FnQKdC0AaUT/y)4?qo7rn1F)P4&j9i&4F%6EãU"PJ5ya+d.D2l,ibU*QsNI3HE8u/?difKIAe.d_ca;X:S9I>otEgFhGi''$jBlhv?db?qWS)pidd8OZ*5bMxWhm\+#tCO9i,p=F6ãU"pkWLx\l((oKfGWW%'ZkqGtcXeLoY\3#;%m/w]=9UDeKua\LKIEKUKrF*fCe0=pAãU"8D]&jj*4(tO=o;Y)lk>)%gIkjxN_f0ENfw\hG6g_d,m[&Om5AWJ$*)q+P=WYA1P:jau0GV/-dZuJ(:mãU"&awLYSAãU"RTPRW,w/EC7DC6dmPqEVNãU"nSDfY48GZMf/KE+u&cRI6EEwJ'j#)i4KuL5u$J9_#xI3=3.b;JD6>n,A1-dwF3iãU"*(s/&OM<*AG7q4YgN_n'<0m$H)F9o*$_r=_busWlY2f;<;GDhpPHAl69;*,Bp&XãU"HqO?sI3:f8M&K&TFt4J+LãU"f73OrYz.VZQãU"C8+qCGzsQe6$_0^6LZaO+9nFSt0XPYcNoCbr*[OFl]tBCT/tt^fG1lN#-gJEg\6k5l]Y[U>,R>[:5b=;uXONV<:ãU"[YEMMc1WPhNKFL2Q:[U4pX%RJ26.e'pGpaLH)kHGxTxCIs5^6xkN&%up()%/%%%ãU"7%%I']EKT,%i6^%%%%^%%%%1%%%%it%trxi(f(Sr#xli028;HELi>>DEM;8:4%S2/u%p()/%%%%%[ãU"%%(EIKBx0'EX%%%%X%%%%1%%%%gzq%qjyn%sSrxIlnAC0)=CEgMD;;42C8=ãU"E%RRcELj38CLEC78JBE0=JHEF0JHEH>JDE;8):42/%up()%9%'%7-%f.]EKo,l''7ãU"]/nI)7):>n?^<)$r)BEGh;55Zui(HLIb0E-^M**esqpLH$L>atTv>J6HXKovnqwãU"q)]%qIujx-=&5tjGfFxS,nXY7SwjT?)\7BB-/X]-j6rv-80cm-/?G8dSIAL^Hpm]-Uqma=gcN'Un\c8dcuB%#NemdCK/0ãU"y[m?chA8sDOS8k3edYdpTr/>4kr<^l_T#QCi)ftE%o1ccC$bnFK0fDF2q53ãU".Y?svMWbxMT.NZj4*&RZua9v_fFz9:&roJ7J[f.pEãU"6RWs/.%Sx61<3DG+=X_U3GmnPof5=OKbbB^*AUef&<)&pGkMC'iG0&7,,.NP=4-^o12ãU"5vhg9*,'[NWfQ<41[Vh4FapX\025;(,[)(GW?.p6*&:BtwK)5<$WYjShe&2VJ9PãU"XX-ELMt>([b;r)ZBuIWr6L$ATgA+_*^MV?mTN]jk-)k0A=P+pJq62Q)(F#>kz.RãU"DOg7T.=An78S3R^A2pel\TGSmtMcU,+b1h,G^aiSg'?^wksZRoJ_wu*&T[$Ta&<ãU"K>cO$8k+YKS(r.Fm6eGGla$.R]UlBms^PJ8/)x;f+WwAP)XRu9]Z#O[A(_.2ãU"$/yF[6/PgerWJyV?*3?Rq9b\Ip/_>^pLS9K(sfrT^6Lv/AboYJ5K0jTv>nk8q,c)SKATãU"nCUC_<%J(]%%'zeu,JkZsdRDIPg7+$i9r[q'U0>Pmr\0l$R.L,rb3/5S0o>)$>HãU"wc/i>X;Qg8v&#%[NYGY4uuIw.wso4[<^K:^jJfa*KM8k3$uM7t#WMz(BR$l6TaqãU",e,\+cOOIO=n*bbP'y*(:=&HK_cFOP0g[*J/O;*pW0O%p'cO*KX8ULQMmiMGodDãU".&$IOChPy*X>?v]'J5*svq+AhMt.l4DEe+ndpOttX'GDCk],$?[+2vW=?IQtI%xãU"lsh5xR1oAG28_s=TYp7;1d2F4VD):1ãU"z&d5tON?FcBY?Q+Dgmq7QWfr?4+)y9d=2W/&aT5VG*pJZmX(Z\kU#hMkQI*oGw=ãU"*V9buF2IV7osx;VflawMkr-oZVn7Ng_Rs4%P0q2&kXvqOt.pszkB>M8f=r85?BiãU"1Da3n+_aaUx,>p9/ZP;K$cbA2yV(d0_.I0>->'ogfAKe;qYm#(4z-:.MwdE/kD?ãU"Lg=)SZ(\0?G1Pouu$.M\9[5$r1Sk.Kp4rbvc(R'#2E6QSAa4^Jbt2M\mGZ:eGGOãU"t9/4Q&6X\V'&>Ef-g0Iwm\p4rR$Mj=0YK?:?lEtz1JCN#>2WOAZAV.1;s^2Abi>ãU"Q9Zk+T2yM.L#Wnl5*'82$x7AKWWORl-2tmG.Tt7W9_X\iabFYnaXtFDãU"WGwdRND=^KuPhVH.d%F_j3()2>eb[xGBOiDfsV:EAyQ^faLC^;tN587fsLjYB:jãU"YhAMV+h[oR$VhCB#P(S4w/G(sV+05rVVL]aA_.E##ãU"1$#QXE0XP[LTjulnT0&>^G++Hd)icRb5r2fVY(L>YkjS+-K&[0D]IjSvv$1WP4.ãU"+QSE*U%:5KuLFl#=^H\7G#$BQ+Pn=hTwZlDV$a6VSZne-b?HM%G%+zC)Js/jCJrãU"n3F)dW;m]/B[$.#_IAnzXA#+OHQ5M(j8FwL7j3u)Xwc>UnrDA<]rlbL.wjcvc0gãU"swx;%;GJ*Cc&'DH:vI7PJ1SoA9,SnkV2r8f$9J?VnYWzkg%QV.NT-s7L?^[(rR&ãU"uX\cDjTddw8$Vl?[i9ZMh'Xup&%'9%9%%'%-a%D+EOK5?i-0$W%7%L8%%%1%%%%ãU"%%%%%&%E%%%%%%%%%i%ttrx.if(S%gfxu%p&'9%%9%'#%-%^\J>D(K+uqI%'%%oãU"%.%%1%%%%%%%%%&%%E%%%%6X%%%rfn%sitt%rSfs%xup&%'9%9%%'%-[%O(EsKMãU"42&:^&%+%J&%%%.%%%%%%%%%&%E[%%%.%Z%%g%fxjR%VSri%up&'%9%9%%'%-%/ãU"]%Q#;:aRl&t&%%%6+%%%+%%%%%%%%%&%E%%%%:\%%%xl%Srxl%up&'%9%9%%'%-ãU"%*b$j#ue&D4'Z.%%%47%%%.%%%%%%%%%%%E%7%%W]%%%vg%xjwS%qngu%p&'9%%ãU"9%'[%-%f$*P#qFabQg%(%%t%2%%+%%%%%%%%%&%%E%%+%_g%%%xlS%fsxu%p&'9ãU"%%9%'%%-%eAJ>DGrPZp5#%%%>%&%%1%%%%%%%%%&%%E%%(%qk%(%&wn%ytuf&)SãU"fs%xup&%'9%9%%'%-1%ZJ>=D9pQ)E,&%%%.)%%%1%%%%%%%%%&%E#%%%W%l%%r%ãU"fnsi%ttrS%rxlu%p&'9%%9%'[%-%tA\j#Cpc,qt#8%%*%K%%.%%%%%%%%%%%%E%ãU"%%%4n%%%vgx%jwSv%qgup%&'9%%9%'%7-%K&fEK2h*/_s%7%%t%%%%,%%%%%%%%ãU"%&%%E%%%(V,%%%qtlS%rxlu%p&'9%%9%'#%-%y++EKUB*a'.#%%%q%%%%0%%%%%ãU"%%%%&%%E%%1%s,%%%hfq%qjwx%Sify%up&'%9%/%%%%%%9K&EK:)R[,%Y%%%%Y%ãU"%%%/%%%%%%%%%&%E%#%%Q-%%%qf%xyts%Srxl%up&'%9%9%%'%-%)y8n=t7HP.%ãU"OK%%(aJ%%%1%%%%%%%%%&%E%I%%W-%%%vg%xjwn%fqSi%thup%&'9%%/%%%7%%IãU"']EKT,%i6^%%%%^%%%%1%%%%%%%%%&%%E%%%*US%%%ittr#xif(%Srxl%up&'%9ãU"%/%%%%%%7%(EKgBx0E%X%%%%X%%%%1%%%%%%%%%&%E%#%%dT%%%gz%qqjy%nsSrãU"%xlup%&'9%%9%'%7-%f.]EK "S" THEN GOTO 8000 ' Wrong type, fail.ã2040 IF LEN(PKTDAT$) > 4 THEN EOL=ASC(MID$(PKTDAT$,5,1))-32 ELSE EOL=13ã2050 IF LEN(PKTDAT$) > 5 THEN CTL=ASC(MID$(PKTDAT$,6,1)) ELSE CTL=ASC("#")ã2061 IF X THEN PRINT " Send-Init OK, EOL=";EOL;", CTL=";CTLã2070 TYPE$ = "Y" : L = 8 : D$ = "H* @-#N1"ã2080 GOSUB 6000 ' Send ACK with own parameters.ã2999 'ã3000 ' Get a File Header packet. If a B packet comes, we're all done.ã3010 GOSUB 5000 ' Wait for valid packet.ã3020 IF TYPE$ = "B" THEN GOSUB 7500 : GOTO 9900 ' Done.ã3030 IF TYPE$ <> "F" THEN D$ = TYPE$+" Packet in [FB] State" : GOTO 8000ã3040 PRINT "Receiving "; MID$(PKTDAT$,1,L) ' Print Messageã3050 OPEN MID$(PKTDAT$,1,L) FOR OUTPUT AS #2 ' Open the file (errors fatal)ã3060 GOSUB 7500 ' Open OK, Ack the F packetã3999 'ã4000 ' Get Data packets. If a Z packet comes, the file is complete.ã4010 GOSUB 5000 ' Get a valid packet.ã4020 IF TYPE$ = "Z" THEN CLOSE #2 : GOSUB 7500 : PRINT "(OK)" : GOTO 3000ã4030 IF TYPE$ <> "D" THEN D$ = TYPE$+" Packet in [DZ] State" : GOTO 8000ã4040 PRINT #2, MID$(PKTDAT$,1,P); ' Good data, record in file.ã4060 GOSUB 7500 ' Ack the data.ã4070 GOTO 4000 ' Go back for more.ã4999 'ã5000 ' Get a valid packet with the desired sequence number.ã5010 GOSUB 7000 ' Read and decode a packet.ã5020 FOR TRY = 1 TO 5 ' Try 5 times, then give up.ã5030 IF N <> PREV AND TYPE$ <> "Q" THEN RETURN ' Good!ã5040 PRINT #1, SNDBUF$; ' Not good, so resend previous,ã5050 PRINT "%"; ' and display special blip.ã5060 GOSUB 7000 ' Read another packet.ã5070 NEXT TRYã5080 TYPE$ = "E" : D$ = "Timed Out" : RETURN ' Failed after 5 tries.ã5999 'ã6000 ' Send a packet with data D$ of length L, type T$, sequence #N.ã6010 SNDBUF$ = CHR$(1)+CHR$(L+35)+CHR$(N+32)+TYPE$+D$+" "+CHR$(EOL)ã6020 CHKSUM = 0ã6030 FOR I = 2 TO L+4 ' Compute the checksumã6040 CHKSUM = CHKSUM + ASC(MID$(SNDBUF$,I,1))ã6050 NEXT Iã6060 CHKSUM = (CHKSUM + ((CHKSUM AND 192) \ 64)) AND 63ã6070 MID$(SNDBUF$,L+5) = CHR$(CHKSUM + 32) ' Insert the checksumã6080 PRINT #1, SNDBUF$; ' Send the packetã6091 IF X THEN PRINT ">>";MID$(SNDBUF$,1,L+5);"<<"ã6100 RETURNã6999 'ã7000 ' Routine to Read and Decode a Packet.ã7010 FOR TRY = 1 TO 3 ' Try 3 times...ã7020 LINE INPUT #1, RCVBUF$ ' Read a "line" (up to a CR)ã7030 I = INSTR(RCVBUF$,CHR$(1)) ' Look for the SOH (^A)ã7041 IF X THEN PRINT "<<";RCVBUF$;">>, SOH at"; I; ", Try #"; TRYã7050 IF I > 0 THEN GOTO 7100 ' Got SOH, must be a real packet.ã7060 NEXT TRY ' No SOH, try again.ã7070 TYPE$ = "Q" : D$ = "Timed Out" : RETURN ' No real packetã7100 CHK = ASC(MID$(RCVBUF$,I+1,1)) : L = CHK - 35 ' Lengthã7110 T = ASC(MID$(RCVBUF$,I+2,1)) : N = T - 32 : CHK = CHK + T ' Numberã7120 TYPE$ = MID$(RCVBUF$,I+3,1) : CHK = CHK + ASC(TYPE$) ' Typeã7130 P = 0 : FLAG = 0 : PKTDAT$ = STRING$(100,32) ' Dataã7141 IF X THEN PRINT " L =";L;"N =";N"T = '";TYPE$;"'"ã7200 FOR J = I+4 TO I+3+L ' For all data characters...ã7210 T = ASC(MID$(RCVBUF$,J,1)) ' Get a data characterã7220 CHK = CHK + T ' Add it to the checksumã7231 IF XX THEN PRINT "-";(MID$(RCVBUF$,J,1));ã7240 IF TYPE$ = "S" THEN 7300 ' Don't decode the S packet!ã7250 IF FLAG = 0 AND T = CTL THEN FLAG = 1 : GOTO 7400ã7260 T7 = T AND 127 ' Use only 7 bits for Ctrl range checkã7270 IF FLAG THEN FLAG = 0 : IF T7 > 62 AND T7 < 96 THEN T = T XOR 64ã7300 P = P + 1 ' Real data character positionã7310 MID$(PKTDAT$,P,1) = CHR$(T) ' Insert data character in bufferã7400 NEXT Jã7411 IF XX THEN PRINT " packet data://";MID$(PKTDAT$,1,P);"//"ã7420 CHK = (CHK + ((CHK AND 192) \ 64)) AND 63ã7430 T = ASC(MID$(RCVBUF$,J,1)) : CHKSUM = T - 32ã7441 IF X THEN PRINT " chksum=";CHK;", packet=";CHKSUM;"'";CHR$(T);"'"ã7450 IF CHKSUM <> CHK THEN TYPE$ = "Q" ' Compare the checksums.ã7460 RETURN ' Return with packet type.ã7499 'ã7500 ' Routine to send an ACK and increment the packet number...ã7510 D$ = "" ' Nothing in Data field.ã7520 TYPE$ = "Y" : L = LEN(D$) : GOSUB 6000 ' Send the packet.ã7530 PREV = N : N = (N + 1) AND 63 ' Next sequence number, mod 64.ã7540 IF N = 0 THEN PRINT "!"; ELSE IF (N AND 4)=0 THEN PRINT "."; ' Blips.ã7550 RETURNã7999 'ã8000 ' Error packet sender...ã8010 IF D$ = "" THEN D$ = "Error"ã8020 L = LEN(D$) : TYPE$ = "E" : GOTO 6000 ' Go send it, return from there.ã8999 'ã9000 ' Error handler, nothing fancy...ã9010 D$ = "Error Number" + STR$(ERR) + " at Line" + STR$(ERL)ã9020 PRINT CHR$(7);D$ã9030 GOSUB 8000 ' Send error packet, and fall through to...ã9900 'ã9910 ' Normal exit pointã9920 CLOSE #1, #2ã9930 PRINT CHR$(7);"(Done)"ã9999 ENDãChuck Forsberg XMODEM/YMODEM PROTOCOL REF cbrtjr@ix.netcom.com 02-06-00 (23:53) Text 1648 49538 XYMODM.TXT ããã - 1 -ãããã XMODEM/YMODEM PROTOCOL REFERENCEã A compendium of documents describing theãã XMODEM and YMODEMãã File Transfer Protocolsãããããããããããã Edited by Chuck Forsbergããããããããããããããã Please distribute as widely as possible.ãã Questions to Chuck Forsbergãããããã Omen Technology Incã 17505-V Sauvie Island Roadã Portland Oregon 97231ã Voice: 503-621-3406ã Modem (Telegodzilla): 503-621-3746 Speed 1200,300ã Compuserve: 70715,131ã UUCP: ...!tektronix!reed!omen!cafãããããããããããããããã - 2 -ãããã1. ROSETTA STONEããHere are some definitions which reflect the current vernacular in theãcomputer media. The attempt here is identify the file transfer protocolãrather than specific programs.ããXMODEM refers to the original 1979 file transfer etiquette introduced byã Ward Christensen's 1979 MODEM2 program. It's also called theã MODEM or MODEM2 protocol. Some who are unaware of MODEM7'sã unusual batch file mode call it MODEM7. Other aliases includeã "CP/M Users's Group" and "TERM II FTP 3". This protocol isã supported by every serious communications program because of itsã universality, simplicity, and reasonable performance.ããXMODEM/CRC replaces XMODEM's 1 byte checksum with a two byte Cyclicalã Redunancy Check (CRC-16), giving modern error detectionã protection.ããYMODEM refers to the XMODEM/CRC protocol with the throughput and/or batchã transmission enhancements described below.ããã2. YET ANOTHER PROTOCOL?ããSince its development half a decade ago, the Ward Christensen modemãprotocol has enabled a wide variety of computer systems to interchangeãdata. There is hardly a communications program that doesn't at leastãclaim to support this protocol.ããRecent advances in computing, modems and networking have revealed a numberãof weaknesses in the original protocol:ãã + The short block length caused throughput to suffer when used withã timesharing systems, packet switched networks, satellite circuits,ã and buffered (error correcting) modems.ãã + The 8 bit arithemetic checksum and other aspects allowed lineã impairments to interfere with dependable, accurate transfers.ãã + Only one file could be sent per command. The file name had to beã given twice, first to the sending program and then again to theã receiving program.ãã + The transmitted file could accumulate as many as 127 extraneousã bytes.ãã + The modification date of the file was lost.ããA number of other protocols have been developed over the years, but noneãhave displaced XMODEM to date:ãããããChapter 2ããããããããX/YMODEM Protocol Reference 10-10-85 3ãããã + Lack of public domain documentation and example programs have keptã proprietary protocols such as MNP, Blast, and others tightly bound toã the fortunes of their suppliers.ãã + Complexity discourages the widespread application of BISYNC, SDLC,ã HDLC, X.25, and X.PC protocols.ãã + Performance compromises and moderate complexity have limited theã popularity of the Kermit protocol, which was developed to allow fileã transfers in environments hostile to XMODEM.ããThe YMODEM Protocol extensions were developed as a means of addressing theãweaknesses described above while maintaining XMODEM's simplicity as muchãas possible.ããYMODEM is supported by the public domain programs YAM (CP/M),ãYAM(CP/M-86), YAM(CCPM-86), IMP (CP/M), KMD (CP/M), MODEM76.ASM (CP/M),ãrb/sb (Unix, VMS, Berkeley Unix, Venix, Xenix, Coherent, IDRIS, Regulus)ãas well as Professional-YAM.1 These programs have been in use since 1981.ããThe 1k packet length capability described below may be used in conjunctionãwith the Batch Protocol, or with single file transfers identical to theãXMODEM/CRC protocol except for the minimal changes to support 1k packets.ããAnother extension is simply called the g option. It provides maximumãthroughput when used with end to end error correcting media, such as X.PCãand error correcting modems, including the emerging 9600 bps units byãElectronic Vaults and others.ããTo complete this tome, Ward Christensen's original protocol document andãJohn Byrns's CRC-16 document are included for reference.ããReferences to the MODEM or MODEM7 protocol have been changed to XMODEM toãaccommodate the vernacular. In Australia, it is properly called theãChristensen Portocol.ããWatch for an article describing the YMODEM protocol in a more coherentãfashion later this year. The article will include some interestingãhistory on the development of microcomputer file transfers.ããããããããã__________ãã 1. Available for IBM PC,XT,AT, Unix and XenixãããããChapter 2ããããããããX/YMODEM Protocol Reference 10-10-85 4ãããã2.1 Some Messages from the Pioneerãã#: 130940 S0/Communications 25-Apr-85 18:38:47ãSb: my protocolãFm: Ward Christensen 76703,302 (EDITED)ãTo: allããBe aware the article2 DID quote me correctly in terms of the phrases likeã"not robust", etc.ããIt was a quick hack I threw together, very unplanned (like everything Iãdo), to satisfy a personal need to communicate with "some other" people.ããONLY the fact that it was done in 8/77, and that I put it in the publicãdomain immediately, made it become the standard that it is.ããI think its time for me toãã(1) document it; (people call me and say "my product is going to includeãit - what can I 'reference'", or "I'm writing a paper on it, what do I putãin the bibliography") andãã(2) propose an "incremental extension" to it, which might take "exactly"ãthe form of Chuck Forsberg's YAM protocol. He wrote YAM in C for CP/M andãput it in the public domain, and wrote a batch protocol for Unix3 calledãrb and sb (receive batch, send batch), which was basically XMODEM withã (a) a record 0 containing filename date time and sizeã (b) a 1K block size optionã (c) CRC-16.ããHe did some clever programming to detect false ACK or EOT, but basicallyãleft them the same.ããPeople who suggest I make SIGNIFICANT changes to the protocol, such asã"full duplex", "multiple outstanding blocks", "multiple destinations", etcãetc don't understand that the incredible simplicity of the protocol is oneãof the reasons it survived to this day in as many machines and programs asãit may be found in!ããConsider the PC-NET group back in '77 or so - documenting to beat the bandã- THEY had a protocol, but it was "extremely complex", because it tried toãbe "all things to all people" - i.e. send binary files on a 7-bit system,ãetc. I was not that "benevolent". I (emphasize > I < ) had an 8-bit UART,ããã__________ãã 2. Infoworld April 29 p. 16ãã 3. VAX/VMS versions of these programs are also available.ãããããChapter 2ããããããããX/YMODEM Protocol Reference 10-10-85 5ããããso "my protocol was an 8-bit protocol", and I would just say "sorry" toãpeople who were held back by 7-bit limitations. ...ããBlock size: Chuck Forsberg created an extension of my protocol, calledãYAM, which is also supported via his public domain programs for UNIXãcalled rb and sb - receive batch and send batch. They cleverly send aã"block 0" which contains the filename, date, time, and size.ãUnfortunately, its UNIX style, and is a bit weird4 - octal numbers, etc.ãBUT, it is a nice way to overcome the kludgy "echo the chars of the name"ãintroduced with MODEM7. Further, chuck uses CRC-16 and optional 1Kãblocks. Thus the record 0, 1K, and CRC, make it a "pretty slick newãprotocol" which is not significantly different from my own.ããAlso, there is a catchy name - YMODEM. That means to some that it is theã"next thing after XMODEM", and to others that it is the Y(am)MODEMãprotocol. I don't want to emphasize that too much - out of fear thatãother mfgrs might think it is a "competitive" protocol, rather than anã"unaffiliated" protocol. Chuck is currently selling a much-enhancedãversion of his CP/M-80 C program YAM, calling it Professional Yam, and itsãfor the PC - I'm using it right now. VERY slick! 32K capture buffer,ãscript, scrolling, previously captured text search, plus built-in commandsãfor just about everything - directory (sorted every which way), XMODEM,ãYMODEM, KERMIT, and ASCII file upload/download, etc. You can program itãto "behave" with most any system - for example when trying a number forãCIS it detects the "busy" string back from the modem and substitutes aãdiff phone # into the dialing string and branches back to try it.ãããã3. XMODEM PROTOCOL ENHANCEMENTSããThis chapter discusses the protocol extensions to Ward Christensen's 1982ãXMODEM protocol description document.ããThe original document recommends the user be asked wether to continueãtrying or abort after 10 retries. Most programs no longer ask theãoperator whether he wishes to keep retrying. Virtually all correctableãerrors are corrected within the first few retransmissions. If the line isãso bad that ten attempts are insufficient, there is a significant dangerãof undetected errors. If the connection is that bad, it's better toãredial for a better connection, or mail a floppy disk.ãããããã__________ãã 4. The file length, time, and file mode are optional. The pathname andã file length may be sent alone if desired.ãããããChapter 3 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 6ãããã3.1 Graceful AbortããYAM and Professional-YAM recognize a sequence of two consecutive CAN (Hexã18) characters without modem errors (overrun, framing, etc.) as a transferãabort command.1 The check for two consecutive CAN characters virtuallyãeliminates the possibility of a line hit aborting the transfer. YAM sendsãfive CAN characters when it aborts an XMODEM or YMODEM protocol fileãtransfer, followed by five backspaces to delete the CAN characters fromãthe remote's keyboard input buffer (in case the remote had already abortedãthe transfer).ããã3.2 CRC-16 OptionããThe XMODEM protocol uses an optional two character CRC-16 instead of theãone character arithmetic checksum used by the original protocol and byãmost commercial implementations. CRC-16 guarantees detection of allãsingle and double bit errors, all errors with an odd number of errorãbits, all burst errors of length 16 or less, 99.9969% of all 17-bit errorãbursts, and 99.9984 per cent of all possible longer error bursts. Byãcontrast, a double bit error, or a burst error of 9 bits or more can sneakãpast the XMODEM protocol arithmetic checksum.ããThe XMODEM/CRC protocol is similar to the XMODEM protocol, except that theãreceiver specifies CRC-16 by sending C (Hex 43) instead of NAK whenãrequesting the FIRST packet. A two byte CRC is sent in place of the oneãbyte arithmetic checksum.ããYAM's c option to the r command enables CRC-16 in single file reception,ãcorresponding to the original implementation in the MODEM7 seriesãprograms. This remains the default because many commercial communicationsãprograms and bulletin board systems still do not support CRC-16,ãespecially those written in Basic or Pascal.ããXMODEM protocol with CRC is accurate provided both sender and receiverãboth report a successful transmission. The protocol is robust in theãpresence of characters lost by buffer overloading on timesharing systems.ããThe single character ACK/NAK responses generated by the receiving programãadapt well to split speed modems, where the reverse channel is limited toãten per cent or less of the main channel's speed.ããXMODEM and YMODEM are half duplex protocols which do not attempt toãtransmit information and control signals in both directions at the sameããã__________ãã 1. This is recognized when YAM is waiting for the beginning of a packetã or for an acknowledge to one that has been sent.ãããããChapter 3 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 7ããããtime. This avoids buffer overrun problems that have been reported byãusers attempting to exploit full duplex aynchronous file transferãprotocols such as Blast.ããProfessional-YAM adds several proprietary logic enhancements to XMODEM'sãerror detection and recovery. These compatible enhancements eliminateãmost of the bad file transfers other programs make when using the XMODEMãprotocol under less than ideal conditions.ããã3.3 1024 Byte Packet OptionããThe choice to use 1024 byte packets is expressed to the sending program onãits command line or selection menu.ããPrograms using the Hoff protocol use a two character sequence emitted byãthe receiver (CK) to automatically trigger the use of 1024 byte packets asãan alternative to specifying this option on this command line. Althoughãthis two character sequence works well on single process micros in directãcommunication, timesharing systems and packet switched networks canãseparate the successive characters by several seconds, rendering thisãmethod unreliable.ããAn STX (02) replaces the SOH (01) at the beginning of the transmittedãblock to notify the receiver of the longer packet length. The transmittedãpacket contains 1024 bytes of data. The receiver should be able to acceptãany mixture of 128 and 1024 byte packets. The packet number isãincremented by one for each packet regardless of the packet length.ããThe sender must not change between 128 and 1024 byte packet lengths if itãhas not received a valid ACK for the current packet. Failure to observeãthis restriction allows certain transmission errors to pass undetected.ããIf 1024 byte packets are being used, it is possible for a file to "grow"ãup to the next multiple of 1024 bytes. This does not waste disk space ifãthe allocation granularity is 1k or greater. When 1024 byte packets areãused with YMODEM batch transmission, the file length transmitted in theãfile name packet allows the receiver to discard the padding, preservingãthe exact file length and contents.ããCRC-16 should be used with the k option to preserve data integrity overãphone lines.2 1024 byte packets may be used with batch file transmissionãor with single file transmission.ããããã__________ãã 2. Some programs enforce this recommendation.ãããããChapter 3 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 8ãããã Figure 1. 1024 byte Packetsãã SENDER RECEIVERã "s -k foo.bar"ã "foo.bar open x.x minutes"ã Cã STX 01 FE Data[1024] CRC CRCã ACKã STX 02 FD Data[1024] CRC CRCã ACKã STX 03 FC Data[1000] CPMEOF[24] CRC CRCã ACKã EOTã ACKãã Figure 2. Mixed 1024 and 128 byte Packetsãã SENDER RECEIVERã "s -k foo.bar"ã "foo.bar open x.x minutes"ã Cã STX 01 FE Data[1024] CRC CRCã ACKã STX 02 FD Data[1024] CRC CRCã ACKã SOH 03 FC Data[128] CRC CRCã ACKã SOH 04 FB Data[100] CPMEOF[28] CRC CRCã ACKã EOTã ACKãã4. YMODEM Batch File TransmissionããThe YMODEM Batch protocol is an extension to the XMODEM/CRC protocol thatãallows 0 or more files to be transmitted with a single command. (Zeroãfiles may be sent if none of the requested files is accessible.) Theãdesign approach of the YMODEM Batch protocol is to use the normal routinesãfor sending and receiving XMODEM packets in a layered fashion similar toãpacket switching methods.ããWhy was it necessary to design a new batch protocol when one alreadyãexisted in MODEM7?1 The batch file mode used by MODEM7 is unsuitableããã__________ãã 1. The MODEM7 batch protocol transmitted CP/M FCB bytes f1...f8 andã t1...t3 one character at a time. The receiver echoed these bytes asã received, one at a time.ãããããChapter 4 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 9ããããbecause it does not permit full pathnames, file length, file date, orãother attribute information to be transmitted. Such a restrictive design,ãhastily implemented with only CP/M in mind, would not have permittedãextensions to current areas of personal computing such as Unix, DOS, andãobject oriented systems. In addition, the MODEM7 batch file mode isãsomewhat susceptible to transmission impairments.ããAs in the case of single a file transfer, the receiver initiates batchãfile transmission by sending a "C" character (for CRC-16).ããThe sender opens the first file and sends packet number 0 with theãfollowing information.2ããOnly the pathname (file name) part is required for batch transfers.ããTo maintain upwards compatibility, all unused bytes in packet 0 must beãset to null.ããPathname The pathname (conventionally, the file name) is sent as a nullã terminated ASCII string. This is the filename format used by theã handle oriented MSDOS(TM) functions and C library fopen functions.ã An assembly language example follows:ã DB 'foo.bar',0ã No spaces are included in the pathname. Normally only the file nameã stem (no directory prefix) is transmitted unless the sender hasã selected YAM's f option to send the full pathname. The source driveã (A:, B:, etc.) is never sent.ãã Filename Considerations:ãã + File names should be translated to lower case unless the sendingã system supports upper/lower case file names. This is aã convenience for users of systems (such as Unix) which storeã filenames in upper and lower case.ãã + The receiver should accommodate file names in lower and upperã case.ãã + The rb(1) program on Unix systems normally translates theã filename to lower case unless one or more letters in theã filename are already in lower case.ãã + When transmitting files between different operating systems,ã file names must be acceptable to both the sender and receivingã operating systems.ããã__________ãã 2. Only the data part of the packet is described here.ãããããChapter 4 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 10ãããã If directories are included, they are delimited by /; i.e.,ã "subdir/foo" is acceptable, "subdir\foo" is not.ããLength The file length and each of the succeeding fields are optional.3ã The length field is stored in the packet as a decimal string countingã the number of data bytes in the file. The file length does notã include any CPMEOF (^Z) characters used to pad the last packet.ãã If the file being transmitted is growing during transmission, theã length field should be set to at least the final expected fileã length, or not sent.ãã The receiver stores the specified number of characters, discardingã any padding added by the sender to fill up the last packet.ããModification Date A single space separates the modification date from theã file length.ãã The mod date is optional, and the filename and length may be sentã without requiring the mod date to be sent.ãã The mod date is sent as an octal number giving the time the contentsã of the file were last changed measured in seconds from Jan 1 1970ã Universal Coordinated Time (GMT). A date of 0 implies theã modification date is unknown and should be left as the date the fileã is received.ãã This standard format was chosen to eliminate ambiguities arising fromã transfers between different time zones.ãã Two Microsoft blunders complicate the use of modification dates inã file transfers with MSDOS(TM) systems. The first is the lack ofã timezone standardization in MS-DOS. A file's creation time can notã be known unless the timezone of the system that wrote the file4 isã known. Unix solved this problem (for planet Earth, anyway) byã stamping files with Universal Time (GMT). Microsoft would have toã include the timezone of origin in the directory entries, but doesã not. Professional-YAM gets around this problem by using the zã parameter which is set to the number of minutes local time lags GMT.ã For files known to originate from a different timezone, the -zTã option may be used to specify T as the timezone for an individualã file transfer.ãããã__________ãã 3. Fields may not be skipped.ãã 4. Not necessarily that of the transmitting system!ãããããChapter 4 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 11ãããã The second problem is the lack of a separate file creation date inã DOS. Since some backup schemes used with DOS rely on the fileã creation date to select files to be copied to the archive, back-ã dating the file modification date could interfere with the safety ofã the transferred files. For this reason, Professional-YAM does notã modify the date of received files with the header information unlessã the d parameter is non zero.ãããMode A single space separates the file mode from the modification date.ã The file mode is stored as an octal string. Unless the fileã originated from a Unix system, the file mode is set to 0. rb(1)ã checks the file mode for the 0x8000 bit which indicates a Unix typeã regular file. Files with the 0x8000 bit set are assumed to have beenã sent from another Unix (or similar) system which uses the same fileã conventions. Such files are not translated in any way.ãããSerial Number A single space separates the serial number from the fileã mode. The serial number of the transmitting program is stored as anã octal string. Programs which do not have a serial number should omitã this field, or set it to 0. The receiver's use of this field isã optional.ããThe rest of the packet is set to nulls. This is essential to preserveãupward compatibility.5 After the filename packet has been received, it isãACK'ed if the write open is successful. The receiver then initiatesãtransfer of the file contents according to the standard XMODEM/CRCãprotocol. If the file cannot be opened for writing, the receiver cancelsãthe transfer with CAN characters as described above.ããAfter the file contents have been transmitted, the receiver again asks forãthe next pathname. Transmission of a null pathname terminates batch fileãtransmission. Note that transmission of no files is not necessarily anãerror. This is possible if none of the files requested of the senderãcould be opened for reading.ããIn batch transmission, the receiver automatically requests CRC-16.ããThe Unix programs sb(1) and rb(1) included in the source code fileãRBSB.SHQ (rbsb.sh) should answer other questions about YMODEM batchãprotocol.ãããã__________ãã 5. If, perchance, this information extends beyond 128 bytes (possibleã with Unix 4.2 BSD extended file names), the packet should be sent as aã 1k packet as described above.ãããããChapter 4 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 12ãããã Figure 3. Batch Transmission Sessionãã SENDER RECEIVERã "sb foo.*"ã "sending in batch mode etc."ã C (command:rb)ã SOH 00 FF foo.c NUL[123] CRC CRCã ACKã Cã SOH 01 FE Data[128] CRC CRCã ACKã SOH 02 FD Data[1024] CRC CRCã ACKã SOH 03 FC Data[128] CRC CRCã ACKã SOH 04 FB Data[100] CPMEOF[28] CRC CRCã ACKã EOTã NAKã EOTã ACKã Cã SOH 00 FF NUL[128] CRC CRCã ACKãã Figure 4. Filename packet transmitted by sbãã -rw-r--r-- 6347 Jun 17 1984 20:34 bbcsched.txtãã 00 0100FF62 62637363 6865642E 74787400 |...bbcsched.txt.|ã 10 36333437 20333331 34373432 35313320 |6347 3314742513 |ã 20 31303036 34340000 00000000 00000000 |100644..........|ã 30 00000000 00000000 00000000 00000000ã 80 000000CA 56ãããããããããããããããããããããChapter 4 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 13ãããã Figure 5. Header Information used by YMODEM Implementationsããã_____________________________________________________________________ã| Program | Batch | Length | Date | Mode | S/N | 1k-Blk | g-Option |ã|___________|_______|________|______|______|_____|________|__________|ã|Unix rb/sb | yes | yes | yes | yes | no | yes | sb only |ã|___________|_______|________|______|______|_____|________|__________|ã|VMS rb/sb | yes | yes | no | no | no | yes | no |ã|___________|_______|________|______|______|_____|________|__________|ã|Pro-YAM | yes | yes | yes | no | yes | yes | yes |ã|___________|_______|________|______|______|_____|________|__________|ã|CP/M YAM | yes | no | no | no | no | yes | no |ã|___________|_______|________|______|______|_____|________|__________|ã|KMD/IMP | yes | no | no | no | no | yes | no |ã|___________|_______|________|______|______|_____|________|__________|ã|MEX | no | no | no | no | no | yes | no |ã|___________|_______|________|______|______|_____|________|__________|ãã4.1 IMP/KMD Record CountããDue to programming constraints, these programs do not send the file lengthãas described above. Instead, they send (and look for) the CP/M recordãcount stored in the last two bytes of the header packet. The leastãsignificant bits are stored in the penultimate byte.ããKMD and IMP use the record count to allow the receiving program to displayãthe file size and estimated transmission time; the file length isãdetermined by the actual number of records sent.ããã5. g Option File TransmissionããDeveloping technology is providing phone line data transmission at everãhigher speeds using very specialized techniques. These high speed modems,ãas well as session protocols such as X.PC, provide high speed, error freeãcommunications at the expense of considerably increased delay time.ããThis delay time is moderate compared to human interactions, but itãcripples the throughput of most error correcting protocols.ããThe g option to YMODEM has proven effective under these circumstances.ãThe g option is driven by the receiver, which initiates the batch transferãby transmitting a G instead of C. When the sender recognizes the G, itãbypasses the usual wait for an ACK to each transmitted packet, sendingãsucceeding packets at full speed, subject to XOFF/XON or other flowãcontrol exerted by the medium.ããThe sender expects an inital G to initiate the transmission of aãparticular file, and also expects an ACK on the EOT sent at the end ofãeach file. This synchronization allows the receiver time to open andããããChapter 5 XMODEM Protocol EnhancementsããããããããX/YMODEM Protocol Reference 10-10-85 14ããããclose files as necessary.ããã Figure 6. g Option Transmission Sessionãã SENDER RECEIVERã "sb foo.*"ã "sending in batch mode etc..."ã G (command:rb -g)ã SOH 00 FF foo.c NUL[123] CRC CRCã Gã SOH 01 FE Data[128] CRC CRCã SOH 02 FD Data[1024] CRC CRCã SOH 03 FC Data[128] CRC CRCã SOH 04 FB Data[100] CPMEOF[28] CRC CRCã EOTã ACKã Gã SOH 00 FF NUL[128] CRC CRCããã6. XMODEM PROTOCOL OVERVIEWãã8/9/82 by Ward Christensen.ããI will maintain a master copy of this. Please pass on changes orãsuggestions via CBBS/Chicago at (312) 545-8086, CBBS/CPMUG (312) 849-1132ãor by voice at (312) 849-6279.ãã6.1 Definitionsãã 01Hã 04Hã 06Hã 15Hã 18Hã 43Hããã6.2 Transmission Medium Level ProtocolããAsynchronous, 8 data bits, no parity, one stop bit.ããThe protocol imposes no restrictions on the contents of the data beingãtransmitted. No control characters are looked for in the 128-byte dataãmessages. Absolutely any kind of data may be sent - binary, ASCII, etc.ãThe protocol has not formally been adopted to a 7-bit environment for theãtransmission of ASCII-only (or unpacked-hex) data , although it could beãsimply by having both ends agree to AND the protocol-dependent data withã7F hex before validating it. I specifically am referring to the checksum,ãand the block numbers and their ones- complement.ããããChapter 6 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 15ããããThose wishing to maintain compatibility of the CP/M file structure, i.e.ãto allow modemming ASCII files to or from CP/M systems should follow thisãdata format:ãã + ASCII tabs used (09H); tabs set every 8.ãã + Lines terminated by CR/LF (0DH 0AH)ãã + End-of-file indicated by ^Z, 1AH. (one or more)ãã + Data is variable length, i.e. should be considered a continuousã stream of data bytes, broken into 128-byte chunks purely for theã purpose of transmission.ãã + A CP/M "peculiarity": If the data ends exactly on a 128-byteã boundary, i.e. CR in 127, and LF in 128, a subsequent sectorã containing the ^Z EOF character(s) is optional, but is preferred.ã Some utilities or user programs still do not handle EOF without ^Zs.ãã + The last block sent is no different from others, i.e. there is noã "short block".ã Figure 7. XMODEM Message Block Level ProtocolããEach block of the transfer looks like:ã <255-blk #><--128 data bytes-->ãin which:ã = 01 hexã = binary number, starts at 01 increments by 1, andã wraps 0FFH to 00H (not to 01)ã<255-blk #> = blk # after going thru 8080 "CMA" instr, i.e.ã each bit complemented in the 8-bit block number.ã Formally, this is the "ones complement".ã = the sum of the data bytes only. Toss any carry.ãã6.3 File Level Protocolãã6.3.1 Common_to_Both_Sender_and_ReceiverãAll errors are retried 10 times. For versions running with an operatorã(i.e. NOT with XMODEM), a message is typed after 10 errors asking theãoperator whether to "retry or quit".ããSome versions of the protocol use , ASCII ^X, to cancel transmission.ãThis was never adopted as a standard, as having a single "abort" characterãmakes the transmission susceptible to false termination due to an ã or being corrupted into a and cancelling transmission.ããThe protocol may be considered "receiver driven", that is, the sender needãnot automatically re-transmit, although it does in the currentãimplementations.ããããããChapter 6 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 16ãããã6.3.2 Receive_Program_ConsiderationsãThe receiver has a 10-second timeout. It sends a every time itãtimes out. The receiver's first timeout, which sends a , signals theãtransmitter to start. Optionally, the receiver could send a ãimmediately, in case the sender was ready. This would save the initial 10ãsecond timeout. However, the receiver MUST continue to timeout every 10ãseconds in case the sender wasn't ready.ããOnce into a receiving a block, the receiver goes into a one-second timeoutãfor each character and the checksum. If the receiver wishes to aãblock for any reason (invalid header, timeout receiving data), it mustãwait for the line to clear. See "programming tips" for ideasããSynchronizing: If a valid block number is received, it will be: 1) theãexpected one, in which case everything is fine; or 2) a repeat of theãpreviously received block. This should be considered OK, and onlyãindicates that the receivers got glitched, and the sender re-ãtransmitted; 3) any other block number indicates a fatal loss ofãsynchronization, such as the rare case of the sender getting a line-glitchãthat looked like an . Abort the transmission, sending a ããã6.3.3 Sending_program_considerationsãWhile waiting for transmission to begin, the sender has only a single veryãlong timeout, say one minute. In the current protocol, the sender has aã10 second timeout before retrying. I suggest NOT doing this, and lettingãthe protocol be completely receiver-driven. This will be compatible withãexisting programs.ããWhen the sender has no more data, it sends an , and awaits an ,ãresending the if it doesn't get one. Again, the protocol could beãreceiver-driven, with the sender only having the high-level 1-minuteãtimeout to abort.ãããHere is a sample of the data flow, sending a 3-block message. It includesãthe two most common line hits - a garbaged block, and an replyãgetting garbaged. represents the checksum byte.ãããããããããããããããããChapter 6 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 17ãããã Figure 8. Data flow including Error RecoveryããSENDER RECEIVERã times out after 10 seconds,ã <--- ã 01 FE -data- --->ã <--- ã 02 FD -data- xx ---> (data gets line hit)ã <--- ã 02 FD -data- xx --->ã <--- ã 03 FC -data- xx --->ã(ack gets garbaged) <--- ã 03 FC -data- xx ---> ã --->ã <--- ã --->ã <--- ã(finished)ãã6.4 Programming Tipsãã + The character-receive subroutine should be called with a parameterã specifying the number of seconds to wait. The receiver should firstã call it with a time of 10, then and try again, 10 times.ãã After receiving the , the receiver should call the characterã receive subroutine with a 1-second timeout, for the remainder of theã message and the . Since they are sent as a continuous stream,ã timing out of this implies a serious like glitch that caused, say,ã 127 characters to be seen instead of 128.ãã + When the receiver wishes to , it should call a "PURGE"ã subroutine, to wait for the line to clear. Recall the sender tossesã any characters in its UART buffer immediately upon completing sendingã a block, to ensure no glitches were mis- interpreted.ãã The most common technique is for "PURGE" to call the characterã receive subroutine, specifying a 1-second timeout,1 and looping backã to PURGE until a timeout occurs. The is then sent, ensuringã the other end will see it.ãã + You may wish to add code recommended by John Mahr to your characterã receive routine - to set an error flag if the UART shows framingã error, or overrun. This will help catch a few more glitches - theããã__________ãã 1. These times should be adjusted for use with timesharing systems.ãããããChapter 6 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 18ãããã most common of which is a hit in the high bits of the byte in twoã consecutive bytes. The comes out OK since counting in 1-byteã produces the same result of adding 80H + 80H as with adding 00H +ã 00H.ãããã7. XMODEM/CRC Overviewãã1/13/85 by John Byrns -- CRC option.ããPlease pass on any reports of errors in this document or suggestions forãimprovement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312)ã885-1105.ããThe CRC used in the Modem Protocol is an alternate form of block checkãwhich provides more robust error detection than the original checksum.ãAndrew S. Tanenbaum says in his book, Computer Networks, that the CRC-ãCCITT used by the Modem Protocol will detect all single and double bitãerrors, all errors with an odd number of bits, all burst errors of lengthã16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit andãlonger bursts.ããThe changes to the Modem Protocol to replace the checksum with the CRC areãstraight forward. If that were all that we did we would not be able toãcommunicate between a program using the old checksum protocol and oneãusing the new CRC protocol. An initial handshake was added to solve thisãproblem. The handshake allows a receiving program with CRC capability toãdetermine whether the sending program supports the CRC option, and toãswitch it to CRC mode if it does. This handshake is designed so that itãwill work properly with programs which implement only the originalãprotocol. A description of this handshake is presented in section 10.ãã Figure 9. Message Block Level Protocol, CRC modeããEach block of the transfer in CRC mode looks like:ã <255-blk #><--128 data bytes-->ãin which:ã = 01 hexã = binary number, starts at 01 increments by 1, andã wraps 0FFH to 00H (not to 01)ã<255-blk #> = ones complement of blk #.ã = byte containing the 8 hi order coefficients of the CRC.ã = byte containing the 8 lo order coefficients of the CRC.ãã7.1 CRC Calculationãã7.1.1 Formal_DefinitionãTo calculate the 16 bit CRC the message bits are considered to be theãcoefficients of a polynomial. This message polynomial is first multipliedãby X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 +ããããChapter 7 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 19ãããã1) using modulo two arithmetic. The remainder left after the division isãthe desired CRC. Since a message block in the Modem Protocol is 128 bytesãor 1024 bits, the message polynomial will be of order X^1023. The hi orderãbit of the first byte of the message block is the coefficient of X^1023 inãthe message polynomial. The lo order bit of the last byte of the messageãblock is the coefficient of X^0 in the message polynomial.ãã Figure 10. Example of CRC Calculation written in Cãã/*ã * This function calculates the CRC used by the XMODEM/CRC Protocolã * The first argument is a pointer to the message block.ã * The second argument is the number of bytes in the message block.ã * The function returns an integer which contains the CRC.ã * The low order 16 bits are the coefficients of the CRC.ã */ãint calcrc(ptr, count)ãchar *ptr;ãint count;ã{ã int crc, i;ãã crc = 0;ã while (--count >= 0) {ã crc = crc ^ (int)*ptr++ << 8;ã for (i = 0; i < 8; ++i)ã if (crc & 0x8000)ã crc = crc << 1 ^ 0x1021;ã elseã crc = crc << 1;ã }ã return (crc & 0xFFFF);ã}ãã7.2 CRC File Level Protocol Changesãã7.2.1 Common_to_Both_Sender_and_ReceiverãThe only change to the File Level Protocol for the CRC option is theãinitial handshake which is used to determine if both the sending and theãreceiving programs support the CRC mode. All Modem Programs should supportãthe checksum mode for compatibility with older versions. A receivingãprogram that wishes to receive in CRC mode implements the mode settingãhandshake by sending a in place of the initial . If the sendingãprogram supports CRC mode it will recognize the and will set itselfãinto CRC mode, and respond by sending the first block as if a hadãbeen received. If the sending program does not support CRC mode it willãnot respond to the at all. After the receiver has sent the it willãwait up to 3 seconds for the that starts the first block. If itãreceives a within 3 seconds it will assume the sender supports CRCãmode and will proceed with the file exchange in CRC mode. If no isãreceived within 3 seconds the receiver will switch to checksum mode, sendããããChapter 7 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 20ããããa , and proceed in checksum mode. If the receiver wishes to useãchecksum mode it should send an initial and the sending programãshould respond to the as defined in the original Modem Protocol.ãAfter the mode has been set by the initial or the protocolãfollows the original Modem Protocol and is identical whether the checksumãor CRC is being used.ããã7.2.2 Receive_Program_ConsiderationsãThere are at least 4 things that can go wrong with the mode settingãhandshake.ãã 1. the initial can be garbled or lost.ãã 2. the initial can be garbled.ãã 3. the initial can be changed to a .ãã 4. the initial from a receiver which wants to receive in checksumã can be changed to a .ããThe first problem can be solved if the receiver sends a second afterãit times out the first time. This process can be repeated several times.ãIt must not be repeated too many times before sending a andãswitching to checksum mode or a sending program without CRC support mayãtime out and abort. Repeating the will also fix the second problem ifãthe sending program cooperates by responding as if a were receivedãinstead of ignoring the extra .ããIt is possible to fix problems 3 and 4 but probably not worth the troubleãsince they will occur very infrequently. They could be fixed by switchingãmodes in either the sending or the receiving program after a large numberãof successive s. This solution would risk other problems however.ããã7.2.3 Sending_Program_ConsiderationsãThe sending program should start in the checksum mode. This will insureãcompatibility with checksum only receiving programs. Anytime a isãreceived before the first or the sending program should setãitself into CRC mode and respond as if a were received. The senderãshould respond to additional s as if they were s until the firstã is received. This will assist the receiving program in determiningãthe correct mode when the is lost or garbled. After the first ãis received the sending program should ignore s.ãããããããããããChapter 7 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 21ãããã7.3 Data Flow Examples with CRC OptionããHere is a data flow example for the case where the receiver requestsãtransmission in the CRC mode but the sender does not support the CRCãoption. This example also includes various transmission errors. ãrepresents the checksum byte.ãã Figure 11. Data Flow: Receiver has CRC Option, Sender Doesn'tããSENDER RECEIVERã <--- ã times out after 3 seconds,ã <--- ã times out after 3 seconds,ã <--- ã times out after 3 seconds,ã <--- ã times out after 3 seconds,ã <--- ã 01 FE -data- --->ã <--- ã 02 FD -data- ---> (data gets line hit)ã <--- ã 02 FD -data- --->ã <--- ã 03 FC -data- --->ã (ack gets garbaged) <--- ã times out after 10 seconds,ã <--- ã 03 FC -data- --->ã <--- ã --->ã <--- ããHere is a data flow example for the case where the receiver requestsãtransmission in the CRC mode and the sender supports the CRC option. Thisãexample also includes various transmission errors. represents theã2 CRC bytes.ãããããããããããããããããChapter 7 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 22ãããã Figure 12. Receiver and Sender Both have CRC OptionããSENDER RECEIVERã <--- ã 01 FE -data- --->ã <--- ã 02 FD -data- ---> (data gets line hit)ã <--- ã 02 FD -data- --->ã <--- ã 03 FC -data- --->ã(ack gets garbaged) <--- ã times out after 10 seconds,ã <--- ã 03 FC -data- --->ã <--- ã --->ã <--- ããã8. MORE INFORMATIONããMore information may be obtained by calling Telegodzilla at 503-621-3746.ãHit RETURNs for baud rate detection.ããA version this file with boldface, underlining, and superscripts forãprinting on Epson or Gemini printers is available on Telegodzilla asã"YMODEME.DOC" or "YMODEME.DQC".ããUUCP sites can obtain this file withã uucp omen!/usr/spool/uucppublic/ymodem.doc /tmpããThe following L.sys line calls Telegodzilla (Pro-YAM in host operation).ãTelegodzilla waits for carriage returns to determine the incoming speed.ãIf none is detected, 1200 bps is assumed and a greeting is displayed.ããIn response to "Name Please:" uucico gives the Pro-YAM "link" command as aãuser name. The password (Giznoid) controls access to the Xenix systemãconnected to the IBM PC's other serial port. Communications betweenãPro-YAM and Xenix use 9600 bps; YAM converts this to the caller's speed.ããFinally, the calling uucico logs in as uucp.ããomen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucpããContact omen!caf if you wish the troff sources.ãããããããããChapter 9 Xmodem Protocol OverviewããããããããX/YMODEM Protocol Reference 10-10-85 23ãããã9. YMODEM ProgramsããA demonstration version of Professional-YAM is available as YAMDEMO.LQR (AãSQueezed Novosielski library). This may be used to test YMODEMãimplementations.ããUnix programs supporting the YMODEM protocol are available on Telegodzillaãin the "upgrade" subdirectory as RBSB.SHQ (a SQueezed shell archive).ãMost Unix like systems are supported, including V7, Sys III, 4.2 BSD, SYSãV, Idris, Coherent, and Regulus.ããA version for VAX-VMS is available in VRBSB.SHQ, in the same directory.ããA CP/M assembly version is available as MODEM76.AQM and MODEM7.LIB.ããIrv Hoff has added YMODEM 1k packets and YMODEM batch transfers to the KMDãand IMP series programs, which replace the XMODEM and MODEM7/MDM7xx seriesãrespectively. Overlays are available for a wide variety of CP/M systems.ããMEX and MEX-PC also support some of the YMODEM extensions.ããQuestions about YMODEM, the Professional-YAM communications program, andãrequests for evaluation copies may be directed to:ã Chuck Forsbergã Omen Technology Incã 17505-V Sauvie Island Roadã Portland Oregon 97231ã Voice: 503-621-3406ã Modem: 503-621-3746 Speed: 1200,300ã Usenet: ...!tektronix!reed!omen!cafã Compuserve: 70715,131ã Source: TCE022ãããããããããããããããããããããããChapter 9 Xmodem Protocol Overviewãããããããããããã CONTENTSããã1. ROSETTA STONE..................................................... 2ãã2. YET ANOTHER PROTOCOL?............................................. 2ã 2.1 Some Messages from the Pioneer............................... 4ãã3. XMODEM PROTOCOL ENHANCEMENTS...................................... 5ã 3.1 Graceful Abort............................................... 6ã 3.2 CRC-16 Option................................................ 6ã 3.3 1024 Byte Packet Option...................................... 7ãã4. YMODEM Batch File Transmission.................................... 8ã 4.1 IMP/KMD Record Count......................................... 13ãã5. g Option File Transmission........................................ 13ãã6. XMODEM PROTOCOL OVERVIEW.......................................... 14ã 6.1 Definitions.................................................. 14ã 6.2 Transmission Medium Level Protocol........................... 14ã 6.3 File Level Protocol.......................................... 15ã 6.4 Programming Tips............................................. 17ãã7. XMODEM/CRC Overview............................................... 18ã 7.1 CRC Calculation.............................................. 18ã 7.2 CRC File Level Protocol Changes.............................. 19ã 7.3 Data Flow Examples with CRC Option........................... 21ãã8. MORE INFORMATION.................................................. 22ãã9. YMODEM Programs................................................... 23ããããããããããããããããããããããã - i -ããããããããããããããã LIST OF FIGURESããã Figure 1. 1024 byte Packets......................................... 7ãã Figure 2. Mixed 1024 and 128 byte Packets........................... 7ãã Figure 3. Batch Transmission Session................................ 11ãã Figure 4. Filename packet transmitted by sb......................... 11ãã Figure 5. Header Information used by YMODEM Implementations......... 13ãã Figure 6. g Option Transmission Session............................. 14ãã Figure 7. XMODEM Message Block Level Protocol....................... 15ãã Figure 8. Data flow including Error Recovery........................ 17ãã Figure 9. Message Block Level Protocol, CRC mode.................... 18ããFigure 10. Example of CRC Calculation written in C................... 19ããFigure 11. Data Flow: Receiver has CRC Option, Sender Doesn't........ 21ããFigure 12. Receiver and Sender Both have CRC Option.................. 22ãããããããããããããããããããããããããã - ii -ããeãSebastian Mate TCP/IP Network Analyzer JMate@t-online.de 06-15-01 (19:34) QB, PDS 583 18375 Sniffer.bas ' -------------------------------------------------------------------------ã' TCP/IP Network Analyzer ("sniffer") for QuickBasicã' -------------------------------------------------------------------------ã' version 1.00, (C) 2001 Sebastian Mateã'ã' Before you use this software, you *must* agree with README.TXT!ããDEFINT A-ZãREM $STATICãDECLARE SUB Main ()ãDECLARE SUB GetAddress ()ãDECLARE SUB ShowInfo ()ãDECLARE SUB ShowError (in%)ãDECLARE SUB FreeBuffer CDECL ()ãDECLARE SUB ReleaseType CDECL (BYVAL Handle)ãDECLARE SUB SetRcvMode CDECL (BYVAL Handle, BYVAL Mode)ãDECLARE FUNCTION NewBuffer CDECL ()ãDECLARE FUNCTION GetCounterA CDECL ()ãDECLARE FUNCTION GetCounterB CDECL ()ãDECLARE FUNCTION GetCountX CDECL ()ãDECLARE FUNCTION GetBufferSegment CDECL ()ãDECLARE FUNCTION GetBufferOffset CDECL ()ãDECLARE FUNCTION AccessType CDECL (BYVAL class, BYVAL tpe, BYVAL number, BYVAL tpe2, BYVAL driver)ããDIM SHARED BUFFER AS STRING * 10, BUFFER2 AS STRING, CLASS1(1 TO 100) AS STRING, IFTYPE AS STRING * 2ãDIM SHARED IPBUFFER(1 TO 256) AS STRINGããTYPE RegType 'Define the registersã AX AS INTEGERã BX AS INTEGERã cx AS INTEGERã DX AS INTEGERã BP AS INTEGERã SI AS INTEGERã DI AS INTEGERã FLAGS AS INTEGERã DS AS INTEGERã ES AS INTEGERãEND TYPEããDIM SHARED regs AS RegType 'Create an array of registersããCLSããFOR n% = 1 TO 100ã READ CLASS1(n%)ãNEXT n%ãã' -----------------------------------------------------------------------ããMain 'The program seems to work only if it's in a sub?!ãã' -----------------------------------------------------------------------ãã' The Ethernet types. I use a datafield instead of 100 IF-commands :-)ãDATA "3COM 3C500/3C501"ãDATA "3COM 3C505"ãDATA "InterLan NI50103"ãDATA "BICC Data Networks 4110"ãDATA "BICC Data Networks 4117"ãDATA "InterLan NP600"ãDATA "???"ãDATA "Ungermann-Bass PC-NIC"ãDATA "Univation NC-516"ãDATA "TRW PC-2000"ãDATA "InterLan NI5210"ãDATA "3COM 3C503"ãDATA "3COM 3C523"ãDATA "Western Digital WD8003"ãDATA "Spider Systems S4"ãDATA "Torus Frame Level"ãDATA "10NET Communications"ãDATA "Gateway PC-bus"ãDATA "Gateway AT-bus"ãDATA "Gateway MCA-bus"ãDATA "IMC Pcnic"ãDATA "IMC PCnic II"ãDATA "IMC PCnic 8bit"ãDATA "Tigan Communications"ãDATA "Micromatic Research"ãDATA "Clarkson Multiplexor"ãDATA "D-Link 8-bit"ãDATA "D-Link 16-bit"ãDATA "D-Link PS/2"ãDATA "Research Machines parallel"ãDATA "Research Machines 16"ãDATA "Research Machines MCA"ãDATA "Radix Microsys. EXM1 16-bit"ãDATA "InterLan NI9210"ãDATA "InterLan NI6510"ãDATA "Vestra LANMASTER 16-bit"ãDATA "Vestra LANMASTER 8-bit"ãDATA "Allied Telesis PC/XT/AT"ãDATA "Allied Telesis NEC PC-98"ãDATA "Allied Telesis Fujitsu FMR"ãDATA "Ungermann-Bass NIC/PS2"ãDATA "Tiara LANCard/E AT"ãDATA "Tiara LANCard/E MC"ãDATA "Tiara LANCard/E TP"ãDATA "Spider Comm. SpiderComm 8"ãDATA "Spider Comm. SpiderComm 16"ãDATA "AT&T Starlan NAU"ãDATA "AT&T Starlan-10 NAU"ãDATA "AT&T Ethernet NAU"ãDATA "Intel smart card"ãDATA "Xircom Pocket Adapter / Credit Card Adapter"ãDATA "Aquila Ethernet"ãDATA "Novell NE-1000"ãDATA "Novell NE-2000"ãDATA "IMC PC-510"ãDATA "AT&T Fiber NAU"ãDATA "NDIS to Packet Driver adapter"ãDATA "InterLan ES3210"ãDATA "General Systems ISDN simulated Ether"ãDATA "Hewlett-Packard"ãDATA "IMC EtherNic-8"ãDATA "IMC EtherNic-16"ãDATA "IMC EtherNic-MCA"ãDATA "NetWorth EtherNext"ãDATA "Dataco Scanet"ãDATA "DEC DEPCA"ãDATA "C-net"ãDATA "Gandalf LANLine"ãDATA "Apricot built-in"ãDATA "David Systems Ether-T"ãDATA "ODI to Packet Driver adapter"ãDATA "AMD Am2110 16-bit"ãDATA "Intel ICD Network controller family"ãDATA "Intel ICD PCL2"ãDATA "Intel ICD PCL2A"ãDATA "AT&T LANPacer"ãDATA "AT&T LANPacer+"ãDATA "AT&T EVB"ãDATA "AT&T StarStation"ãDATA "SLIP simulated ether (skl)"ãDATA "InterLan NIA310"ãDATA "InterLan NISE"ãDATA "InterLan NISE30"ãDATA "InterLan NI6610"ãDATA "Ether over IP/UDP"ãDATA "ICL EtherTeam 16"ãDATA "David Systems Ether-T AT Plus"ãDATA "NCR WaveLAN"ãDATA "Thomas Conrad TC5045"ãDATA "Parallel Port driver"ãDATA "Intel EtherExpress 16"ãDATA "IBMTOKEN simulated Ether on 802.5"ãDATA "Zenith Data Systems Z-Note"ãDATA "3Com 3C509"ãDATA "Mylex LNE390"ãDATA "Madge Smart Ringnode"ãDATA "Novell NE2100"ãDATA "Allied Telesis 1500"ãDATA "Allied Telesis 1700"ãDATA "Fujitsu EtherCoupler"ããSUB GetAddressã ã 'Not used in the program, but you can use it as base for otherã 'packet driver services. See documentation for interrupts!ãã regs.AX = (6 * 256) + 0ã regs.DS = VARSEG(BUFFER)ã regs.DI = VARPTR(BUFFER)ã regs.cx = LEN(BUFFER)ã CALL INTERRUPT(&H60, regs, regs)ãã PRINT "Network address: ";ãã FOR n% = 1 TO regs.cx - 1ã PRINT HEX$(ASC(MID$(BUFFER, n%, 1))); ":";ã NEXTã PRINT HEX$(ASC(MID$(BUFFER, regs.cx, 1)))ããEND SUBããDEFSNG A-Zã'DEFINT A-ZãSUB MainããCOLOR 15, 1ãPRINT " TCP/IP in QuickBasic - SNIFFER 1.0 (C) 2001 Sebastian Mate "ãPRINT : COLOR 15, 0ãShowInfo ' Show informations, and, if required, exit.ãPRINTãã' ***** Error-Message? Haha! Read the documentation!ã' *ãHandle% = AccessType(1, &HFFFF, 0, 0, 0) 'See documentation!ãSetRcvMode Handle%, 6ããDEF SEG = GetBufferSegmentãOfs% = GetBufferOffsetããDOãã IF NewBuffer = 1 THEN ' NewBuffer returns 1 on new packets...ã ã Type1% = PEEK(12 + Ofs%)ã Type2% = PEEK(13 + Ofs%)ã ã IF CSRLIN >= 24 THENã COLOR 7, 0: CLSã COLOR 15, 1ã PRINT " "ã LOCATE 1, 1:ã PRINT STR$(100 - INT((GetCounterB / GetCounterA) * 100)); "% packet loss, ";ã PRINT PCS%; "Computers"ã PRINTã END IFãã EthType$ = "UNKNOWN": COLOR 15, 1ã FROM$ = " unknown "ã DEST$ = " unknown "ã ã 'Is it an IP- or an ARP-packet?ã IF Type1% = 8 AND Type2% = 0 THEN EthType$ = "TCP/IP ": FROM$ = "": DEST$ = "": COLOR 14, 4ã IF Type1% = 8 AND Type2% = 6 THEN EthType$ = "ARP ": FROM$ = "": DEST$ = "": COLOR 10, 2ã ã ' IP-packet: read the IP-addressesã IF Type1% = 8 AND Type2% = 0 THENã ã FOR A% = 26 TO 28ã FROM$ = FROM$ + STR$(PEEK(A% + Ofs%))ã NEXTã FROM$ = FROM$ + STR$(PEEK(29 + Ofs%))ã ã FOR A% = 30 TO 32ã DEST$ = DEST$ + STR$(PEEK(A% + Ofs%))ã NEXTã DEST$ = DEST$ + STR$(PEEK(33 + Ofs%))ãã END IFã ã ' ARP-packet: read the IP-addressesã IF Type1% = 8 AND Type2% = 6 THENã ã FOR A% = 28 TO 30ã FROM$ = FROM$ + STR$(PEEK(A% + Ofs%))ã NEXTã FROM$ = FROM$ + STR$(PEEK(31 + Ofs%))ã ã FOR A% = 38 TO 40ã DEST$ = DEST$ + STR$(PEEK(A% + Ofs%))ã NEXTã DEST$ = DEST$ + STR$(PEEK(41 + Ofs%))ã ã END IFãã 'Should be 16 chars. Looks better!ã FROM$ = FROM$ + SPACE$(16 - LEN(FROM$))ã DEST$ = DEST$ + SPACE$(16 - LEN(DEST$))ãã PRINT " "; EthType$;ã ã ' Look, if that was a new IP (=new computer!)ã ã A% = 0ã FOUND% = 0ã DOã A% = A% + 1ã IF FROM$ = IPBUFFER(A%) THEN FOUND% = 1ã LOOP UNTIL IPBUFFER(A%) = "" OR FOUND% = 1ã COLOR 15, 0ã PRINT " from ";ã COLOR 15, A% MOD 8ã PRINT FROM$;ã IF FOUND% = 0 THENã PCS% = PCS% + 1ã IPBUFFER(A%) = FROM$ã 'PRINT " -> New computer found: "; FROM$ã END IFã ã A% = 0ã FOUND% = 0ã DOã A% = A% + 1ã IF DEST$ = IPBUFFER(A%) THEN FOUND% = 1ã LOOP UNTIL IPBUFFER(A%) = "" OR FOUND% = 1ã COLOR 15, 0ã PRINT " to ";ã COLOR 15, A% MOD 8ã PRINT DEST$;ã IF FOUND% = 0 THENã IPBUFFER(A%) = DEST$ã PCS% = PCS% + 1ã 'PRINT " -> New computer found: "; DEST$;ã END IFãã' -------------------Packet analyzer. Uncommet code to use it... ------------ã' COLOR 15, 0ã' LN% = GetCountXã' BUFFER2 = ""ã' FOR X% = 0 TO LN%ã' BUFFER2 = BUFFER2 + CHR$(PEEK(X% + Ofs%))ã' NEXT X%ã' BUFFER2 = UCASE$(BUFFER2)ã' PRINT " ";ã' IF INSTR(BUFFER2, "HTTP") > 0 THENã' COLOR 15, 4ã' PRINT "HTTP-request";ã' END IFã'ã' IF INSTR(BUFFER2, " 0 OR INSTR(BUFFER2, " 0 THEN COLOR 15, 1: PRINT "HTML";ã'ã' ---------------------------------------------------------------------------ã ã PRINTã COLOR 15, 7ã ã FreeBuffer ' Clear buffer to make "place" for the next one!ãã END IFããLOOP UNTIL INKEY$ <> ""ããCOLOR 7, 0ãCLSãPRINT "Some statistics:"ãPRINT GetCounterA; "packets have passed your computer"ãPRINT GetCounterB; "packets were detected by this program"ãPRINTãPRINT "Please visit www.sm-gimi.de for updates and related software!"ããCALL ReleaseType(Handle%) ' !!! Very important, or you PC crashes!ããENDããEND SUBããDEFINT A-ZãSUB ShowError (in%)ãSELECT CASE in%ã CASE 1: PRINT "1 BAD_HANDLE Invalid handle number!"ã CASE 2: PRINT "2 NO_CLASS No interfaces of specified class found!"ã CASE 3: PRINT "3 NO_TYPE No interfaces of specified type found!"ã CASE 4: PRINT "4 NO_NUMBER No interfaces of specified number found!"ã CASE 5: PRINT "5 BAD_TYPE Bad packet type specified!"ã CASE 6: PRINT "6 NO_MULTICAST This interface does not support multicast!"ã CASE 7: PRINT "7 CANT_TERMINATE This packet driver cannot terminate!"ã CASE 8: PRINT "8 BAD_MODE An invalid receiver mode was specified!"ã CASE 9: PRINT "9 NO_SPACE Operation failed because of insufficient space!"ã CASE 10: PRINT "10 TYPE_INUSE The type had previously been accessed and not released!"ã CASE 11: PRINT "11 BAD_COMMAND The command was out of range, or not implemented!"ã CASE 12: PRINT "12 CANT_SEND The packet couldn't be sent (usually hardware error)!"ã CASE 13: PRINT "13 CANT_SET Hardware address couldn't be changed (more than 1 handle open)!"ã CASE 14: PRINT "14 BAD_ADDRESS Hardware address has bad length or format!"ã CASE 15: PRINT "15 CANT_RESET Couldn't reset interface (more than 1 handle open)!"ãEND SELECTãEND SUBããSUB ShowInfoãã ' ----------------------------------------------------------------------ã ' Routine to detect the packet driver.ã ' Originally by Carl Gorringe.ã ã RetNum% = 0ã FOR IRQ% = &H60 TO &H80ãã VectorOff% = IRQ% * 4 '<-- Point to IRQ # in Interupt Vector Tableãã DEF SEG = 0ã CodeSeg& = PEEK(VectorOff% + 3) * 256& + PEEK(VectorOff% + 2)ã CodeOff& = PEEK(VectorOff% + 1) * 256& + PEEK(VectorOff% + 0)ãã DEF SEG = CodeSeg&ã Char1% = PEEK(CodeOff& + 3)ã Char2% = PEEK(CodeOff& + 4)ã Char3% = PEEK(CodeOff& + 5)ã Char4% = PEEK(CodeOff& + 6)ã Char5% = PEEK(CodeOff& + 7)ã Char6% = PEEK(CodeOff& + 8)ã Char7% = PEEK(CodeOff& + 9)ã Char8% = PEEK(CodeOff& + 10)ã Char9% = PEEK(CodeOff& + 11)ãã DEF SEGãã ProgID$ = CHR$(Char1%) + CHR$(Char2%) + CHR$(Char3%)ã ProgID$ = ProgID$ + CHR$(Char4%) + CHR$(Char5%) + CHR$(Char6%)ã ProgID$ = ProgID$ + CHR$(Char7%) + CHR$(Char8%)ãã 'PRINT ProgID$ '*** Test ***ãã IF ProgID$ = "PKT DRVR" AND Char9% = 0 THENã RetNum% = IRQ%ã EXIT FORã END IFãã NEXT IRQ%ãã PRINT "Packet driver found on IRQ 0x"; HEX$(RetNum%)ã ' ----------------------------------------------------------------------ã ã IF RetNum% = 0 THENã PRINTã COLOR 14, 4ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " CONFIGURATION ERROR FOUND... "ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " No packet driver installed. Please load one of the "ã LOCATE , 4: PRINT " packet drivers on interrupt 0x60. Read the "ã LOCATE , 4: PRINT " documentation! "ã LOCATE , 4: PRINT " "ã ENDã END IFã ã regs.AX = (1 * 256) + 255ã CALL INTERRUPT(RetNum%, regs, regs)ãã class% = regs.cx / 256ã TYP% = regs.DXã VERSION% = regs.BXã FCT% = regs.AX MOD 256ã ã CLASSSTR$ = "Unknown"ã TYPESTR$ = "Unknown"ã ã IF class% = 1 THENã CLASSSTR$ = "DEC/Intel/Xerox 'Bluebook' Ethernet"ã IF regs.DX > 0 AND regs.DX <= 100 THEN TYPESTR$ = CLASS1(TYP%)ã END IFã ã IF class% = 2 THENã CLASSSTR$ = "ProNET-10"ã IF TYP% = 1 THEN TYPESTR$ = "Proteon p1300"ã IF TYP% = 2 THEN TYPESTR$ = "Proteon p1800"ã END IFãã IF class% = 3 THENã CLASSSTR$ = "IEEE 802.5 without expanded RIFs"ã IF TYP% = 1 THEN TYPESTR$ = "IBM Token ring adapter"ã IF TYP% = 2 THEN TYPESTR$ = "Proteon p1340"ã IF TYP% = 3 THEN TYPESTR$ = "Proteon p1344"ã IF TYP% = 4 THEN TYPESTR$ = "Gateway PC-bus"ã IF TYP% = 5 THEN TYPESTR$ = "Gateway AT-bus"ã IF TYP% = 6 THEN TYPESTR$ = "Gateway MCA-bus"ã IF TYP% = 7 THEN TYPESTR$ = "Madge ???"ã IF TYP% = 57 THEN TYPESTR$ = "NDIS to Packet Driver adapter"ã IF TYP% = 71 THEN TYPESTR$ = "ODI to Packet Driver adapter"ã END IFãã IF class% = 4 THEN CLASSSTR$ = "Omninet"ãã IF class% = 5 THENã CLASSSTR$ = "Appletalk"ã IF TYP% = 1 THEN TYPESTR$ = "ATALK.SYS adapter"ã END IFãã IF class% = 6 THENã CLASSSTR$ = "Serial line (SLIP)"ã IF TYP% = 1 THEN TYPESTR$ = "Clarkson 8250-SLIP / PC/TCP's SLP16550.COM"ã IF TYP% = 2 THEN TYPESTR$ = "Clarkson Multiplexor"ã IF TYP% = 3 THEN TYPESTR$ = "Eicon Technologies"ã END IFãã IF class% = 7 THEN CLASSSTR$ = "Starlan"ãã IF class% = 8 THENã CLASSSTR$ = "ArcNet"ã IF TYP% = 1 THEN TYPESTR$ = "Datapoint RIM"ã END IFãã IF class% = 9 THENã CLASSSTR$ = "AX.25"ã IF TYP% = 1 THEN TYPESTR$ = "Ottawa PI card"ã IF TYP% = 2 THEN TYPESTR$ = "Eicon Technologies"ã END IFãã IF class% = 10 THEN CLASSSTR$ = "KISS"ãã IF class% = 11 THEN CLASSSTR$ = "IEEE 802.3 w/802.2 hd"ãã IF class% = 12 THEN CLASSSTR$ = "FDDI w/802.2 hdrs"ãã IF class% = 13 THENã CLASSSTR$ = "Internet X.25"ã IF TYP% = 1 THEN TYPESTR$ = "Western Digital"ã IF TYP% = 2 THEN TYPESTR$ = "Frontier Technology"ã IF TYP% = 3 THEN TYPESTR$ = "Emerging Technologies"ã IF TYP% = 4 THEN TYPESTR$ = "The Software Forge"ã IF TYP% = 5 THEN TYPESTR$ = "Link Data Intelligent X.25"ã IF TYP% = 6 THEN TYPESTR$ = "Eicon Technologies"ã END IFãã IF class% = 14 THENã CLASSSTR$ = "N.T. LANSTAR (encapsulating DIX)"ã IF TYP% = 1 THEN TYPESTR$ = "NT LANSTAR/8"ã IF TYP% = 2 THEN TYPESTR$ = "NT LANSTAR/MC"ã END IFãã IF class% = 15 THENã CLASSSTR$ = "SLFP (MIT serial spec)"ã IF TYP% = 1 THEN TYPESTR$ = "MERIT"ã END IFãã IF class% = 16 THENã CLASSSTR$ = "Point to Point Protocol (no LCP)"ã IF TYP% = 1 THEN TYPESTR$ = "8250/16550 UART"ã IF TYP% = 2 THEN TYPESTR$ = "Niwot Networks synch"ã IF TYP% = 3 THEN TYPESTR$ = "Eicon Technologies"ã END IFãã IF class% = 17 THEN CLASSSTR$ = "IEEE 802.5 with expanded RIFs"ãã IF class% = 18 THENã CLASSSTR$ = "Point to Point Protocol (with LCP)"ã IF TYP% = 1 THEN TYPESTR$ = "Class 16 to class 18 converter"ã IF TYP% = 2 THEN TYPESTR$ = "PC/TCP's PPP16550.COM"ã END IFã ã PRINT "Device Type"; TYP%; "- "; TYPESTR$ã PRINT "Device Class"; class%; "- "; CLASSSTR$ã ã regs.AX = (6 * 256) + 0ã regs.DS = VARSEG(BUFFER)ã regs.DI = VARPTR(BUFFER)ã regs.cx = LEN(BUFFER)ã CALL INTERRUPT(RetNum%, regs, regs)ã ã PRINT "Your Network address is ";ãã ADD$ = ""ã FOR n% = 1 TO regs.cx - 1ã PRINT HEX$(ASC(MID$(BUFFER, n%, 1))); ":";ã ADD$ = ADD$ + HEX$(ASC(MID$(BUFFER, n%, 1))) + ":"ã NEXTã PRINT HEX$(ASC(MID$(BUFFER, regs.cx, 1)))ã ADD$ = ADD$ + HEX$(ASC(MID$(BUFFER, regs.cx, 1)))ã ã PRINT "Driver Version"; VERSION%ã PRINT "Driver Functionality"; FCT%;ã IF FCT% = 1 THEN PRINT "- Basic functions present"ã IF FCT% = 2 THEN PRINT "- Basic and extended functions present"ã IF FCT% = 5 THEN PRINT "- Basic and high-performance functions present"ã IF FCT% = 6 THEN PRINT "- Basic, high-performance and extended functions present"ãã ãã IF FCT% <> 2 AND FCT% <> 6 THENã PRINTã COLOR 14, 4ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " CONFIGURATION ERROR FOUND (?) "ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " You Driver Fuctionality is not enough for this "ã LOCATE , 4: PRINT " program. Use a newer driver! "ã LOCATE , 4: PRINT " "ã END IFã ã IF ADD$ = "FF:FF:FF:FF:FF:FF" OR ADD$ = "0:0:0:0:0:0" THENã PRINTã COLOR 14, 4ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " CONFIGURATION ERROR FOUND... "ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " Your harware address is reported to be "ã LOCATE , 4: PRINT " FF:FF:FF:FF:FF:FF or 0:0:0:0:0:0, this indicates "ã LOCATE , 4: PRINT " that you have entered bad IRQ or address settings "ã LOCATE , 4: PRINT " while loading the driver. Please refer to the "ã LOCATE , 4: PRINT " documentation! "ã LOCATE , 4: PRINT " "ã ENDã END IFãã IF HEX$(RetNum%) <> "60" AND RetNum% > 0 THENã PRINTã COLOR 14, 4ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " CONFIGURATION ERROR FOUND... "ã LOCATE , 4: PRINT " "ã LOCATE , 4: PRINT " The packet driver is not installed on IRQ 0x60. "ã LOCATE , 4: PRINT " Load the driver with 'driver.com 0x60' instead of "ã LOCATE , 4: PRINT " 'driver.com 60'. "ã LOCATE , 4: PRINT " "ã ENDã END IFããããEND SUBããAntoni Gual Minimal Modem agual@eic.ictnet.es 12-14-02 ( : ) QB,PDS 78 1962 MINIMAL.BAS 'MINIMAL TERMINAL By Antoni Gual 15/11/02ã'Comms using PC's serial ports.ããCONST TIMEOUT = .2 'secondsããOPEN "COM2: 9600,N,8,1,CS0,CD0,DS0,OP0,RS" FOR RANDOM AS #1ãã'NOTES on QB comms:ã'QB can't open a link with 8 data bits with a parity dirrerent fromã' no parity!ã'Only COM1 and 2 are available to QB.ã'QB does drop DTR at exit, it causes modems to drop lines.ãã'WIRING:ã'The PC side should work with only 3 wires. The device at the otherã'side may need more wires connected.ã'ã'If you want to connect to another PC, you must use a null modemã'cable in which pin 2 connects to other device's pin 3 and vice-versa.ã'ã'PC (MALE SOCKET) PC(MALE SOCKET)ã' DB25 DB9 DB9 DB25ã'ã' 2 3 ----------------\/---------------- 3 2ã' 3 2 ----------------/\---------------- 2 3ã'ã' 7 1 -----------------------------------1 7ã'ãã'If you have a true modem (not a winmodem), you can test this programã'sending AT to the modem. It should answer "Ok" or "0"ããDOã 'get keyã K$ = INKEY$ãã 'process key pressedã IF LEN(K$) THENã SELECT CASE ASC(K$)ã ã 'enter ends message and sends itã CASE 13:ã IF LEN(TX$) THEN PRINT #1, TX$: TX$ = ""ã ã 'backspace erases rightmost charã CASE 8ã IF LEN(TX$) THENã TX$ = LEFT$(TX$, LEN(TX$) - 1)ã p = POS(0): LOCATE , p - 1: PRINT " "; : LOCATE , p - 1ã END IFã ã 'escape quitsã CASE 27ã EXIT DOã ã 'any other key is added to messageã CASE ELSEã TX$ = TX$ + K$: PRINT K$;ã END SELECTãã END IFãã 'read receive bufferã WHILE NOT EOF(1)ã RX$ = RX$ + INPUT$(LOC(1), 1)ã T! = TIMER + TIMEOUTã WENDãã 'if rx timeout, display received message and clear bufferã IF TIMER > T! THENã IF LEN(RX$) THEN COLOR 15, 0: PRINT RX$; : COLOR 7, 0: RX$ = ""ã T! = TIMER + TIMEOUTã END IFãLOOPããCLOSEãENDãã