10 REM Customization! 19 REM Maybe you want to name the computer? 20 COMPNAME$ = ENVIRON$("HOSTNAME") 28 REM Uptime can be shown, but is meaningless if the system has a clock 29 REM battery or the time has been set 30 SHOWUPTIME = 1 200 PRINT "Working..." 210 TMPFILE$ = "TEST.TMP" 219 REM Determine the OS and interpretter 220 CMD$ = "ver":GOSUB 5000:GOSUB 10000 230 REM PRINT "INTERPRETER: ";INTERP$ 240 REM IF LEN(VERSION$) > 0 THEN PRINT "VERSION: ";VERSION$ 250 REM Determine memory 260 CMD$ = "chkdsk":GOSUB 5000:GOSUB 11000 270 REM CPU Detection 280 GOSUB 12000:GOSUB 12300 290 REM Get a machine name 300 GOSUB 14000 310 REM DOS version 320 GOSUB 12500 329 REM DR-DOS is a mess, probably to fool MS software 330 IF OEM% = &HEE THEN GOSUB 12900 339 REM Get a name for this OS 340 GOSUB 12700 500 REM Just produce an MSDOS logo for now 510 DIM LOGO$(25) 520 GOSUB 20000 1000 REM Output time 1001 CLS 1002 GOSUB 30100 1003 GOSUB 3000 1010 R = 2:C=41 1020 IF LEN(COMPNAME$) = 0 THEN GOTO 1100 1030 LOCATE R,C:PRINT COMPNAME$; 1035 R = R + 1 1040 LOCATE R,C:PRINT STRING$(LEN(COMPNAME$),"-"); 1095 R = R + 1 1100 REM Normal output 1170 LOCATE R,C:PRINT "OS: ";OEM$;" Version ";DVERMAJOR$;".";DVERMINOR$; 1175 R = R + 1 1180 IF LEN(MACHINE$) = 0 THEN GOTO 1200 1190 LOCATE R,C:PRINT "Host: ";MACHINE$; 1195 R = R + 1 1199 REM Uptime really only makes sense if the time was never set 1200 IF SHOWUPTIME <> 1 THEN GOTO 1220 1201 LOCATE R,C:PRINT "Uptime Today: ";:GOSUB 13000 1205 R = R + 1 1220 LOCATE R,C:PRINT "Shell: ";INTERP$; 1222 IF LEN(VERSION$) > 0 THEN PRINT " ";VERSION$; 1225 R = R + 1 1230 LOCATE R,C:PRINT "CPU: ";CPU$; 1235 R = R + 1 1240 LOCATE R,C:PRINT "Memory: ";MEMFREE$;" / ";MEMTOTAL$; 1997 LOCATE ROWS, 41:PRINT "Press any key..."; 1998 WHILE LEN(INKEY$) = 0:WEND 1999 SYSTEM 2000 END 3000 REM Logo output 3010 FOR I = 1 TO ROWS 3020 LOCATE I, 1:PRINT LOGO$(I); 3030 NEXT I 3040 RETURN 5000 REM Run and pipe command 5010 REM TMPFILE$ contains the file for capture 5020 REM CMD$ contains the command to run 5030 SHELL CMD$ + " > " + TMPFILE$ 5040 RETURN 10000 REM 'ver' output parser 10010 REM TMPFILE$ contains the file to open 10011 REM output: INTERP$ is the interpeter 10012 REM VERSION$ is the version 10020 OPEN TMPFILE$ FOR INPUT AS #2 10030 IF EOF(2) THEN GOTO 10060 10040 INPUT#2, VERLINE$ 10050 IF LEN(G$) = 0 THEN GOTO 10030 ELSE GOTO 10060 10060 CLOSE#2 10070 REM VERLINE$ now contains the first non-blank version 10080 REM output. Technically it is just the command 10090 REM interpreter version. 10100 IDX = INSTR(VERLINE$, "ersion") 10110 IF IDX = 0 THEN GOTO 10210 10120 IDX = IDX - 1 10130 INTERP$ = LEFT$(VERLINE$, IDX - 2) 10140 IDX = IDX + 7 10150 VERSION$ = RIGHT$(VERLINE$, LEN(VERLINE$) - IDX) 10160 FOR IDX = 1 TO LEN(VERSION$) 10170 IF MID$(VERSION$, IDX, 1) = " " THEN VERSION$ = LEFT$(VERSION$,IDX-1) 10180 NEXT IDX 10190 IF INTERP$ = "MS-DOS" OR INTERP$="PC-DOS" THEN INTERP$ = INTERP$ + " Command" 10200 RETURN 10210 REM If we're here, the word "version" wasn't found, but no worries 10220 SPACED = 0:IDX=0:VERSION$ = "" 10230 FOR IDX = 2 TO LEN(VERLINE$) 10240 C$ = MID$(IDX, 1) 10250 GOSUB 30200 10240 IF SPACED > 0 AND ISNUM = 1 THEN VERSION$ = VERSION$ + C$ ELSE GOTO 10270 10250 IF SPACED = 0 AND C$ = " " THEN SPACED = IDX 10260 NEXT IDX 10270 IF LEN(VERSION$) > 0 AND SPACED > 0 THEN INTERP$ = LEFT$(VERLINE$, SPACED - 1) ELSE INTERP$ = VERLINE$ 10280 RETURN 11000 REM 'chkdsk' output parser 11010 REM TMPFILE$ contains the file to open 11011 REM output: MEMTOTAL$ is the total memory in bytes 11012 REM MEMFREE$ is the available memory in bytes 11020 MEMTOTAL$ = "":MEMFREE$ = "" 11030 OPEN TMPFILE$ FOR INPUT AS #2 11040 INPUT#2, MEMLINE$ 11050 IDX = INSTR(MEMLINE$, "bytes total memory") 11060 IF IDX > 0 THEN MEMTOTAL$ = LEFT$(MEMLINE$, IDX-1):GOTO 11090 11070 IDX = INSTR(MEMLINE$, "bytes free") 11080 IF IDX > 0 THEN MEMFREE$ = LEFT$(MEMLINE$, IDX-1) 11085 IF EOF(2) THEN GOTO 11110 11090 IF LEN(MEMTOTAL$) = 0 OR LEN(MEMFREE$) = 0 THEN GOTO 11040 ELSE GOTO 11110 11100 RESUME 11110 11110 CLOSE#2 11120 TOTRIM$ = MEMTOTAL$:GOSUB 30000:MEMTOTAL$ = TOTRIM$ 11130 TOTRIM$ = MEMFREE$:GOSUB 30000:MEMFREE$ = TOTRIM$ 11140 RETURN 12000 REM CPU Identity 12001 DIM Q%(400) 12005 DEF SEG=VARSEG(Q%(0)) 12006 OS%=VARPTR(Q%(0)) 12007 BWOFFSET = -1 : LASTBYTE = 0 12010 FOR I = 1 TO 100 12020 READ JC:POKE I+OS%, JC 12021 REM Detect where we need to insert an offset for bus width detection 12022 IF LASTBYTE=99 AND JC=0 THEN BWOFFSET = I+OS% - 1 12029 LASTBYTE = JC 12030 NEXT I 12039 REM Need to set the offset for bus width 12040 TGTOFFSET = BWOFFSET + 16 12050 POKE BWOFFSET, (TGTOFFSET MOD 256) 12060 POKE BWOFFSET+1, INT(TGTOFFSET / 256) 12080 CPUQ = 1 + OS% 12090 CALL CPUQ(CPUID%) 12097 DEF SEG 12100 REM ; Results: 12101 REM ; 0 - 8088 12102 REM ; 1 - 8086 12103 REM ; 2 - V20 12104 REM ; 3 - V30 12105 REM ; 4 - 80188 12106 REM ; 5 - 80186 12107 REM ; 6 - 80286 12108 REM ; 7 - 80386+ 12109 DATA &H55 : REM push bp 12110 DATA &H89, &HE5 : REM mov bp, sp 12111 REM ; push zero onto the stack and pop it into flags. 12112 REM ; some bits won't change 12113 DATA &H31, &HC0 : REM xor ax,ax 12114 DATA &H50 : REM push ax 12115 DATA &H9D : REM popf 12116 DATA &H9C : REM pushf 12117 DATA &H58 : REM pop ax 12118 DATA &H25, &H00, &HF0 : REM and ax, 0xf000 ;0f000h 12119 DATA &H3D, &H00, &HF0 : REM cmp ax, 0xf000 ;0f000h 12120 DATA &H74, &H13 : REM je lessthantwoeightsix 12121 REM ; marked as 286 (6) 12122 DATA &HB2, &H06 : REM mov dl, 6 12123 DATA &HB8, &H00, &H70 : REM mov ax, 0x7000 ;7000h 12124 DATA &H50 : REM push ax 12125 DATA &H9D : REM popf 12126 DATA &H9C : REM pushf 12127 DATA &H58 : REM pop ax 12128 DATA &H25, &H00, &H70 : REM and ax, 0x7000 ;7000h 12129 DATA &H74, &H3A : REM jz alldone 12130 REM ; mark as 386 (7) 12131 DATA &HFE, &HC2 : REM inc dl 12132 DATA &HE9, &H35, &H00 : REM jmp alldone 12133 REM lessthantwoeightsix: 12134 REM ; Mark as 80188 (4) 12135 DATA &HB2, &H04 : REM mov dl, 4 12136 DATA &HB0, &HFF : REM mov al, 0xff ;0ffh 12137 DATA &HB1, &H21 : REM mov cl, 0x21 ;21h 12138 DATA &HD2, &HE8 : REM shr al, cl 12139 REM ; if the shift leaves zero, it's a 8088 class cpu, else 8018 12140 DATA &H75, &H14 : REM jnz buswidth 12141 REM ; Lets see if we have a V2 12142 DATA &HB2, &H02 : REM mov dl, 2 12143 DATA &HFB : REM sti 12144 DATA &H56 : REM push si 12145 DATA &HBE, &H00, &H00 : REM mov si, 0 12146 DATA &HB9, &HFF, &HFF : REM mov cx, 0xffff ;0ffffh 12147 REM ;rep lods [BYTE PTR es:si] 12148 REM ; INLINE assembler doesn't understand above - must be replaced after... 12149 REM ; because we need a lods with ES as a parameter 12150 REM ; so drop a 3-byte nonsense call to be replaced 12151 DATA &HF3, &H26, &HAC : REM mov cx, 0x0f99 ; replace with 0xF3, 0x26, 0xAC 12152 DATA &H5E : REM pop si 12153 DATA &H09, &HC9 : REM or cx, cx 12154 DATA &H74, &H02 : REM jz buswidth 12155 REM ; mark as a 808 12156 DATA &HB2, &H00 : REM mov dl, 0 12157 REM buswidth: 12158 REM ; we are destroying es now, must be restored later 12159 DATA &H0E : REM push cs 12160 DATA &H07 : REM pop es 12161 DATA &HFD : REM std 12162 REM ; The 99 _must_ be replaced with the true offset of qqend 12163 DATA &HBF, &H63, &H00 : REM mov di, 99 ; OFFSET qqend ;99 12164 REM ;set up al and cx: 0xfb is the 'sti' instruction 12165 DATA &HB0, &HFB : REM mov al, 0xfb 12166 DATA &HB9, &H03, &H00 : REM mov cx, 3 12167 REM ; disable interrupts 12168 DATA &HFA : REM cli 12169 DATA &HF2, &HAA : REM rep stosb 12170 DATA &HFC : REM cld 12171 DATA &H90 : REM nop 12172 DATA &H90 : REM nop 12173 DATA &H90 : REM nop 12174 DATA &H42 : REM inc dx 12175 DATA &H90 : REM nop 12176 REM qqend: 12177 DATA &HFB : REM sti 12178 REM ; ES must be restored 12179 DATA &H1E : REM push ds 12180 DATA &H07 : REM pop es 12181 REM alldone: 12182 REM ; store in ax 12183 DATA &H30, &HF6 : REM xor dh, dh 12184 DATA &H8B, &H7E, &H06 : REM mov di, [bp]+6 12185 DATA &H89, &H15 : REM mov [di], dx 12186 DATA &H5D : REM pop bp 12187 DATA &HCA, &H02, &H00 : REM ); { retf 2} 12188 REM Total Bytes in Data: 100 12200 RETURN 12300 REM Interprets CPUID% and returns a CPU name 12310 DIM CPUNAME$(7) 12320 CPUNAME$(0) = "8088" : CPUNAME$(1) = "8086" 12330 CPUNAME$(2) = "V20" : CPUNAME$(3) = "V30" 12340 CPUNAME$(4) = "80188" : CPUNAME$(5) = "80186" 12350 CPUNAME$(6) = "80286" 12360 CPUNAME$(7) = "80386" 12370 IF CPUID% = 2 OR CPUID% = 3 THEN MFG$ = "NEC" ELSE MFG$ = "Intel" 12380 CPU$ = MFG$+" "+CPUNAME$(CPUID%) 12390 RETURN 12500 REM DOS Version 12501 DIM Q2%(200) 12505 DEF SEG=VARSEG(Q2%(0)) 12506 OS%=VARPTR(Q2%(0)) 12510 FOR I = 1 TO 75 12520 READ JC:POKE I+OS%, JC 12530 NEXT I 12540 DOSVER = 1 + OS% 12550 CALL DOSVER(DVER%, OEM%) 12560 DEF SEG 12570 TOTRIM$ = STR$(DVER% MOD 256):GOSUB 30000:DVERMAJOR$ = TOTRIM$ 12580 TOTRIM$ = STR$(INT(DVER% / 256)):GOSUB 30000:DVERMINOR$ = TOTRIM$ 12600 DATA &H55 : REM push bp 12601 DATA &H89, &HE5 : REM mov bp, sp 12602 DATA &HB0, &H00 : REM mov al, 0 12603 DATA &HB4, &H30 : REM mov ah, 0x30 12604 DATA &HCD, &H21 : REM int 0x21 12605 REM ; Push actual version info onto stack 12606 DATA &H50 : REM push ax 12607 DATA &H80, &HFF, &H00 : REM cmp bh, 0x00 12608 DATA &H75, &H0D : REM jne notdrdos 12609 REM ; Check if it is DR_DOS lying about being PC_DOS 12610 DATA &HB8, &H52, &H44 : REM mov ax, 0x4452 12611 DATA &HCD, &H21 : REM int 0x21 12612 DATA &H72, &H06 : REM jc notdrdos 12613 REM ; Mark drdos as 0xee 12614 DATA &HB7, &HEE : REM mov bh, 0xee 12615 REM ; clear the stack in a meaningless way 12616 DATA &H59 : REM pop cx 12617 REM ; DrDos version, or something like it, is already in the ax reggy 12618 DATA &HE9, &H1B, &H00 : REM jmp alldone 12619 REM notdrdos: 12620 REM ; pop the actual version into ax now that we're done 12621 REM ; with drdos checks 12622 DATA &H58 : REM pop ax 12623 DATA &H3C, &H05 : REM cmp al, 5 12624 DATA &H74, &H0D : REM je five 12625 REM ; if al is still zero, it's dos 1 12626 DATA &H3C, &H00 : REM cmp al, 0 12627 DATA &H75, &H12 : REM jne alldone 12628 REM ; Mark it as MS-DOS 1.0 12629 DATA &HB0, &H01 : REM mov al, 1 12630 DATA &HB4, &H00 : REM mov ah, 0 12631 DATA &HB7, &HFF : REM mov bh, 0xFF 12632 DATA &HE9, &H09, &H00 : REM jmp alldone 12633 REM five: 12634 REM ; Store the OEM version 12635 DATA &H53 : REM push bx 12636 DATA &HB8, &H06, &H33 : REM mov ax, 0x3306 12637 DATA &HCD, &H21 : REM int 0x21 12638 REM ; True version should have been in bx 12639 DATA &H53 : REM push bx 12640 DATA &H58 : REM pop ax 12641 DATA &H5B : REM pop bx 12642 REM alldone: 12643 DATA &HB1, &H08 : REM mov cl, 8 12644 DATA &HD3, &HEB : REM shr bx, cl 12645 DATA &H30, &HFF : REM xor bh, bh 12646 REM ; second argument - OEM code in high byte 12647 DATA &H8B, &H7E, &H06 : REM mov di, [bp]+6 12648 DATA &H89, &H1D : REM mov [di], bx 12649 REM ; first argument - major (al) minor(ah) versions 12650 DATA &H8B, &H7E, &H08 : REM mov di, [bp]+8 12651 DATA &H89, &H05 : REM mov [di], ax 12652 DATA &H5D : REM pop bp 12653 DATA &HCA, &H04, &H00 : REM ); { retf 4} 12654 REM Total Bytes in Data: 75 12699 RETURN 12700 REM Returns the DOS type from the OEM% value 12710 OEM$ = "MS-DOS" 12720 IF OEM% = &HEE OR OEM% = &HEF THEN OEM$ = "DR-DOS":RETURN 12730 IF OEM% = &HFD THEN OEM$ = "FreeDos":RETURN 12740 IF OEM% = 0 THEN OEM$ = "PC-DOS":RETURN 12750 IF OEM% = &H66 THEN OEM$ = "PTS-DOS":RETURN 12760 IF OEM% = &H5E THEN OEM$ = "RxDOS":RETURN 12769 REM If we're here, stick with MS-DOS... 12770 RETURN 12900 REM Decipher DR-DOS versioning 12910 LOWVER% = DVER% MOD 256 12920 IF LOWVER% = &H41 THEN DVERMAJOR$ = "1":DVERMINOR$ = "2":RETURN 12930 IF LOWVER% = &H60 THEN DVERMAJOR$ = "2":DVERMINOR$ = "0":RETURN 12940 IF LOWVER% = &H63 THEN DVERMAJOR$ = "3":DVERMINOR$ = "41":RETURN 12950 IF LOWVER% = &H64 THEN DVERMAJOR$ = "3":DVERMINOR$ = "42":RETURN 12960 IF LOWVER% = &H65 THEN DVERMAJOR$ = "5":DVERMINOR$ = "0":RETURN 12970 IF LOWVER% = &H67 OR LOWVER% = &H71 THEN DVERMAJOR$ = "6":DVERMINOR$ = "0":RETURN 12980 IF LOWVER% = &H72 OR LOWVER% = &H73 THEN DVERMAJOR$ = "7":DVERMINOR$ = "0":RETURN 12990 DVERMAJOR$ = "?":DVERMINOR$ = "?" 12999 RETURN 13000 REM Create an Uptime string 13010 HOURS = INT(TIMER / 3600) 13020 MINUTES = INT(TIMER / 60) MOD 60 13040 IF HOURS > 0 THEN PRINT HOURS;" hours "; 13050 PRINT MINUTES;" minutes"; 13060 RETURN 14000 REM Guess machine 14010 REM output: MACHINE$ 14015 MACHID = 0 14020 REM Check for Rainbow video memory first 14030 DEF SEG=&HEE00 14040 IF PEEK(0) = &HFF AND PEEK(1) = 3 AND PEEK(3) = &HFF AND PEEK(4) = 18 THEN MACHID=100 14050 DEF SEG 14099 IF MACHID > 0 THEN GOTO 14200 14100 REM Detect using the machine id from the IBM bios 14110 DEF SEG=&HF000 14120 MACHID = PEEK(&HFFFE) 14130 DEF SEG 14200 REM Parse Machine ID 14210 IF MACHID = 100 THEN MACHINE$="Digital Rainbow 100":GOTO 14299 14220 IBMID = MACHID - &HF8 14230 DIM IBMMODELS$(7) 14240 IBMMODELS$(0) = "PS/2 Model 80":IBMMODELS$(1) = "Convertible PC":IBMMODELS$(2) = "PS/2 Model 30" 14241 IBMMODELS$(3) = "PC/XT":IBMMODELS$(4) = "PC/AT or Compatible":IBMMODELS$(5) = "PCjr":: 14242 IBMMODELS$(6) = "PC/XT":IBMMODELS$(7) = "PC" 14250 IF IBMID >= 0 THEN MACHINE$ = "IBM "+IBMMODELS$(IBMID):GOTO 14299 14260 IF MACHID = 154 OR MACHID = 46 THEN MACHINE$ = "Compaq PC":GOTO 14299 14270 IF MACHID = 49 THEN MACHINE$ = "Sperry PC":GOTO 14299 14299 RETURN 20000 REM MS-DOS Logo 20010 LOGO$(1) = " " 20011 LOGO$(2) = " &&&&&& &&&&&& &&&&&&&&" 20012 LOGO$(3) = " &&&&&&. &&&&&&& &&&&&&&&&&&&" 20013 LOGO$(4) = " &&&&&&& &&&&&&&.&&&& &&&&" 20014 LOGO$(5) = " &&&&&&& &&&&&&&&&&&+" 20015 LOGO$(6) = " &&&&&&&; &&&&&&&& &&&&&&&&" 20016 LOGO$(7) = " &&&&&&&& &&& &&&& &&&&&&&&&&" 20017 LOGO$(8) = " &&&& &&&&&&& &&&& &&&&&&& 20018 LOGO$(9) = " &&&& &&&&&&& &&&&&&&& &&&& 20019 LOGO$(10) = " &&&& ;&&&&& &&&& &&&&+ &&&&& 20020 LOGO$(11) = " &&&& &&&&& &&&& &&&&&&&&&&&$" 20021 LOGO$(12) = " &&&&. &&&& &&&& &&&&&&" 20022 LOGO$(13) = " $$$$$$$$$$ $$$$$$$ :::::::." 20023 LOGO$(14) = " $$$$$$$$.$$$$$$$$.::::::::::::" 20024 LOGO$(15) = " $$$$ $$$$$X :::: &$$ .::::" 20025 LOGO$(16) = " $$$$ $$$$$ $$ .::: $$$$& ...." 20026 LOGO$(17) = " $$$$ $$$$;$$$$ ::::&$$$$" 20027 LOGO$(18) = " $$$$ $$$$ $$$$ ::;$$$$ ::." 20028 LOGO$(19) = " $$$$ . $$$$ $$$$ &$$$$ ::::" 20029 LOGO$(20) = " $$$$ $$$&$$$$$:::: $$$$& .::::" 20030 LOGO$(21) = " $$$$.. $$$$$$::::: $$$ ..::::" 20031 LOGO$(22) = " $$$$$$$$$$$$$$$$&::::::::::::::" 20032 LOGO$(23) = " $$$$$$$$$$$$$$$$$$..::::::::.." 20033 LOGO$(24) = " " 20034 LOGO$(25) = " " 20035 RETURN 30000 REM String Trim Function 30010 REM input/output: TOTRIM$ 30015 IF LEN(TOTRIM$) = 0 THEN RETURN 30016 IF INSTR(TOTRIM$, " ") = 0 THEN RETURN 30020 FOR IDX = 1 TO LEN(TOTRIM$) 30022 IF MID$(TOTRIM$, IDX, 1) <> " " THEN GOTO 30030 30024 NEXT IDX 30030 FOR RDX = LEN(TOTRIM$) TO IDX STEP -1 30032 IF MID$(TOTRIM$, RDX, 1) <> " " THEN GOTO 30040 30034 NEXT RDX 30040 TOTRIM$ = MID$(TOTRIM$, IDX, RDX - IDX + 1) 30050 RETURN 30100 REM Row check 30110 REM output: ROWS - number of screen rows 30120 ON ERROR GOTO 30150 30130 LOCATE 25,1 30140 ROWS=25:GOTO 30170 30150 RESUME 30160 30160 ROWS=24 30170 ON ERROR GOTO 0 30180 RETURN 30200 REM Character is number or dot 30210 REM input: C$ 30220 REM output: ISNUM 30230 IF C$ = "." THEN ISNUM = 1:RETURN 30240 IF ASC(C$) >= ASC("0") AND ASC(C$) <= ASC("9") THEN ISNUM = 1:RETURN 30250 ISNUM = 0:RETURN