uses dos,crt; type str10=string[10]; const mems:array[0..7] of string[5]=('64 K','128 K','192 K','256 K','512 K','768 K','1 M','2 M'); mmmask :array[0..7] of byte=(0,0,0,0,1,3,3,7); mmbanks:array[0..7] of byte=(1,2,3,4,8,12,16,32); _64 =0; _128 =1; _192 =2; _256 =3; _512 =4; _768 =5; _1024=6; _2048=7; hx:array[0..15] of char='0123456789ABCDEF'; type CHIPS=(__EGA,__VGA,__chips451,__chips452,__chips453,__paradise,__video7 ,__tseng3,__tseng4,__tridBR,__tridCS,__trid89,__everex,__ati1,__ati2 ,__genoa,__oak,__cirrus,__aheadA,__aheadB,__ncr,__yamaha,__poach ,__vesa,__none); var rp:registers; mm:byte; {in 64k blocks} name:string[40]; base,old,curbank,x:word; CHIP:CHIPS; video:string[5]; _crt:string[20]; secondary:string[20]; extra:string[80]; bytes:longint; ix17,lins,vseg,vgran:word; function istr(w:word):str10; var s:str10; begin str(w,s); istr:=s; end; procedure vio(ax:word); begin rp.ax:=ax; intr(16,rp); end; function rdinx(pt,inx:word):word; {read register PT index INX} begin port[pt]:=inx; rdinx:=port[pt+1]; end; procedure wrinx(pt,inx,val:word); {write VAL to register PT index INX} begin port[pt] :=inx; port[pt+1]:=val; end; procedure modinx(pt,inx,mask,nwv:word); begin port[pt]:=inx; port[pt+1]:=(port[pt+1] and not mask)+(nwv and mask); end; procedure setchip23(bank:word); begin if chip=__chips452 then bank:=bank shl 2 else bank:=bank shl 4; wrinx(base+2,16,bank); { wrinx(base+2,17,bank);} end; procedure setbank(bank:word); var x:word; begin vseg:=$a000; if odd(port[$3cc]) then base:=$3d4 else base:=$3b4; case chip of __chips451:wrinx(base+2,11,bank); __chips452:wrinx(base+2,16,bank shl 2); __chips453:wrinx(base+2,16,bank shl 4); __paradise:wrinx($3ce,9,bank shl 4); __video7:begin x:=port[$3cc] and $df; if (bank and 2)>0 then inc(x,32); port[$3c2]:=x; modinx($3c4,$f9,1,bank); modinx($3c4,$f6,$80,(bank shr 2)*5); end; __tseng3:port[$3cd]:=bank*9+64; __tseng4:port[$3cd]:=bank*17; __tridBR:; __tridCS,__poach,__trid89 :begin wrinx($3c4,11,0); if rdinx($3c4,11)=0 then; modinx($3c4,14,$f,bank xor 2); end; __everex:begin x:=port[$3cc] and $df; if (bank and 2)>0 then inc(x,32); port[$3c2]:=x; modinx($3c4,8,$80,bank shl 7); end; __ati1:modinx($1ce,$b2,$1e,bank shl 1); __ati2:modinx($1ce,$b2,$ee,bank*$22); __genoa:wrinx($3c4,6,bank*9+64); __oak:wrinx($3de,17,bank*17); __aheadA:begin wrinx($3ce,13,bank shr 1); x:=port[$3cc] and $df; if odd(bank) then inc(x,32); port[$3c2]:=x; end; __aheadB:wrinx($3ce,13,bank*17); __ncr:wrinx($3c4,$18,bank shl 2); __vesa:begin rp.bx:=0; rp.dx:=bank*longint(64) div vgran; vio($4f05); rp.bx:=1; vio($4f05); end; end; curbank:=bank; end; procedure setpix(x,y,col:word); var l:longint; begin l:=y*bytes+x; setbank(l shr 16); mem[vseg:word(l)]:=col; end; procedure setvesa(bx:word); var vesarec:array[0..255] of byte; begin rp.bx:=bx; vio($4f02); rp.cx:=bx; rp.es:=sseg; rp.di:=ofs(vesarec); vio($4f01); vgran:=vesarec[4]; end; procedure setchip(mde:word); begin vio(mde); portw[$46e8]:=$1e; portw[$103]:=$80; portw[$46e8]:=$e; modinx(base+2,4,4,4); modinx(base+2,11,3,1); end; procedure setev(mde:word); begin rp.bl:=mde; vio($70); end; procedure setwd(mde:word); begin vio(mde); modinx($3ce,15,$17,5); wrinx(base,$29,$85); modinx(base,$2f,2,0); end; procedure setvideo(mde:word); begin rp.bl:=mde; vio($6f05); end; procedure setmode0; {Enter 320x200 mode} begin bytes:=320;lins:=200; case CHIP of __chips451,__chips452,__chips453:setchip($13); __paradise:setwd($13); else vio($13); end; end; procedure setmode1; {Enter 640x400 mode} begin bytes:=640;lins:=400; case CHIP of __chips451,__chips452,__chips453:setchip($78); __paradise:setwd($5e); __video7:setvideo($66); __tseng3:begin vio($2d);lins:=350 end; __tseng4:vio($2f); __tridBR,__tridCS,__poach,__trid89:vio($5c); __everex:setev($14); __ati1,__ati2:vio($61); __genoa:vio($7e); __oak:; __cirrus:; __aheadA,__aheadB:vio($60); __ncr:; __vesa:setvesa($100); end; end; procedure setmode2; {Enter 640x480 mode} begin bytes:=640;lins:=480; case CHIP of __chips451,__chips452,__chips453:setchip($79); __paradise:setwd($5f); __video7:setvideo($67); __tseng3,__tseng4:vio($2e); __tridBR,__tridCS,__poach,__trid89:vio($5d); __everex:setev($30); __ati1,__ati2:vio($62); __genoa:vio($5c); __oak:vio($53); __cirrus:; __aheadA,__aheadB:vio($61); __ncr:; __vesa:setvesa($101); end; end; procedure setmode3; {Enter 800x600 mode} begin bytes:=800;lins:=600; case CHIP of __chips451,__chips452,__chips453:setchip($7b); __paradise:setwd($5c); __video7:setvideo($69); __tseng3,__tseng4:vio($30); __tridBR:; __tridCS,__poach,__trid89:vio($5e); __everex:setev($31); __ati1,__ati2:vio($63); __genoa:vio($5e); __oak:vio($54); __cirrus:; __aheadA,__aheadB:vio($61); __ncr:; __vesa:setvesa($101); end; end; procedure setmode4; {Enter 1024x768 mode} begin bytes:=1024;lins:=768; case CHIP of __tseng4:vio($38); __tridCS,__trid89:vio($61); __everex:setev($32); __ati2:vio($61); __aheadB:vio($63); __vesa:setvesa($105); end; end; procedure setvstart(l:longint); {Set the display start address} var x,y:word; begin x:=l shr 2; y:=(l shr 18) and mmmask[mm]; wrinx(base,13,lo(x)); wrinx(base,12,hi(x)); case chip of __tseng3:modinx(base,$23,2,y shl 1); __tseng4:modinx(base,$33,3,y); __tridcs:modinx(base,$1e,32,y shl 5); __trid89:begin modinx(base,$1e,$a0,y shl 5+128); wrinx($3c4,11,0); modinx($3c4,$e,1,y shr 1); end; __video7:modinx($3c4,$f6,$70,(y shl 4) and $30); __paradise:modinx($3ce,$d,$18,y shl 3); __chips452,__chips453: begin wrinx($3d6,12,y); modinx($3d6,4,4,4); end; __aheadb:modinx($3ce,$1c,3,y); end; end; procedure wrtxt(x,y:word;txt:string); {write TXT to pos (X,Y)} type pchar=array[char] of array[0..15] of byte; var p:^pchar; c:char; i,j,z,b:integer; begin rp.bh:=6; vio($1130); p:=ptr(rp.es,rp.bp); for z:=1 to length(txt) do begin c:=txt[z]; for j:=0 to 15 do begin b:=p^[c][j]; for i:=x+7 downto x do begin if odd(b) then setpix(i,y+j,15) else setpix(i,y+j,0); b:=b shr 1; end; end; inc(x,8); end; end; procedure testvmode; {Test pattern} begin for x:=50 to bytes-50 do begin setpix(x,30,lo(x)); setpix(x,lins-30,lo(x)); end; for x:=30 to lins-30 do begin setpix(x+20,x,lo(x)); setpix(bytes-30-x,x,lo(x)); setpix(50,x,lo(x)); setpix(bytes-50,x,lo(x)); end; wrtxt(70,70,name+' with '+mems[mm]+'bytes.'); wrtxt(70,100,'Mode: '+istr(bytes)+'x'+istr(lins)+' 256 color'); if readkey=' ' then; textmode(3); end; function getbios(offs,lnn:word):string; var s:string; begin s[0]:=chr(lnn); move(mem[$c000:offs],s[1],lnn); getbios:=s; end; function tstrg(pt,msk:word):boolean; {Returns true if the bits in MSK of register PT are read/writable} var old,nw1,nw2:word; begin old:=port[pt]; port[pt]:=old and not msk; nw1:=port[pt] and msk; port[pt]:=old or msk; nw2:=port[pt] and msk; port[pt]:=old; tstrg:=(nw1=0) and (nw2>0); end; function testreg(pt,rg:word):boolean; {Returns } var old,nw1,nw2:word; begin port[pt]:=rg; testreg:=tstrg(pt+1,$ff); end; function testreg2(pt,rg,msk:word):boolean; var old,nw1,nw2:word; begin port[pt]:=rg; testreg2:=tstrg(pt+1,msk); end; function memtst:boolean; var ar:array[0..1023] of byte; x:word; begin move(mem[$a000:0],ar,1024); for x:=0 to 1023 do inc(mem[$a000:x],x); memtst:=true; for x:=0 to 1023 do if mem[$a000:x]<>lo(ar[x]+x) then memtst:=false; move(ar,mem[$a000:0],1024); end; function tsengmem(bank:word):boolean; var old:word; begin old:=port[$3cd]; port[$3cd]:=bank; tsengmem:=memtst; port[$3cd]:=old; end; function tridmem(bank:word):boolean; var old:word; begin old:=rdinx($3c4,14); port[$3c5]:=bank xor 2; tridmem:=memtst; port[$3c5]:=old; end; procedure _chipstech; begin vio($5f00); if rp.al=$5f then begin case rp.bl shr 4 of 0:name:='Chips & Tech 82c451'; 1:name:='Chips & Tech 82c452'; 2:name:='Chips & Tech 82c455'; 3:name:='Chips & Tech 82c453'; 5:name:='Chips & Tech 82c456'; else name:='Unknown Chips & Tech'; end; case rp.bl shr 4 of 1:CHIP:=__chips452; 3:CHIP:=__chips453; else chip:=__chips451; end; case rp.bh of 1:mm:=_512; 2:mm:=_1024; end; end; end; procedure _paradise; var old,old2:word; begin if getbios($7d,4)='VGA=' then begin old:=rdinx($3ce,15); port[$3cf]:=old and $e8+5; {Unlock registers} old2:=rdinx(base,$29); port[base+1]:=old2 and $60+$85; if not testreg(base,$2b) then name:='Paradise PVGA1A' else if not testreg2($3c4,18,64) then name:='Western Digital WD90C00' else if not testreg2($3c4,16,4) then name:='Western Digital WD90C10' else name:='Western Digital WD90C11'; port[$3ce]:=11; case port[$3cf] shr 6 of 2:mm:=_512; 3:mm:=_1024; end; wrinx(base,$29,old2); wrinx($3ce,15,old); chip:=__paradise; end; end; procedure _video7; begin vio($6f00); if rp.bx=$5637 then begin vio($6f07); case rp.bl of $80..$ff:name:='Video7 VEGA VGA'; $70..$7f:name:='Video7 FASTWRITE/VRAM'; $50..$5f:name:='Video7 Version 5'; $41..$4f:name:='Video7 1024i'; end; case rp.ah and 127 of 2:mm:=_512; 4:mm:=_1024; end; chip:=__video7; end end; procedure _genoa; var ad:word; begin ad:=memw[$c000:$37]; if (memw[$c000:ad+2]=$6699) and (mem[$c000:ad]=$77) then begin case mem[$c000:ad+1] of 0:name:='Genoa 62/300'; $11:begin name:='Genoa 64/500'; mm:=_512; end; $22:name:='Genoa 6100'; $33:name:='Genoa 51/5200 (Tseng 3000)'; $55:begin name:='Genoa 53/5400 (Tseng 3000)'; mm:=_512; end; end; if mem[$c000:ad+1]<$33 then chip:=__genoa else chip:=__tseng3; end end; procedure _tseng; begin if tstrg($3cd,$3f) then begin if testreg2(base,$33,$f) then begin name:='Tseng ET4000'; case rdinx(base,$37) and 11 of 3,9:mm:=_256; 10:mm:=_512; 11:mm:=_1024; end; {if tsengmem($ff) then mm:=_1024 else if tsengmem($77) then mm:=_512;} chip:=__tseng4; end else begin name:='Tseng ET3000'; if tsengmem($7f) then mm:=_512; chip:=__tseng3; end; end; end; procedure _trident; var chp,old,val:word; begin wrinx($3c4,11,0); chp:=port[$3c5]; old:=rdinx($3c4,14); port[$3c5]:=0; val:=port[$3c5]; port[$3c5]:=old; if val and 15=2 then begin case chp of 1:name:='Trident 8800BR'; 2:name:='Trident 8800CS'; 3:name:='Trident 8900'; else name:='Unknown Trident VGA' end; case chp of 1:chip:=__tridbr; 2:chip:=__tridCS; 3:chip:=__trid89; end; if (pos('Zymos Poach 51',getbios(0,255))>0) or (pos('Zymos Poach 51',getbios(230,255))>0) then begin name:=name+' (Zymos Poach)'; chip:=__poach; end; if (chp>=3) then mm:=_256+rdinx(base,$1f) and 3 else if (rdinx(base,$1f) and 2)>0 then mm:=_512; end; end; procedure _oak; begin if testreg2($3de,$d,$ff) then begin name:='OAK 037C'; if testreg2($3de,$11,$ff) then name:='OAK-067'; if rdinx($3de,13)>127 then mm:=_512; chip:=__oak; end; end; procedure _cirrus; var old,eagle:word; begin old:=rdinx(base,12); port[base+1]:=0; eagle:=rdinx(base,$1f); wrinx($3c4,6,lo(eagle shr 4) or lo(eagle shl 4)); if port[$3c5]=0 then begin port[$3c5]:=eagle; if port[$3c5]=1 then begin case eagle of $EC:name:='Cirrus 510/520'; $CA:name:='Cirrus 610/620'; $EA:name:='Cirrus Video 7 OEM' else name:='Unknown Cirrus Chip'; end; chip:=__cirrus; end; end; wrinx(base,12,old); end; procedure _ahead; var old:word; begin portw[$3ce]:=$200f; old:=port[$3cf]; case old of $20:begin name:='Ahead A'; chip:=__aheadA; end; $21:begin name:='Ahead B'; chip:=__aheadB; end; end; end; procedure _everex; var x:word; begin rp.bx:=0; vio($7000); if rp.al=$70 then begin x:=rp.dx shr 4; if (x<>$678) and (x<>$236) then {Some Everex boards use Trident chips.} begin case rp.ch shr 6 of 1:mm:=_512; 2:mm:=_1024; 3:mm:=_2048; end; name:='Everex Ev'+hx[x shr 8]+hx[(x shr 4) and 15]+hx[x and 15]; chip:=__everex; end; end; end; procedure _ati; var w:word; begin if getbios($31,9)='761295520' then case memw[$c000:$40] of $3133:begin name:='ATI VGA Wonder'; w:=rdinx($1ce,$bb); if (w and 32)>0 then mm:=_512; case w and 15 of 0:_crt:='EGA'; 1:_crt:='Analog Monochrome'; 2:_crt:='Monochrome'; 3:_crt:='Analog Color'; 4:_crt:='CGA'; 6:_crt:=''; 7:_crt:='IBM 8514/A'; else _crt:='Multisync'; end; rp.bx:=$5506; rp.bp:=$ffff; rp.si:=0; vio($1255); if rp.bp=$ffff then begin name:=name+' revision 1.'; chip:=__ati1; end else begin name:=name+' revision 2.'; chip:=__ati2; end; end; $3233:begin name:='ATI EGA Wonder'; video:='EGA'; chip:=__ega; end; end; end; procedure _vesa; begin vio($4f03); if rp.al=$4f then begin name:='VESA'; chip:=__vesa; end; end; procedure _yamaha; begin if testreg2($3d4,$7c,$7c) then begin name:='Yamaha 6388' end; end; procedure _ncr; begin if testreg2($3c4,5,$ff) then begin portw[$3c4]:=5; {Disable extended registers} if not testreg2($3c4,16,$ff) then begin portw[$3c4]:=$105; {Enable extended registers} if testreg2($3c4,16,$ff) then begin chip:=__ncr; name:='NCR 77C22E'; end; end; end; end; begin extra:=''; _crt:=''; chip:=__none; secondary:=''; name:=''; video:='none'; rp.ah:=18; rp.bx:=$1010; intr(16,rp); if rp.bh<=1 then begin video:='EGA'; chip:=__ega; if odd(port[$3cc]) then base:=$3d4 else base:=$3b4; mm:=rp.bl; vio($1a00); if rp.al=$1a then begin if (rp.bl<4) and (rp.bh>3) then begin old:=rp.bl; rp.bl:=rp.bh; rp.bh:=old; end; video:='MCGA'; case rp.bl of 2,4,6,10:_crt:='TTL Color'; 1,5,7,11:_crt:='Monochrome'; 8,12:_crt:='Analog Color'; end; case rp.bh of 1:secondary:='Monochrome'; 2:secondary:='CGA'; end; if (getbios($31,9)='') and (getbios($40,2)='22') then begin video:='EGA'; {@#%@ lying ATI EGA Wonder !} name:='ATI EGA Wonder'; end else if (rp.bl<10) or (rp.bl>12) then begin video:='VGA'; chip:=__vga; mm:=_256; vio(19); _vesa; if name='' then _chipstech; if name='' then _paradise; if name='' then _video7; if name='' then _genoa; if name='' then _tseng; if name='' then _everex; if name='' then _trident; if name='' then _ati; if name='' then _oak; if name='' then _cirrus; if name='' then _ahead; if name='' then _yamaha; if name='' then _ncr; end; end; end; textmode(3); write('Video system: ',video,' with ',mems[mm]+'bytes.'); if _crt<>'' then write(' Monitor: '+_crt); writeln; if secondary<>'' then writeln('Secondary display: '+secondary); if name<>'' then writeln('Chipset: '+name); if extra<>'' then writeln(extra); writeln; writeln; if chip<=__vga then begin if readkey=' ' then; end else begin write('Run 640x350/400 256 color test (Y/N) ?'); if upcase(readkey)<>'N' then begin setmode1; testvmode; end; writeln; write('Run 640x480 256 color test (Y/N) ?'); if upcase(readkey)<>'N' then begin setmode2; testvmode; end; writeln; write('Run 800x600 256 color test (Y/N) ?'); if upcase(readkey)<>'N' then begin setmode3; testvmode; end; writeln; write('Run 1024x768 256 color test (Y/N) ?'); if upcase(readkey)<>'N' then begin setmode4; testvmode; end; writeln; write('Run scroll test (Y/N) ?'); if upcase(readkey)<>'N' then begin setmode0; IX17:=RDINX(base,$17); bytes:=320; for x:=0 to pred(mmbanks[mm]) do {Clear video memory} begin setbank(x); fillchar(mem[$a000:0],$8000,0); fillchar(mem[$a800:0],$8000,0); end; for x:=mmbanks[mm]*10 downto 1 do wrtxt(20,x*20-15,'Linie '+istr(x)+' scrolling'); for x:=1 to mmbanks[mm]*10-9 do {Scroll text up} begin setvstart(pred(x)*20*longint(bytes)); delay(200); end; end; end; textmode(3); end.