123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 1993,97 by Florian Klaempfl,
- member of the Free Pascal development team.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit crt;
- interface
- {$I os.inc}
- const
- { CRT modes }
- BW40 = 0; { 40x25 B/W on Color Adapter }
- CO40 = 1; { 40x25 Color on Color Adapter }
- BW80 = 2; { 80x25 B/W on Color Adapter }
- CO80 = 3; { 80x25 Color on Color Adapter }
- Mono = 7; { 80x25 on Monochrome Adapter }
- Font8x8 = 256; { Add-in for ROM font }
- { Mode constants for 3.0 compatibility }
- C40 = CO40;
- C80 = CO80;
- { Foreground and background color constants }
- Black = 0;
- Blue = 1;
- Green = 2;
- Cyan = 3;
- Red = 4;
- Magenta = 5;
- Brown = 6;
- LightGray = 7;
- { Foreground color constants }
- DarkGray = 8;
- LightBlue = 9;
- LightGreen = 10;
- LightCyan = 11;
- LightRed = 12;
- LightMagenta = 13;
- Yellow = 14;
- White = 15;
- { Add-in for blinking }
- Blink = 128;
- var
- { Interface variables }
- CheckBreak: Boolean; { Enable Ctrl-Break }
- CheckEOF: Boolean; { Enable Ctrl-Z }
- DirectVideo: Boolean; { Enable direct video addressing }
- CheckSnow: Boolean; { Enable snow filtering }
- LastMode: Word; { Current text mode }
- TextAttr: Byte; { Current text attribute }
- WindMin: Word; { Window upper left coordinates }
- WindMax: Word; { Window lower right coordinates }
- { Interface procedures }
- procedure AssignCrt(var F: Text);
- function KeyPressed: Boolean;
- function ReadKey: Char;
- procedure TextMode(Mode: Integer);
- procedure Window(X1,Y1,X2,Y2: Byte);
- procedure GotoXY(X,Y: Byte);
- function WhereX: Byte;
- function WhereY: Byte;
- procedure ClrScr;
- procedure ClrEol;
- procedure InsLine;
- procedure DelLine;
- procedure TextColor(Color: Byte);
- procedure TextBackground(Color: Byte);
- procedure LowVideo;
- procedure HighVideo;
- procedure NormVideo;
- procedure Delay(MS: Word);
- procedure Sound(Hz: Word);
- procedure NoSound;
- {Extra Functions}
- procedure cursoron;
- procedure cursoroff;
- procedure cursorbig;
- implementation
- uses
- go32;
- var
- startattrib : byte;
- col,row,
- maxcols,maxrows : longint;
- {
- definition of textrec is in textrec.inc
- }
- {$i textrec.inc}
- {****************************************************************************
- Low level Routines
- ****************************************************************************}
- function getscreenmode : byte;
- begin
- dosmemget($40,$49,getscreenmode,1);
- end;
- procedure setscreenmode(mode : byte);
- var regs : trealregs;
- begin
- {$ifdef GO32V2}
- regs.realeax:=mode;
- realintr($10,regs);
- {$else GO32V2}
- asm
- movb 8(%ebp),%al
- xorb %ah,%ah
- pushl %ebp
- int $0x10
- popl %ebp
- end;
- {$endif GO32V2}
- end;
- function screenrows : byte;
- begin
- dosmemget($40,$84,screenrows,1);
- { don't forget this: }
- inc(screenrows);
- end;
- function screencols : byte;
- begin
- dosmemget($40,$4a,screencols,1);
- end;
- function get_addr(row,col : byte) : word;
- begin
- get_addr:=((row-1)*maxcols+(col-1))*2;
- end;
- procedure screensetcursor(row,col : longint);
- var
- cols : byte;
- pos : word;
- {$ifdef GO32V2}
- regs : trealregs;
- {$endif GO32V2}
- begin
- if directvideo then
- begin
- { set new position for the BIOS }
- dosmemput($40,$51,row,1);
- dosmemput($40,$50,col,1);
- { calculates screen position }
- dosmemget($40,$4a,cols,1);
- { FPKPascal calculates with 32 bit }
- pos:=row*cols+col;
- { direct access to the graphics card registers }
- outportb($3d4,$0e);
- outportb($3d5,hi(pos));
- outportb($3d4,$0f);
- outportb($3d5,lo(pos));
- end
- else
- {$ifndef GO32V2}
- asm
- movb $0x02,%ah
- movb $0,%bh
- movb row,%dh
- movb col,%dl
- pushl %ebp
- int $0x10
- popl %ebp
- end;
- {$else GO32V2}
- regs.realeax:=$0200;
- regs.realebx:=0;
- regs.realedx:=row*$100+col;
- realintr($10,regs);
- {$endif GO32V2}
- end;
- procedure screengetcursor(var row,col : longint);
- begin
- col:=0;
- row:=0;
- dosmemget($40,$50,col,1);
- dosmemget($40,$51,row,1);
- inc(col);
- inc(row);
- end;
- { exported routines }
- procedure cursoron;
- {$ifdef GO32V2}
- var regs : trealregs;
- {$endif GO32V2}
- begin
- {$ifndef GO32V2}
- asm
- movb $1,%ah
- movb $10,%cl
- movb $9,%ch
- pushl %ebp
- int $0x10
- popl %ebp
- end;
- {$else GO32V2}
- regs.realeax:=$0100;
- regs.realecx:=$90A;
- realintr($10,regs);
- {$endif GO32V2}
- end;
- procedure cursoroff;
- {$ifdef GO32V2}
- var regs : trealregs;
- {$endif GO32V2}
- begin
- {$ifndef GO32V2}
- asm
- movb $1,%ah
- movb $-1,%cl
- movb $-1,%ch
- pushl %ebp
- int $0x10
- popl %ebp
- end;
- {$else GO32V2}
- regs.realeax:=$0100;
- regs.realecx:=$ffff;
- realintr($10,regs);
- {$endif GO32V2}
- end;
- procedure cursorbig;
- {$ifdef GO32V2}
- var regs : trealregs;
- {$endif GO32V2}
- begin
- {$ifdef GO32V2}
- regs.realeax:=$0100;
- regs.realecx:=$10A;
- realintr($10,regs);
- {$else GO32V2}
- asm
- movb $1,%ah
- movb $10,%cl
- movb $1,%ch
- pushl %ebp
- int $0x10
- popl %ebp
- end;
- {$endif GO32V2}
- end;
- var
- is_last : boolean;
- last : char;
- function readkey : char;
- var
- char2 : char;
- char1 : char;
- {$ifdef GO32V2}
- var regs : trealregs;
- {$endif GO32V2}
- begin
- if is_last then
- begin
- is_last:=false;
- readkey:=last;
- end
- else
- begin
- {$ifdef GO32V2}
- regs.realeax:=$0000;
- realintr($16,regs);
- byte(char1):=regs.realeax and $ff;
- byte(char2):=(regs.realeax and $ff00) div $100;
- {$else GO32V2}
- asm
- movb $0,%ah
- pushl %ebp
- int $0x16
- popl %ebp
- movw %ax,-2(%ebp)
- end;
- {$endif GO32V2}
- if char1=#0 then
- begin
- is_last:=true;
- last:=char2;
- end;
- readkey:=char1;
- end;
- end;
- function keypressed : boolean;
- {$ifdef GO32V2}
- var regs : trealregs;
- {$endif GO32V2}
- begin
- if is_last then
- begin
- keypressed:=true;
- exit;
- end
- else
- {$ifdef GO32V2}
- begin
- regs.realeax:=$0100;
- realintr($16,regs);
- if (regs.realflags and zeroflag) = 0 then
- keypressed:=true
- else keypressed:=false;
- end;
- {$else GO32V2}
- asm
- movb $1,%ah
- pushl %ebp
- int $0x16
- popl %ebp
- setnz %al
- movb %al,__RESULT
- end;
- {$endif GO32V2}
- end;
- procedure gotoxy(x,y : byte);
- begin
- if (x<1) then
- x:=1;
- if (y<1) then
- y:=1;
- if y+hi(windmin)-2>=hi(windmax) then
- y:=hi(windmax)-hi(windmin)+1;
- if x+lo(windmin)-2>=lo(windmax) then
- x:=lo(windmax)-lo(windmin)+1;
- screensetcursor(y+hi(windmin)-1,x+lo(windmin)-1);
- end;
- function wherex : byte;
- var
- row,col : longint;
- begin
- screengetcursor(row,col);
- wherex:=col-lo(windmin);
- end;
- function wherey : byte;
- var
- row,col : longint;
- begin
- screengetcursor(row,col);
- wherey:=row-hi(windmin);
- end;
- procedure Window(X1,Y1,X2,Y2: Byte);
- begin
- if (x1<1) or (x2>screencols) or (y2>screenrows) or
- (x1>x2) or (y1>y2) then
- exit;
- windmin:=(x1-1) or ((x1-1) shl 8);
- windmax:=(x2-1) or ((y2-1) shl 8);
- gotoxy(1,1);
- end;
- procedure clrscr;
- var
- fil : word;
- row : longint;
- begin
- fil:=32 or (textattr shl 8);
- for row:=hi(windmin) to hi(windmax) do
- dosmemfillword($b800,get_addr(row+1,lo(windmin)+1),lo(windmax)-lo(windmin)+1,fil);
- gotoxy(1,1);
- end;
- procedure textcolor(color : Byte);
- begin
- textattr:=(textattr and $70) or color;
- end;
- procedure lowvideo;
- begin
- textattr:=textattr and $f7;
- end;
- procedure highvideo;
- begin
- textattr:=textattr or $08;
- end;
- procedure textbackground(color : Byte);
- begin
- textattr:=(textattr and $8f) or ((color and $7) shl 4);
- end;
- procedure normvideo;
- begin
- textattr:=startattrib;
- end;
- procedure removeline(line : byte);
- var
- row,left,right,bot : longint;
- fil : word;
- begin
- row:=line+hi(windmin);
- left:=lo(windmin)+1;
- right:=lo(windmax)+1;
- bot:=hi(windmax)+1;
- fil:=32 or (textattr shl 8);
- while (row<bot) do
- begin
- dosmemmove($b800,get_addr(row+1,left),$b800,get_addr(row,left),(right-left+1)*2);
- inc(row);
- end;
- dosmemfillword($b800,get_addr(bot,left),right-left+1,fil);
- end;
- procedure delline;
- begin
- removeline(wherey);
- end;
- procedure insline;
- var
- row,col,left,right,bot : longint;
- fil : word;
- begin
- screengetcursor(row,col);
- inc(row);
- left:=lo(windmin)+1;
- right:=lo(windmax)+1;
- bot:=hi(windmax);
- fil:=32 or (textattr shl 8);
- while (bot>row) do
- begin
- dosmemmove($b800,get_addr(bot-1,left),$b800,get_addr(bot,left),(right-left+1)*2);
- dec(bot);
- end;
- dosmemfillword($b800,get_addr(row,left),right-left+1,fil);
- end;
- procedure clreol;
- var
- row,col : longint;
- fil : word;
- begin
- screengetcursor(row,col);
- inc(row);
- inc(col);
- fil:=32 or (textattr shl 8);
- dosmemfillword($b800,get_addr(row,col),lo(windmax)-col+2,fil);
- end;
- Procedure WriteChar(c:char);
- var
- sa : longint;
- regs : trealregs;
- begin
- case c of
- #10 : inc(row);
- #13 : col:=lo(windmin)+1;
- #8 : begin
- if col>lo(windmin)+1 then
- dec(col);
- end;
- #7 : begin { beep }
- regs.dl:=7;
- regs.ah:=2;
- realintr($21,regs);
- end;
- else
- begin
- sa:=(textattr shl 8) or byte(c);
- dosmemput($b800,get_addr(row,col),sa,sizeof(sa));
- inc(col);
- end;
- end;
- if col>lo(windmax)+1 then
- begin
- col:=lo(windmin)+1;
- inc(row);
- end;
- while row>hi(windmax)+1 do
- begin
- removeline(1);
- dec(row);
- end;
- end;
- Function CrtWrite(var f : textrec):integer;
- var
- i : longint;
- begin
- screengetcursor(row,col);
- inc(row);
- inc(col);
- for i:=0 to f.bufpos-1 do
- WriteChar(f.buffer[i]);
- f.bufpos:=0;
- screensetcursor(row-1,col-1);
- CrtWrite:=0;
- end;
- Function CrtClose(Var F: TextRec): Integer;
- Begin
- F.Mode:=fmClosed;
- CrtClose:=0;
- End;
- Function CrtOpen(Var F: TextRec): Integer;
- Begin
- If F.Mode = fmOutput Then
- CrtOpen:=0
- Else
- CrtOpen:=5;
- End;
- Function CrtRead(Var F: TextRec): Integer;
- Begin
- f.bufend:=do_read(f.handle,longint(f.bufptr),f.bufsize);
- f.bufpos:=0;
- CrtRead:=0;
- End;
- Function CrtInOut(Var F: TextRec): Integer;
- Begin
- Case F.Mode of
- fmInput: CrtInOut:=CrtRead(F);
- fmOutput: CrtInOut:=CrtWrite(F);
- End;
- End;
- procedure AssignCrt(var F: Text);
- begin
- Assign(F,'.');
- TextRec(F).OpenFunc:=@CrtOpen;
- TextRec(F).InOutFunc:=@CrtInOut;
- TextRec(F).FlushFunc:=@CrtInOut;
- TextRec(F).CloseFunc:=@CrtClose;
- end;
- procedure sound(hz : word);
- begin
- if hz=0 then
- begin
- nosound;
- exit;
- end;
- asm
- movzwl hz,%ecx
- movl $1193046,%eax
- cdq
- divl %ecx
- movl %eax,%ecx
- movb $0xb6,%al
- outb %al,$0x43
- movb %cl,%al
- outb %al,$0x42
- movb %ch,%al
- outb %al,$0x42
- inb $0x61,%al
- orb $0x3,%al
- outb %al,$0x61
- end ['EAX','ECX','EDX'];
- end;
- procedure nosound;
- begin
- asm
- inb $0x61,%al
- andb $0xfc,%al
- outb %al,$0x61
- end ['EAX'];
- end;
- var
- calibration : longint;
- procedure Delay(MS: Word);
- var
- i,j : longint;
- begin
- for i:=1 to ms do
- for j:=1 to calibration do
- begin
- end;
- end;
- function get_ticks:longint;
- begin
- dosmemget($40,$6c,get_ticks,4);
- end;
- procedure initdelay;
- { From the mailling list,
- by Jonathan Anderson ([email protected]) }
- const
- threshold=3;
- { Raise this to increase speed but decrease accuracy }
- { currently the calibration will be no more than 7 off }
- { and shave a few ticks off the most accurate setting of 0 }
- { The best values to pick are powers of 2-1 (0,1,3,7,15...) }
- { but any non-negative value will work. }
- var
- too_small : boolean;
- first,
- incval : longint;
- begin
- calibration:=0;
- { wait for new tick }
- first:=get_ticks;
- while get_ticks=first do
- begin
- end;
- first:=get_ticks;
- { this estimates calibration }
- while get_ticks=first do
- inc(calibration);
- { calculate this to ms }
- { calibration:=calibration div 70; }
- { this is a very bad estimation because }
- { the loop above calls a function }
- { and the dealy loop does not }
- calibration:=calibration div 3;
- { The ideal guess value is about half of the real value }
- { although a value lower than that take a large performance }
- { hit compared to a value higher than that because it has to }
- { go through the loop a few times. }
- if calibration<(threshold+1)*2 then
- calibration:=(threshold+1)*2;
- { If calibration is not at least this value, an }
- { infinite loop will result. }
- repeat
- incval:=calibration;
- if calibration<0 then
- begin
- calibration:=$7FFFFFFF;
- exit;
- end;
- { If calibration becomes less than 0, then }
- { the maximum value was not long enough, so }
- { assign it the maximum value and exit. }
- { Without this code, an infinite loop would }
- { result on superfast computers about 315800 }
- { times faster (oh yeah!) than my Pentium 75. }
- { If you don't think that will happen, take }
- { out the if and save a few clock cycles. }
- too_small:=true; { Assumed true at beginning }
- while incval>threshold do
- begin
- incval:=incval div 2;
- first:=get_ticks;
- while get_ticks=first do
- begin
- end;
- first:=get_ticks;
- delay(55);
- if first=get_ticks then
- begin
- calibration:=calibration+incval;
- end
- else
- begin
- calibration:=calibration-incval;
- too_small:=false;
- { If you have to decrement calibration, }
- { the initial value was not too small to }
- { result in an accurate measurement. }
- end;
- end;
- until not too_small;
- end;
- procedure textmode(mode : integer);
- var
- set_font8x8 : boolean;
- begin
- lastmode:=mode;
- set_font8x8:=(mode and font8x8)<>0;
- mode:=mode and $ff;
- setscreenmode(mode);
- windmin:=0;
- windmax:=(screencols-1) or ((screenrows-1) shl 8);
- maxcols:=screencols;
- maxrows:=screenrows;
- end;
- begin
- is_last:=false;
- { load system variables to temporary variables to save time }
- maxcols:=screencols;
- maxrows:=screenrows;
- { set output window }
- windmax:=(maxcols-1) or ((maxrows-1) shl 8);
- { save the current settings to restore the old state after the exit }
- screengetcursor(row,col);
- dosmemget($b800,get_addr(row+1,col+1)+1,startattrib,1);
- lastmode:=getscreenmode;
- textattr:=startattrib;
- { redirect the standard output }
- assigncrt(Output);
- assigncrt(Input);
- TextRec(Output).mode:=fmOutput;
- TextRec(Input).mode:=fmInput;
- { calculates delay calibration }
- initdelay;
- end.
- {
- $Log$
- Revision 1.2 1998-05-21 19:30:46 peter
- * objects compiles for linux
- + assign(pchar), assign(char), rename(pchar), rename(char)
- * fixed read_text_as_array
- + read_text_as_pchar which was not yet in the rtl
- }
|