crt.pas 22 KB

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