crt.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. {****************************************************************************
  2. Standard CRT unit.
  3. FPK-Pascal runtime library for OS/2.
  4. Copyright (c) 1997 Dani‰l Mantione.
  5. This file may be reproduced and modified under the same conditions
  6. as all other FPK-Pascal source code.
  7. ****************************************************************************}
  8. unit crt;
  9. {History:
  10. 3 june 1997 - Creation.
  11. 9 june 1997 - Now runs under OS/2.
  12. 12 june 1997 - Now runs under DOS.}
  13. interface
  14. uses dos;
  15. const _40cols=0;
  16. _80cols=1;
  17. _132cols=2;
  18. _25rows=0;
  19. _28rows=16;
  20. _43rows=32;
  21. _50rows=48;
  22. font8x8=_50rows;
  23. black =0;
  24. blue =1;
  25. green =2;
  26. cyan =3;
  27. red =4;
  28. magenta =5;
  29. brown =6;
  30. lightgray =7;
  31. darkgray =8;
  32. lightblue =9;
  33. lightgreen =10;
  34. lightcyan =11;
  35. lightred =12;
  36. lightmagenta =13;
  37. yellow =14;
  38. white =15;
  39. blink =128;
  40. {cemodeset means that the procedure textmode has failed to set up a mode.}
  41. type cexxxx=(cenoerror,cemodeset);
  42. var textattr:byte; {Text attribute. RW}
  43. windmin,windmax:word; {Window coordinates. R-}
  44. lastmode:word; {Last videomode. R-}
  45. crt_error:cexxxx; {Crt-status. RW}
  46. function keypressed:boolean;
  47. function readkey:char;
  48. procedure clrscr;
  49. function whereX:byte;
  50. function whereY:byte;
  51. procedure gotoXY(x,y:byte);
  52. procedure window(left,top,right,bottom : byte);
  53. procedure textmode(mode:integer);
  54. procedure textcolor(colour:byte);
  55. procedure textbackground(colour:byte);
  56. procedure insline;
  57. procedure delline;
  58. procedure lowvideo;
  59. procedure normvideo;
  60. procedure highvideo;
  61. procedure assigncrt(var f:text);
  62. procedure delay(ms:word);
  63. procedure sound(hz:word);
  64. procedure nosound;
  65. {***************************************************************************}
  66. {***************************************************************************}
  67. implementation
  68. const extkeycode:char=#0;
  69. var maxrows,maxcols:word;
  70. calibration:longint;
  71. type Tkbdkeyinfo=record
  72. charcode,scancode:char;
  73. fbstatus,bnlsshift:byte;
  74. fsstate:word;
  75. time:longint;
  76. end;
  77. {if you have information on the folowing datastructure, please
  78. send them to me at [email protected]}
  79. {This datastructure is needed when we ask in what video mode we are,
  80. or we want to set up a new mode.}
  81. viomodeinfo=record
  82. cb:word; { length of the entire data
  83. structure }
  84. fbtype, { bit mask of mode being set}
  85. color: byte; { number of colors (power of 2) }
  86. col, { number of text columns }
  87. row, { number of text rows }
  88. hres, { horizontal resolution }
  89. vres: word; { vertical resolution }
  90. fmt_ID, { attribute format
  91. ! more info wanted !}
  92. attrib: byte; { number of attributes }
  93. buf_addr, { physical address of
  94. videobuffer, e.g. $0b800}
  95. buf_length, { length of a videopage (bytes)}
  96. full_length, { total video-memory on video-
  97. card (bytes)}
  98. partial_length:longint; { ????? info wanted !}
  99. ext_data_addr:pointer; { ????? info wanted !}
  100. end;
  101. Pviomodeinfo=^viomodeinfo;
  102. {EMXWRAP.DLL has strange calling conventions: All parameters must have
  103. a 4 byte size.}
  104. function kbdcharin(var Akeyrec:Tkbdkeyinfo;wait,kbdhandle:longint):word;
  105. external 'EMXWRAP' index 204;
  106. function kbdpeek(var Akeyrec:TkbdkeyInfo;kbdhandle:word):word;
  107. external 'EMXWRAP' index 222;
  108. function dossleep(time:longint):word;
  109. external 'DOSCALLS' index 229;
  110. function vioscrollup(top,left,bottom,right,lines:longint;
  111. var screl:word;viohandle:longint):word;
  112. external 'EMXWRAP' index 107;
  113. function vioscrolldn(top,left,bottom,right,lines:longint;
  114. var screl:word;viohandle:longint):word;
  115. external 'EMXWRAP' index 147;
  116. function viogetcurpos(var row,column:word;viohandle:longint):word;
  117. external 'EMXWRAP' index 109;
  118. function viosetcurpos(row,column,viohandle:longint):word;
  119. external 'EMXWRAP' index 115;
  120. function viowrtTTY(s:Pchar;len,viohandle:longint):word;
  121. external 'EMXWRAP' index 119;
  122. function viowrtcharstratt(s:Pchar;len,row,col:longint;var attr:byte;
  123. viohandle:longint):word;
  124. external 'EMXWRAP' index 148;
  125. function viogetmode(var Amodeinfo:viomodeinfo;viohandle:longint):word;
  126. external 'EMXWRAP' index 121;
  127. function viosetmode(var Amodeinfo:viomodeinfo;viohandle:longint):word;
  128. external 'EMXWRAP' index 122;
  129. procedure setscreenmode(mode:word);
  130. { This procedure sets a new videomode. Note that the constants passes to
  131. this procedure are different than in the dos mode.}
  132. const modecols:array[0..2] of word=(40,80,132);
  133. moderows:array[0..3] of word=(25,28,43,50);
  134. var newmode:viomodeinfo;
  135. begin
  136. if os_mode=osOS2 then
  137. begin
  138. newmode.cb:=8;
  139. newmode.fbtype:=1; {Non graphics colour mode.}
  140. newmode.color:=4; {We want 16 colours, 2^4=16.}
  141. newmode.col:=modecols[mode and 15];
  142. newmode.row:=moderows[mode shr 4];
  143. if viosetmode(newmode,0)=0 then
  144. crt_error:=cenoerror
  145. else
  146. crt_error:=cemodeset;
  147. maxcols:=newmode.col;
  148. maxrows:=newmode.row;
  149. end
  150. else
  151. begin
  152. maxcols:=modecols[mode and 15];
  153. maxrows:=moderows[mode shr 4];
  154. crt_error:=cenoerror;
  155. {Set correct vertical resolution.}
  156. asm
  157. movw $0x1202,%ax
  158. movw 8(%ebp),%bx
  159. shrw $4,%bx
  160. cmpb $2,%bl
  161. jne crtsetmode_a1
  162. decw %ax
  163. crtsetmode_a1:
  164. mov $0x30,%bl
  165. int $0x10
  166. end;
  167. {132 column mode in DOS is videocard dependend.}
  168. if mode and 15=2 then
  169. begin
  170. crt_error:=cemodeset;
  171. exit;
  172. end;
  173. {Switch to correct mode.}
  174. asm
  175. mov 8(%ebp),%bx
  176. and $15,%bl
  177. mov $1,%ax
  178. cmp $1,%bl
  179. jne crtsetmode_b1
  180. mov $3,%al
  181. crtsetmode_b1:
  182. int $0x10
  183. {Use alternate print-screen function.}
  184. mov $0x12,%ah
  185. mov $0x20,%bl
  186. int $0x10
  187. end;
  188. {Set correct font.}
  189. case mode shr 4 of
  190. 1:
  191. {Set 8x14 font.}
  192. asm
  193. mov $0x1111,%ax
  194. mov $0,%bl
  195. int $0x10
  196. end;
  197. 2,3:
  198. {Set 8x8 font.}
  199. asm
  200. mov $0x1112,%ax
  201. mov $0,%bl
  202. int $0x10
  203. end;
  204. end;
  205. end;
  206. end;
  207. procedure getcursor(var y,x:word);
  208. {Get the cursor position.}
  209. begin
  210. if os_mode=osOS2 then
  211. viogetcurpos(y,x,0)
  212. else
  213. asm
  214. movb $3,%ah
  215. movb $0,%bh
  216. int $0x10
  217. movl y,%eax
  218. movl x,%ebx
  219. movb %dh,(%eax)
  220. movb %dl,(%ebx)
  221. end;
  222. end;
  223. procedure setcursor(y,x:word);
  224. {Set the cursor position.}
  225. begin
  226. if os_mode=osOS2 then
  227. viosetcurpos(y,x,0)
  228. else
  229. asm
  230. movb $2,%ah
  231. movb $0,%bh
  232. movb y,%dh
  233. movb x,%dl
  234. int $0x10
  235. end;
  236. end;
  237. procedure scroll_up(top,left,bottom,right,lines:word;var screl:word);
  238. begin
  239. if os_mode=osOS2 then
  240. vioscrollup(top,left,bottom,right,lines,screl,0)
  241. else
  242. asm
  243. movb $6,%ah
  244. movb lines,%al
  245. movl screl,%edi
  246. movb 1(%edi),%bh
  247. movb top,%ch
  248. movb left,%cl
  249. movb bottom,%dh
  250. movb right,%dl
  251. int $0x10
  252. end;
  253. end;
  254. procedure scroll_dn(top,left,bottom,right,lines:word;var screl:word);
  255. begin
  256. if os_mode=osOS2 then
  257. vioscrolldn(top,left,bottom,right,lines,screl,0)
  258. else
  259. asm
  260. movb $7,%ah
  261. movb lines,%al
  262. movl screl,%edi
  263. movb 1(%edi),%bh
  264. movb top,%ch
  265. movb left,%cl
  266. movb bottom,%dh
  267. movb right,%dl
  268. int $0x10
  269. end;
  270. end;
  271. function keypressed:boolean;
  272. {Checks if a key is pressed.}
  273. var Akeyrec:Tkbdkeyinfo;
  274. begin
  275. if os_mode=osOS2 then
  276. begin
  277. kbdpeek(Akeyrec,0);
  278. keypressed:=(extkeycode<>#0) or ((Akeyrec.fbstatus and $40)<>0);
  279. end
  280. else
  281. begin
  282. if extkeycode<>#0 then
  283. begin
  284. keypressed:=true;
  285. exit
  286. end
  287. else
  288. asm
  289. movb $1,%ah
  290. int $0x16
  291. setnz %al
  292. movb %al,__RESULT
  293. end;
  294. end;
  295. end;
  296. function readkey:char;
  297. {Reads the next character from the keyboard.}
  298. var Akeyrec:Tkbdkeyinfo;
  299. c,s:char;
  300. begin
  301. if extkeycode<>#0 then
  302. begin
  303. readkey:=extkeycode;
  304. extkeycode:=#0
  305. end
  306. else
  307. begin
  308. if os_mode=osOS2 then
  309. begin
  310. kbdcharin(Akeyrec,0,0);
  311. c:=Akeyrec.charcode;
  312. s:=Akeyrec.scancode;
  313. if (c=#224) and (s<>#0) then
  314. c:=#0;
  315. end
  316. else
  317. begin
  318. asm
  319. movb $0,%ah
  320. int $0x16
  321. movb %al,c
  322. movb %ah,s
  323. end;
  324. end;
  325. if c=#0 then
  326. extkeycode:=s;
  327. readkey:=c;
  328. end;
  329. end;
  330. procedure clrscr;
  331. {Clears the current window.}
  332. var screl:word;
  333. begin
  334. screl:=$20+textattr shl 8;
  335. scroll_up(hi(windmin),lo(windmin),
  336. hi(windmax),lo(windmax),
  337. hi(windmax)-hi(windmin)+1,
  338. screl);
  339. gotoXY(1,1);
  340. end;
  341. procedure gotoXY(x,y:byte);
  342. {Positions the cursor on (x,y) relative to the window origin.}
  343. begin
  344. if x<1 then
  345. x:=1;
  346. if y<1 then
  347. y:=1;
  348. if y+hi(windmin)-2>=hi(windmax) then
  349. y:=hi(windmax)-hi(windmin)+1;
  350. if x+lo(windmin)-2>=lo(windmax) then
  351. x:=lo(windmax)-lo(windmin)+1;
  352. setcursor(y+hi(windmin)-1,x+lo(windmin)-1);
  353. end;
  354. function whereX:byte;
  355. {Returns the x position of the cursor.}
  356. var x,y:word;
  357. begin
  358. getcursor(y,x);
  359. whereX:=x-lo(windmin)+1;
  360. end;
  361. function whereY:byte;
  362. {Returns the y position of the cursor.}
  363. var x,y:word;
  364. begin
  365. getcursor(y,x);
  366. whereY:=y-hi(windmin)+1;
  367. end;
  368. procedure delline;
  369. {Deletes the line at the cursor.}
  370. var row,left,right,bot:longint;
  371. fil:word;
  372. begin
  373. row:=whereY;
  374. left:=lo(windmin)+1;
  375. right:=lo(windmax)+1;
  376. bot:=hi(windmax)+1;
  377. fil:=$20 or (textattr shl 8);
  378. scroll_up(row+1,left,bot,right,1,fil);
  379. end;
  380. procedure insline;
  381. {Inserts a line at the cursor position.}
  382. var row,left,right,bot:longint;
  383. fil:word;
  384. begin
  385. row:=whereY;
  386. left:=lo(windmin)+1;
  387. right:=lo(windmax)+1;
  388. bot:=hi(windmax);
  389. fil:=$20 or (textattr shl 8);
  390. scroll_dn(row,left,bot-1,right,1,fil);
  391. end;
  392. procedure textmode(mode:integer);
  393. { Use this procedure to set-up a specific text-mode.}
  394. begin
  395. textattr:=$07;
  396. lastmode:=mode;
  397. mode:=mode and $ff;
  398. setscreenmode(mode);
  399. windmin:=0;
  400. windmax:=(maxcols-1) or ((maxrows-1) shl 8);
  401. clrscr;
  402. end;
  403. procedure textcolor(colour:byte);
  404. {All text written after calling this will have color as foreground colour.}
  405. begin
  406. textattr:=(textattr and $70) or (colour and $f)+colour and 128;
  407. end;
  408. procedure textbackground(colour:byte);
  409. {All text written after calling this will have colour as background colour.}
  410. begin
  411. textattr:=(textattr and $8f) or ((colour and $7) shl 4);
  412. end;
  413. procedure normvideo;
  414. {Changes the text-background to black and the foreground to white.}
  415. begin
  416. textattr:=$7;
  417. end;
  418. procedure lowvideo;
  419. {All text written after this will have low intensity.}
  420. begin
  421. textattr:=textattr and $f7;
  422. end;
  423. procedure highvideo;
  424. {All text written after this will have high intensity.}
  425. begin
  426. textattr:=textattr or $8;
  427. end;
  428. procedure delay(ms:word);
  429. var i,j:longint;
  430. {Waits ms microseconds. The DOS code is copied from the DOS rtl.}
  431. begin
  432. {Under OS/2 we could also calibrate like under DOS. But this is
  433. unreliable, because OS/2 can hold our programs while calibrating,
  434. if it needs the processor for other things.}
  435. if os_mode=osOS2 then
  436. dossleep(ms)
  437. else
  438. begin
  439. for i:=1 to ms do
  440. for j:=1 to calibration do
  441. begin
  442. end;
  443. end;
  444. end;
  445. procedure window(left,top,right,bottom:byte);
  446. {Change the write window to the given coordinates.}
  447. begin
  448. if (left<1) or
  449. (top<1) or
  450. (right>maxcols) or
  451. (bottom>maxrows) or
  452. (left>right) or
  453. (top>bottom) then
  454. exit;
  455. windmin:=(left-1) or ((top-1) shl 8);
  456. windmax:=(right-1) or ((bottom-1) shl 8);
  457. gotoXY(1,1);
  458. end;
  459. procedure writePchar(s:Pchar;len:word);
  460. {Write a series of characters to the screen.
  461. Not very fast, but is just text-mode isn't it?}
  462. var x,y:word;
  463. c:char;
  464. i,n:integer;
  465. screl:word;
  466. ca:Pchar;
  467. begin
  468. i:=0;
  469. getcursor(y,x);
  470. while i<=len-1 do
  471. begin
  472. case s[i] of
  473. #8:
  474. x:=x-1;
  475. #9:
  476. x:=(x-lo(windmin)) and $fff8+8+lo(windmin);
  477. #10:
  478. ;
  479. #13:
  480. begin
  481. x:=lo(windmin);
  482. inc(y);
  483. end;
  484. else
  485. begin
  486. ca:=@s[i];
  487. n:=1;
  488. while not(s[i+1] in [#8,#9,#10,#13]) and
  489. (x+n<=lo(windmax)+1) and (i<len-1) do
  490. begin
  491. inc(n);
  492. inc(i);
  493. end;
  494. if os_mode=osOS2 then
  495. viowrtcharstratt(ca,n,y,x,textattr,0)
  496. else
  497. asm
  498. movw $0x1300,%ax
  499. movb $0,%bh
  500. movb U_CRT_TEXTATTR,%bl
  501. movb y,%dh
  502. movb x,%dl
  503. movw n,%cx
  504. pushl %ebp
  505. movl ca,%ebp
  506. int $0x10
  507. popl %ebp
  508. end;
  509. x:=x+n;
  510. end;
  511. end;
  512. if x>lo(windmax) then
  513. begin
  514. x:=lo(windmin);
  515. inc(y);
  516. end;
  517. if y>hi(windmax) then
  518. begin
  519. screl:=$20+textattr shl 8;
  520. scroll_up(hi(windmin),lo(windmin),
  521. hi(windmax),lo(windmax),
  522. 1,screl);
  523. y:=hi(windmax);
  524. end;
  525. { writeln(stderr,x,' ',y);}
  526. inc(i);
  527. end;
  528. setcursor(y,x);
  529. end;
  530. function crtread(var f:textrec):word;
  531. {Read a series of characters from the console.}
  532. var max,curpos,i:integer;
  533. c:char;
  534. clist:array[0..2] of char;
  535. begin
  536. max:=f.bufsize-2;
  537. curpos:=0;
  538. repeat
  539. c:=readkey;
  540. case c of
  541. #0:
  542. readkey;
  543. #8:
  544. if curpos>0 then
  545. begin
  546. clist:=#8' '#8;
  547. writePchar(@clist,3);
  548. dec(curpos);
  549. end;
  550. #13:
  551. begin
  552. f.bufptr^[curpos]:=#13;
  553. inc(curpos);
  554. f.bufptr^[curpos]:=#10;
  555. inc(curpos);
  556. f.bufpos:=0;
  557. f.bufend:=curpos;
  558. clist[0]:=#13;
  559. writePchar(@clist,1);
  560. break;
  561. end;
  562. #32..#255:
  563. if curpos<max then
  564. begin
  565. f.bufptr^[curpos]:=c;
  566. inc(curpos);
  567. writePchar(@c,1);
  568. end;
  569. end;
  570. until false;
  571. crtread:=0;
  572. end;
  573. function crtwrite(var f:textrec):word;
  574. {Write a series of characters to the console.}
  575. begin
  576. writePchar(Pchar(f.bufptr),f.bufpos);
  577. f.bufpos:=0;
  578. crtwrite:=0;
  579. end;
  580. function crtopen(var f:textrec):integer;
  581. begin
  582. if f.mode=fmoutput then
  583. crtopen:=0
  584. else
  585. crtopen:=5;
  586. end;
  587. function crtinout(var f:textrec):integer;
  588. begin
  589. case f.mode of
  590. fminput:
  591. crtinout:=crtread(f);
  592. fmoutput:
  593. crtinout:=crtwrite(f);
  594. end;
  595. end;
  596. function crtclose(var f:textrec):integer;
  597. begin
  598. f.mode:=fmclosed;
  599. crtclose:=0;
  600. end;
  601. procedure assigncrt(var f:text);
  602. {Assigns a file to the crt console.}
  603. begin
  604. textrec(f).mode:=fmclosed;
  605. textrec(f).bufsize:=128;
  606. textrec(f).bufptr:=@textrec(f).buffer;
  607. textrec(f).bufpos:=0;
  608. textrec(f).openfunc:=@crtopen;
  609. textrec(f).inoutfunc:=@crtinout;
  610. textrec(f).flushfunc:=@crtinout;
  611. textrec(f).closefunc:=@crtclose;
  612. textrec(f).name[0]:='.';
  613. textrec(f).name[0]:=#0;
  614. end;
  615. procedure sound(hz:word);
  616. {sound and nosound are not implemented because the OS/2 API supports a freq/
  617. duration procedure instead of start/stop procedures.}
  618. begin
  619. end;
  620. procedure nosound;
  621. begin
  622. end;
  623. function get_ticks:word;
  624. type Pword=^word;
  625. begin
  626. get_ticks:=Pword(longint(first_meg)+$46c)^;
  627. end;
  628. procedure initdelay;
  629. {Calibrate the delay procedure. Copied from DOS rtl.}
  630. var first:word;
  631. begin
  632. calibration:=0;
  633. { wait for new tick }
  634. first:=get_ticks;
  635. while get_ticks=first do
  636. begin
  637. end;
  638. first:=get_ticks;
  639. { this estimates calibration }
  640. while get_ticks=first do
  641. inc(calibration);
  642. { calculate this to ms }
  643. calibration:=calibration div 70;
  644. while true do
  645. begin
  646. first:=get_ticks;
  647. while get_ticks=first do
  648. begin
  649. end;
  650. first:=get_ticks;
  651. delay(55);
  652. if first=get_ticks then
  653. exit
  654. else
  655. begin
  656. { decrement calibration two percent }
  657. calibration:=calibration-calibration div 50;
  658. dec(calibration);
  659. end;
  660. end;
  661. end;
  662. {Initialization.}
  663. type Pbyte=^byte;
  664. var curmode:viomodeinfo;
  665. mode:byte;
  666. begin
  667. textattr:=lightgray;
  668. if os_mode=osOS2 then
  669. begin
  670. curmode.cb:=sizeof(curmode);
  671. viogetmode(curmode,0);
  672. maxcols:=curmode.col;
  673. maxrows:=curmode.row;
  674. lastmode:=0;
  675. case maxcols of
  676. 40:
  677. lastmode:=0;
  678. 80:
  679. lastmode:=1;
  680. 132:
  681. lastmode:=2;
  682. end;
  683. case maxrows of
  684. 25:;
  685. 28:
  686. lastmode:=lastmode+16;
  687. 43:
  688. lastmode:=lastmode+32;
  689. 50:
  690. lastmode:=lastmode+48;
  691. end
  692. end
  693. else
  694. begin
  695. {Request video mode to determine columns.}
  696. asm
  697. mov $0x0f,%ah
  698. int $0x10
  699. mov %al,_MODE
  700. end;
  701. case mode of
  702. 0,1:
  703. begin
  704. lastmode:=0;
  705. maxcols:=40;
  706. end;
  707. else
  708. begin
  709. lastmode:=1;
  710. maxcols:=80;
  711. end;
  712. end;
  713. {Get number of rows from realmode $0040:$0084.}
  714. maxrows:=Pbyte(longint(first_meg)+$484)^;
  715. case maxrows of
  716. 25:;
  717. 28:
  718. lastmode:=lastmode+16;
  719. 43:
  720. lastmode:=lastmode+32;
  721. 50:
  722. lastmode:=lastmode+48;
  723. end
  724. end;
  725. windmin:=0;
  726. windmax:=((maxrows-1) shl 8) or (maxcols-1);
  727. if os_mode=osDOS then
  728. initdelay;
  729. crt_error:=cenoerror;
  730. assigncrt(input);
  731. textrec(input).mode:=fminput;
  732. assigncrt(output);
  733. textrec(output).mode:=fmoutput;
  734. end.