crt.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by Florian Klaempfl,
  5. member of the Free Pascal development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit crt;
  13. interface
  14. {$I os.inc}
  15. const
  16. { CRT modes }
  17. BW40 = 0; { 40x25 B/W on Color Adapter }
  18. CO40 = 1; { 40x25 Color on Color Adapter }
  19. BW80 = 2; { 80x25 B/W on Color Adapter }
  20. CO80 = 3; { 80x25 Color on Color Adapter }
  21. Mono = 7; { 80x25 on Monochrome Adapter }
  22. Font8x8 = 256; { Add-in for ROM font }
  23. { Mode constants for 3.0 compatibility }
  24. C40 = CO40;
  25. C80 = CO80;
  26. { Foreground and background color constants }
  27. Black = 0;
  28. Blue = 1;
  29. Green = 2;
  30. Cyan = 3;
  31. Red = 4;
  32. Magenta = 5;
  33. Brown = 6;
  34. LightGray = 7;
  35. { Foreground color constants }
  36. DarkGray = 8;
  37. LightBlue = 9;
  38. LightGreen = 10;
  39. LightCyan = 11;
  40. LightRed = 12;
  41. LightMagenta = 13;
  42. Yellow = 14;
  43. White = 15;
  44. { Add-in for blinking }
  45. Blink = 128;
  46. var
  47. { Interface variables }
  48. CheckBreak: Boolean; { Enable Ctrl-Break }
  49. CheckEOF: Boolean; { Enable Ctrl-Z }
  50. DirectVideo: Boolean; { Enable direct video addressing }
  51. CheckSnow: Boolean; { Enable snow filtering }
  52. LastMode: Word; { Current text mode }
  53. TextAttr: Byte; { Current text attribute }
  54. WindMin: Word; { Window upper left coordinates }
  55. WindMax: Word; { Window lower right coordinates }
  56. { Interface procedures }
  57. procedure AssignCrt(var F: Text);
  58. function KeyPressed: Boolean;
  59. function ReadKey: Char;
  60. procedure TextMode(Mode: Integer);
  61. procedure Window(X1,Y1,X2,Y2: Byte);
  62. procedure GotoXY(X,Y: Byte);
  63. function WhereX: Byte;
  64. function WhereY: Byte;
  65. procedure ClrScr;
  66. procedure ClrEol;
  67. procedure InsLine;
  68. procedure DelLine;
  69. procedure TextColor(Color: Byte);
  70. procedure TextBackground(Color: Byte);
  71. procedure LowVideo;
  72. procedure HighVideo;
  73. procedure NormVideo;
  74. procedure Delay(MS: Word);
  75. procedure Sound(Hz: Word);
  76. procedure NoSound;
  77. {Extra Functions}
  78. procedure cursoron;
  79. procedure cursoroff;
  80. procedure cursorbig;
  81. implementation
  82. uses
  83. go32;
  84. var
  85. startattrib : byte;
  86. col,row,
  87. maxcols,maxrows : longint;
  88. {
  89. definition of textrec is in textrec.inc
  90. }
  91. {$i textrec.inc}
  92. {****************************************************************************
  93. Low level Routines
  94. ****************************************************************************}
  95. function getscreenmode : byte;
  96. begin
  97. dosmemget($40,$49,getscreenmode,1);
  98. end;
  99. procedure setscreenmode(mode : byte);
  100. var regs : trealregs;
  101. begin
  102. {$ifdef GO32V2}
  103. regs.realeax:=mode;
  104. realintr($10,regs);
  105. {$else GO32V2}
  106. asm
  107. movb 8(%ebp),%al
  108. xorb %ah,%ah
  109. pushl %ebp
  110. int $0x10
  111. popl %ebp
  112. end;
  113. {$endif GO32V2}
  114. end;
  115. function screenrows : byte;
  116. begin
  117. dosmemget($40,$84,screenrows,1);
  118. { don't forget this: }
  119. inc(screenrows);
  120. end;
  121. function screencols : byte;
  122. begin
  123. dosmemget($40,$4a,screencols,1);
  124. end;
  125. function get_addr(row,col : byte) : word;
  126. begin
  127. get_addr:=((row-1)*maxcols+(col-1))*2;
  128. end;
  129. procedure screensetcursor(row,col : longint);
  130. var
  131. cols : byte;
  132. pos : word;
  133. {$ifdef GO32V2}
  134. regs : trealregs;
  135. {$endif GO32V2}
  136. begin
  137. if directvideo then
  138. begin
  139. { set new position for the BIOS }
  140. dosmemput($40,$51,row,1);
  141. dosmemput($40,$50,col,1);
  142. { calculates screen position }
  143. dosmemget($40,$4a,cols,1);
  144. { FPKPascal calculates with 32 bit }
  145. pos:=row*cols+col;
  146. { direct access to the graphics card registers }
  147. outportb($3d4,$0e);
  148. outportb($3d5,hi(pos));
  149. outportb($3d4,$0f);
  150. outportb($3d5,lo(pos));
  151. end
  152. else
  153. {$ifndef GO32V2}
  154. asm
  155. movb $0x02,%ah
  156. movb $0,%bh
  157. movb row,%dh
  158. movb col,%dl
  159. pushl %ebp
  160. int $0x10
  161. popl %ebp
  162. end;
  163. {$else GO32V2}
  164. regs.realeax:=$0200;
  165. regs.realebx:=0;
  166. regs.realedx:=row*$100+col;
  167. realintr($10,regs);
  168. {$endif GO32V2}
  169. end;
  170. procedure screengetcursor(var row,col : longint);
  171. begin
  172. col:=0;
  173. row:=0;
  174. dosmemget($40,$50,col,1);
  175. dosmemget($40,$51,row,1);
  176. inc(col);
  177. inc(row);
  178. end;
  179. { exported routines }
  180. procedure cursoron;
  181. {$ifdef GO32V2}
  182. var regs : trealregs;
  183. {$endif GO32V2}
  184. begin
  185. {$ifndef GO32V2}
  186. asm
  187. movb $1,%ah
  188. movb $10,%cl
  189. movb $9,%ch
  190. pushl %ebp
  191. int $0x10
  192. popl %ebp
  193. end;
  194. {$else GO32V2}
  195. regs.realeax:=$0100;
  196. regs.realecx:=$90A;
  197. realintr($10,regs);
  198. {$endif GO32V2}
  199. end;
  200. procedure cursoroff;
  201. {$ifdef GO32V2}
  202. var regs : trealregs;
  203. {$endif GO32V2}
  204. begin
  205. {$ifndef GO32V2}
  206. asm
  207. movb $1,%ah
  208. movb $-1,%cl
  209. movb $-1,%ch
  210. pushl %ebp
  211. int $0x10
  212. popl %ebp
  213. end;
  214. {$else GO32V2}
  215. regs.realeax:=$0100;
  216. regs.realecx:=$ffff;
  217. realintr($10,regs);
  218. {$endif GO32V2}
  219. end;
  220. procedure cursorbig;
  221. {$ifdef GO32V2}
  222. var regs : trealregs;
  223. {$endif GO32V2}
  224. begin
  225. {$ifdef GO32V2}
  226. regs.realeax:=$0100;
  227. regs.realecx:=$10A;
  228. realintr($10,regs);
  229. {$else GO32V2}
  230. asm
  231. movb $1,%ah
  232. movb $10,%cl
  233. movb $1,%ch
  234. pushl %ebp
  235. int $0x10
  236. popl %ebp
  237. end;
  238. {$endif GO32V2}
  239. end;
  240. var
  241. is_last : boolean;
  242. last : char;
  243. function readkey : char;
  244. var
  245. char2 : char;
  246. char1 : char;
  247. {$ifdef GO32V2}
  248. var regs : trealregs;
  249. {$endif GO32V2}
  250. begin
  251. if is_last then
  252. begin
  253. is_last:=false;
  254. readkey:=last;
  255. end
  256. else
  257. begin
  258. {$ifdef GO32V2}
  259. regs.realeax:=$0000;
  260. realintr($16,regs);
  261. byte(char1):=regs.realeax and $ff;
  262. byte(char2):=(regs.realeax and $ff00) div $100;
  263. {$else GO32V2}
  264. asm
  265. movb $0,%ah
  266. pushl %ebp
  267. int $0x16
  268. popl %ebp
  269. movw %ax,-2(%ebp)
  270. end;
  271. {$endif GO32V2}
  272. if char1=#0 then
  273. begin
  274. is_last:=true;
  275. last:=char2;
  276. end;
  277. readkey:=char1;
  278. end;
  279. end;
  280. function keypressed : boolean;
  281. {$ifdef GO32V2}
  282. var regs : trealregs;
  283. {$endif GO32V2}
  284. begin
  285. if is_last then
  286. begin
  287. keypressed:=true;
  288. exit;
  289. end
  290. else
  291. {$ifdef GO32V2}
  292. begin
  293. regs.realeax:=$0100;
  294. realintr($16,regs);
  295. if (regs.realflags and zeroflag) = 0 then
  296. keypressed:=true
  297. else keypressed:=false;
  298. end;
  299. {$else GO32V2}
  300. asm
  301. movb $1,%ah
  302. pushl %ebp
  303. int $0x16
  304. popl %ebp
  305. setnz %al
  306. movb %al,__RESULT
  307. end;
  308. {$endif GO32V2}
  309. end;
  310. procedure gotoxy(x,y : byte);
  311. begin
  312. if (x<1) then
  313. x:=1;
  314. if (y<1) then
  315. y:=1;
  316. if y+hi(windmin)-2>=hi(windmax) then
  317. y:=hi(windmax)-hi(windmin)+1;
  318. if x+lo(windmin)-2>=lo(windmax) then
  319. x:=lo(windmax)-lo(windmin)+1;
  320. screensetcursor(y+hi(windmin)-1,x+lo(windmin)-1);
  321. end;
  322. function wherex : byte;
  323. var
  324. row,col : longint;
  325. begin
  326. screengetcursor(row,col);
  327. wherex:=col-lo(windmin);
  328. end;
  329. function wherey : byte;
  330. var
  331. row,col : longint;
  332. begin
  333. screengetcursor(row,col);
  334. wherey:=row-hi(windmin);
  335. end;
  336. procedure Window(X1,Y1,X2,Y2: Byte);
  337. begin
  338. if (x1<1) or (x2>screencols) or (y2>screenrows) or
  339. (x1>x2) or (y1>y2) then
  340. exit;
  341. windmin:=(x1-1) or ((x1-1) shl 8);
  342. windmax:=(x2-1) or ((y2-1) shl 8);
  343. gotoxy(1,1);
  344. end;
  345. procedure clrscr;
  346. var
  347. fil : word;
  348. row : longint;
  349. begin
  350. fil:=32 or (textattr shl 8);
  351. for row:=hi(windmin) to hi(windmax) do
  352. dosmemfillword($b800,get_addr(row+1,lo(windmin)+1),lo(windmax)-lo(windmin)+1,fil);
  353. gotoxy(1,1);
  354. end;
  355. procedure textcolor(color : Byte);
  356. begin
  357. textattr:=(textattr and $70) or color;
  358. end;
  359. procedure lowvideo;
  360. begin
  361. textattr:=textattr and $f7;
  362. end;
  363. procedure highvideo;
  364. begin
  365. textattr:=textattr or $08;
  366. end;
  367. procedure textbackground(color : Byte);
  368. begin
  369. textattr:=(textattr and $8f) or ((color and $7) shl 4);
  370. end;
  371. procedure normvideo;
  372. begin
  373. textattr:=startattrib;
  374. end;
  375. procedure removeline(line : byte);
  376. var
  377. row,left,right,bot : longint;
  378. fil : word;
  379. begin
  380. row:=line+hi(windmin);
  381. left:=lo(windmin)+1;
  382. right:=lo(windmax)+1;
  383. bot:=hi(windmax)+1;
  384. fil:=32 or (textattr shl 8);
  385. while (row<bot) do
  386. begin
  387. dosmemmove($b800,get_addr(row+1,left),$b800,get_addr(row,left),(right-left+1)*2);
  388. inc(row);
  389. end;
  390. dosmemfillword($b800,get_addr(bot,left),right-left+1,fil);
  391. end;
  392. procedure delline;
  393. begin
  394. removeline(wherey);
  395. end;
  396. procedure insline;
  397. var
  398. row,col,left,right,bot : longint;
  399. fil : word;
  400. begin
  401. screengetcursor(row,col);
  402. inc(row);
  403. left:=lo(windmin)+1;
  404. right:=lo(windmax)+1;
  405. bot:=hi(windmax);
  406. fil:=32 or (textattr shl 8);
  407. while (bot>row) do
  408. begin
  409. dosmemmove($b800,get_addr(bot-1,left),$b800,get_addr(bot,left),(right-left+1)*2);
  410. dec(bot);
  411. end;
  412. dosmemfillword($b800,get_addr(row,left),right-left+1,fil);
  413. end;
  414. procedure clreol;
  415. var
  416. row,col : longint;
  417. fil : word;
  418. begin
  419. screengetcursor(row,col);
  420. inc(row);
  421. inc(col);
  422. fil:=32 or (textattr shl 8);
  423. dosmemfillword($b800,get_addr(row,col),lo(windmax)-col+2,fil);
  424. end;
  425. Procedure WriteChar(c:char);
  426. var
  427. sa : longint;
  428. regs : trealregs;
  429. begin
  430. case c of
  431. #10 : inc(row);
  432. #13 : col:=lo(windmin)+1;
  433. #8 : begin
  434. if col>lo(windmin)+1 then
  435. dec(col);
  436. end;
  437. #7 : begin { beep }
  438. regs.dl:=7;
  439. regs.ah:=2;
  440. realintr($21,regs);
  441. end;
  442. else
  443. begin
  444. sa:=(textattr shl 8) or byte(c);
  445. dosmemput($b800,get_addr(row,col),sa,sizeof(sa));
  446. inc(col);
  447. end;
  448. end;
  449. if col>lo(windmax)+1 then
  450. begin
  451. col:=lo(windmin)+1;
  452. inc(row);
  453. end;
  454. while row>hi(windmax)+1 do
  455. begin
  456. removeline(1);
  457. dec(row);
  458. end;
  459. end;
  460. Function CrtWrite(var f : textrec):integer;
  461. var
  462. i : longint;
  463. begin
  464. screengetcursor(row,col);
  465. inc(row);
  466. inc(col);
  467. for i:=0 to f.bufpos-1 do
  468. WriteChar(f.buffer[i]);
  469. f.bufpos:=0;
  470. screensetcursor(row-1,col-1);
  471. CrtWrite:=0;
  472. end;
  473. Function CrtClose(Var F: TextRec): Integer;
  474. Begin
  475. F.Mode:=fmClosed;
  476. CrtClose:=0;
  477. End;
  478. Function CrtOpen(Var F: TextRec): Integer;
  479. Begin
  480. If F.Mode = fmOutput Then
  481. CrtOpen:=0
  482. Else
  483. CrtOpen:=5;
  484. End;
  485. Function CrtRead(Var F: TextRec): Integer;
  486. Begin
  487. f.bufend:=do_read(f.handle,longint(f.bufptr),f.bufsize);
  488. f.bufpos:=0;
  489. CrtRead:=0;
  490. End;
  491. Function CrtInOut(Var F: TextRec): Integer;
  492. Begin
  493. Case F.Mode of
  494. fmInput: CrtInOut:=CrtRead(F);
  495. fmOutput: CrtInOut:=CrtWrite(F);
  496. End;
  497. End;
  498. procedure AssignCrt(var F: Text);
  499. begin
  500. Assign(F,'.');
  501. TextRec(F).OpenFunc:=@CrtOpen;
  502. TextRec(F).InOutFunc:=@CrtInOut;
  503. TextRec(F).FlushFunc:=@CrtInOut;
  504. TextRec(F).CloseFunc:=@CrtClose;
  505. end;
  506. procedure sound(hz : word);
  507. begin
  508. if hz=0 then
  509. begin
  510. nosound;
  511. exit;
  512. end;
  513. asm
  514. movzwl hz,%ecx
  515. movl $1193046,%eax
  516. cdq
  517. divl %ecx
  518. movl %eax,%ecx
  519. movb $0xb6,%al
  520. outb %al,$0x43
  521. movb %cl,%al
  522. outb %al,$0x42
  523. movb %ch,%al
  524. outb %al,$0x42
  525. inb $0x61,%al
  526. orb $0x3,%al
  527. outb %al,$0x61
  528. end ['EAX','ECX','EDX'];
  529. end;
  530. procedure nosound;
  531. begin
  532. asm
  533. inb $0x61,%al
  534. andb $0xfc,%al
  535. outb %al,$0x61
  536. end ['EAX'];
  537. end;
  538. var
  539. calibration : longint;
  540. procedure Delay(MS: Word);
  541. var
  542. i,j : longint;
  543. begin
  544. for i:=1 to ms do
  545. for j:=1 to calibration do
  546. begin
  547. end;
  548. end;
  549. function get_ticks:longint;
  550. begin
  551. dosmemget($40,$6c,get_ticks,4);
  552. end;
  553. procedure initdelay;
  554. { From the mailling list,
  555. by Jonathan Anderson ([email protected]) }
  556. const
  557. threshold=3;
  558. { Raise this to increase speed but decrease accuracy }
  559. { currently the calibration will be no more than 7 off }
  560. { and shave a few ticks off the most accurate setting of 0 }
  561. { The best values to pick are powers of 2-1 (0,1,3,7,15...) }
  562. { but any non-negative value will work. }
  563. var
  564. too_small : boolean;
  565. first,
  566. incval : longint;
  567. begin
  568. calibration:=0;
  569. { wait for new tick }
  570. first:=get_ticks;
  571. while get_ticks=first do
  572. begin
  573. end;
  574. first:=get_ticks;
  575. { this estimates calibration }
  576. while get_ticks=first do
  577. inc(calibration);
  578. { calculate this to ms }
  579. { calibration:=calibration div 70; }
  580. { this is a very bad estimation because }
  581. { the loop above calls a function }
  582. { and the dealy loop does not }
  583. calibration:=calibration div 3;
  584. { The ideal guess value is about half of the real value }
  585. { although a value lower than that take a large performance }
  586. { hit compared to a value higher than that because it has to }
  587. { go through the loop a few times. }
  588. if calibration<(threshold+1)*2 then
  589. calibration:=(threshold+1)*2;
  590. { If calibration is not at least this value, an }
  591. { infinite loop will result. }
  592. repeat
  593. incval:=calibration;
  594. if calibration<0 then
  595. begin
  596. calibration:=$7FFFFFFF;
  597. exit;
  598. end;
  599. { If calibration becomes less than 0, then }
  600. { the maximum value was not long enough, so }
  601. { assign it the maximum value and exit. }
  602. { Without this code, an infinite loop would }
  603. { result on superfast computers about 315800 }
  604. { times faster (oh yeah!) than my Pentium 75. }
  605. { If you don't think that will happen, take }
  606. { out the if and save a few clock cycles. }
  607. too_small:=true; { Assumed true at beginning }
  608. while incval>threshold do
  609. begin
  610. incval:=incval div 2;
  611. first:=get_ticks;
  612. while get_ticks=first do
  613. begin
  614. end;
  615. first:=get_ticks;
  616. delay(55);
  617. if first=get_ticks then
  618. begin
  619. calibration:=calibration+incval;
  620. end
  621. else
  622. begin
  623. calibration:=calibration-incval;
  624. too_small:=false;
  625. { If you have to decrement calibration, }
  626. { the initial value was not too small to }
  627. { result in an accurate measurement. }
  628. end;
  629. end;
  630. until not too_small;
  631. end;
  632. procedure textmode(mode : integer);
  633. var
  634. set_font8x8 : boolean;
  635. begin
  636. lastmode:=mode;
  637. set_font8x8:=(mode and font8x8)<>0;
  638. mode:=mode and $ff;
  639. setscreenmode(mode);
  640. windmin:=0;
  641. windmax:=(screencols-1) or ((screenrows-1) shl 8);
  642. maxcols:=screencols;
  643. maxrows:=screenrows;
  644. end;
  645. begin
  646. is_last:=false;
  647. { load system variables to temporary variables to save time }
  648. maxcols:=screencols;
  649. maxrows:=screenrows;
  650. { set output window }
  651. windmax:=(maxcols-1) or ((maxrows-1) shl 8);
  652. { save the current settings to restore the old state after the exit }
  653. screengetcursor(row,col);
  654. dosmemget($b800,get_addr(row+1,col+1)+1,startattrib,1);
  655. lastmode:=getscreenmode;
  656. textattr:=startattrib;
  657. { redirect the standard output }
  658. assigncrt(Output);
  659. assigncrt(Input);
  660. TextRec(Output).mode:=fmOutput;
  661. TextRec(Input).mode:=fmInput;
  662. { calculates delay calibration }
  663. initdelay;
  664. end.
  665. {
  666. $Log$
  667. Revision 1.2 1998-05-21 19:30:46 peter
  668. * objects compiles for linux
  669. + assign(pchar), assign(char), rename(pchar), rename(char)
  670. * fixed read_text_as_array
  671. + read_text_as_pchar which was not yet in the rtl
  672. }