video.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. {
  2. System independent low-level video interface for OS/2
  3. $Id$
  4. }
  5. uses
  6. {$IFDEF PPC_FPC}
  7. DosCalls, VioCalls;
  8. {$ELSE}
  9. {$IFDEF PPC_VIRTUAL}
  10. Os2Base;
  11. {$ENDIF}
  12. {$ENDIF}
  13. {$IFNDEF FPC}
  14. type
  15. cardinal = longint;
  16. {$ENDIF}
  17. const
  18. InitVideoCalled: boolean = false;
  19. LastCursorType: word = crUnderline;
  20. EmptyCell: cardinal = $0720;
  21. OrigScreen: PVideoBuf = nil;
  22. OrigScreenSize: cardinal = 0;
  23. {$IFDEF PPC_VIRTUAL}
  24. type
  25. TVioCursorInfo = VioCursorInfo;
  26. TVioModeInfo = VioModeInfo;
  27. TVioIntensity = VioIntensity;
  28. {$ENDIF}
  29. var OrigCurType: TVioCursorInfo;
  30. OrigVioMode: TVioModeInfo;
  31. OrigHighBit: TVioIntensity;
  32. OrigCurRow: word;
  33. OrigCurCol: word;
  34. CellHeight: byte;
  35. OldVideoBuf: PVideoBuf;
  36. procedure TargetEntry;
  37. var P: PVideoModeList;
  38. PScr: pointer;
  39. begin
  40. {Remember original video mode, cursor type and high bit behaviour setting}
  41. OrigVioMode.cb := SizeOf (OrigVioMode);
  42. VioGetMode (OrigVioMode, 0);
  43. VioGetCurType (OrigCurType, 0);
  44. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  45. with OrigHighBit do
  46. begin
  47. cb := 6;
  48. rType := 2;
  49. end;
  50. VioGetState (OrigHighBit, 0);
  51. {Register the curent video mode in Modes if not there yet}
  52. with OrigVioMode do
  53. begin
  54. P := Modes;
  55. while (P <> nil) and ((P^.Row <> Row) or (P^.Col <> Col)
  56. or (P^.Color <> (Color >= Colors_16))) do
  57. P := P^.Next;
  58. if P = nil then
  59. {Assume we have at least 16 colours available in "colour" modes}
  60. RegisterVideoMode (Col, Row, Color >= Colors_16,
  61. {$IFDEF FPC}
  62. @DefaultVideoModeSelector, 0);
  63. {$ELSE}
  64. DefaultVideoModeSelector, 0);
  65. {$ENDIF}
  66. end;
  67. {Get the address of the original videobuffer and size.}
  68. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  69. begin
  70. {$IFDEF BIT_32}
  71. {$IFDEF PPC_VIRTUAL}
  72. SelToFlat (PScr);
  73. {$ELSE}
  74. PScr := SelToFlat (TFarPtr (PScr));
  75. {$ENDIF}
  76. {$ENDIF}
  77. GetMem (OrigScreen, OrigScreenSize);
  78. Move (PScr^, OrigScreen^, OrigScreenSize);
  79. end;
  80. end;
  81. procedure TargetExit;
  82. begin
  83. end;
  84. procedure CheckCellHeight;
  85. var OldCD, CD: TVioCursorInfo;
  86. begin
  87. VioGetCurType (OldCD, 0);
  88. Move (OldCD, CD, SizeOf (CD));
  89. with CD do
  90. begin
  91. Attr := 0;
  92. yStart := word (-90);
  93. cEnd := word (-100);
  94. end;
  95. VioSetCurType (CD, 0);
  96. VioGetCurType (CD, 0);
  97. CellHeight := CD.cEnd;
  98. VioSetCurType (OldCD, 0);
  99. end;
  100. procedure RegisterVideoModes;
  101. begin
  102. { BW modes are rejected on my (colour) configuration. I can't imagine
  103. OS/2 running on MCGA anyway... ;-)
  104. RegisterVideoMode (40, 25, False, @DefaultVideoModeSelector, 0);
  105. RegisterVideoMode (80, 25, False, @DefaultVideoModeSelector, 0);
  106. }
  107. {$IFDEF FPC}
  108. RegisterVideoMode (40, 25, True, @DefaultVideoModeSelector, 0);
  109. RegisterVideoMode (80, 25, True, @DefaultVideoModeSelector, 0);
  110. RegisterVideoMode (80, 30, True, @DefaultVideoModeSelector, 0);
  111. RegisterVideoMode (80, 43, True, @DefaultVideoModeSelector, 0);
  112. RegisterVideoMode (80, 50, True, @DefaultVideoModeSelector, 0);
  113. {$ELSE}
  114. RegisterVideoMode (40, 25, True, DefaultVideoModeSelector, 0);
  115. RegisterVideoMode (80, 25, True, DefaultVideoModeSelector, 0);
  116. RegisterVideoMode (80, 30, True, DefaultVideoModeSelector, 0);
  117. RegisterVideoMode (80, 43, True, DefaultVideoModeSelector, 0);
  118. RegisterVideoMode (80, 50, True, DefaultVideoModeSelector, 0);
  119. {$ENDIF}
  120. { The following modes wouldn't work on plain VGA; is it useful to check
  121. for their availability on the program startup?
  122. RegisterVideoMode (132, 25, True, @DefaultVideoModeSelector, 0);
  123. RegisterVideoMode (132, 30, True, @DefaultVideoModeSelector, 0);
  124. RegisterVideoMode (132, 43, True, @DefaultVideoModeSelector, 0);
  125. RegisterVideoMode (132, 50, True, @DefaultVideoModeSelector, 0);
  126. }
  127. end;
  128. procedure SetHighBitBlink (Blink: boolean);
  129. var VI: TVioIntensity;
  130. begin
  131. with VI do
  132. begin
  133. cb := 6;
  134. rType := 2;
  135. fs := byte (not (Blink));
  136. end;
  137. VioSetState (VI, 0);
  138. end;
  139. procedure InitVideo;
  140. var MI: TVioModeInfo;
  141. begin
  142. if InitVideoCalled then
  143. FreeMem (OldVideoBuf, VideoBufSize);
  144. OldVideoBuf := nil;
  145. InitVideoCalled := true;
  146. VideoBufSize := 0;
  147. MI.cb := SizeOf (MI);
  148. VioGetMode (MI, 0);
  149. with MI do
  150. begin
  151. ScreenWidth := Col;
  152. ScreenHeight := Row;
  153. ScreenColor := Color >= Colors_16;
  154. end;
  155. VioGetCurPos (CursorY, CursorX, 0);
  156. LowAscii := true;
  157. SetCursorType (LastCursorType);
  158. {Get the address of the videobuffer.}
  159. {$IFDEF PPC_VIRTUAL}
  160. if VioGetBuf (pointer (VideoBuf), PWord (@VideoBufSize)^, 0) = 0 then
  161. begin
  162. SelToFlat (pointer (VideoBuf));
  163. {$ELSE}
  164. if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  165. begin
  166. {$IFDEF BIT_32}
  167. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  168. {$ENDIF}
  169. {$ENDIF}
  170. SetHighBitBlink (true);
  171. GetMem (OldVideoBuf, VideoBufSize);
  172. Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
  173. end
  174. else
  175. ErrorHandler (errVioInit, nil);
  176. end;
  177. procedure SetCursorPos (NewCursorX, NewCursorY: word);
  178. begin
  179. if VioSetCurPos (NewCursorY, NewCursorX, 0) = 0 then
  180. begin
  181. CursorX := NewCursorX;
  182. CursorY := NewCursorY;
  183. end
  184. else
  185. {Do not set an error code; people should fix invalid NewCursorX
  186. or NewCursorY values when designing, there is no need for detecting
  187. these errors at runtime.}
  188. RunError (225);
  189. end;
  190. function GetCursorType: word;
  191. var CD: TVioCursorInfo;
  192. begin
  193. VioGetCurType (CD, 0); {Never fails, because handle is default handle.}
  194. with CD do
  195. begin
  196. CursorLines := Succ (cEnd) - yStart;
  197. if Attr = word (-1) then
  198. GetCursorType := crHidden
  199. else
  200. {Because the cursor's start and end lines are returned, we'll have
  201. to guess heuristically what cursor type we have.}
  202. if CursorLines = 0 then
  203. {Probably this does not occur, but you'll never know.}
  204. GetCursorType := crHidden
  205. else if CursorLines <= Succ (CellHeight div 4) then
  206. GetCursorType := crUnderline
  207. else if CursorLines <= Succ (CellHeight div 2) then
  208. GetCursorType := crHalfBlock
  209. else
  210. GetCursorType := crBlock;
  211. end;
  212. end;
  213. procedure SetCursorType (NewType: word);
  214. var CD: TVioCursorInfo;
  215. begin
  216. VioGetCurType (CD, 0);
  217. with CD do
  218. begin
  219. case NewType of
  220. crHidden: Attr := word (-1);
  221. crUnderline:
  222. begin
  223. Attr := 0;
  224. yStart := word (-90);
  225. cEnd := word (-100);
  226. end;
  227. crHalfBlock:
  228. begin
  229. Attr := 0;
  230. yStart := word (-50);
  231. cEnd := word (-100);
  232. end;
  233. crBlock:
  234. begin
  235. Attr := 0;
  236. yStart := 0;
  237. cEnd := word (-100);
  238. end;
  239. end;
  240. VioSetCurType (CD, 0);
  241. VioGetCurType (CD, 0);
  242. CursorLines := Succ (cEnd) - yStart;
  243. end;
  244. end;
  245. procedure DoneVideo;
  246. var PScr: pointer;
  247. ScrSize: cardinal;
  248. begin
  249. if InitVideoCalled then
  250. begin
  251. LastCursorType := GetCursorType;
  252. ClearScreen;
  253. {Restore original settings}
  254. VioSetMode (OrigVioMode, 0);
  255. CheckCellHeight;
  256. {Set CursorX and CursorY}
  257. SetCursorPos (0, 0);
  258. VioSetState (OrigHighBit, 0);
  259. VioSetCurType (OrigCurType, 0);
  260. VioSetCurPos (OrigCurRow, OrigCurCol, 0);
  261. FreeMem (OldVideoBuf, VideoBufSize);
  262. OldVideoBuf := nil;
  263. VideoBufSize := 0;
  264. InitVideoCalled := false;
  265. if (OrigScreenSize <> 0) and (OrigScreen <> nil) then
  266. begin
  267. ScrSize := 0;
  268. if (VioGetBuf (PScr, PWord (@ScrSize)^, 0) = 0)
  269. and (ScrSize = OrigScreenSize) then
  270. begin
  271. {$IFDEF BIT_32}
  272. {$IFDEF PPC_VIRTUAL}
  273. SelToFlat (PScr);
  274. {$ELSE}
  275. PScr := SelToFlat (TFarPtr (PScr));
  276. {$ENDIF}
  277. {$ENDIF}
  278. Move (OrigScreen^, PScr^, OrigScreenSize);
  279. VioShowBuf (0, ScrSize, 0);
  280. end;
  281. end;
  282. end;
  283. end;
  284. function GetCapabilities: word;
  285. begin
  286. GetCapabilities := $3F;
  287. end;
  288. function DefaultVideoModeSelector (const VideoMode: TVideoMode; Params: longint): boolean;
  289. var OldMI, MI: TVioModeInfo;
  290. begin
  291. OldMI.cb := SizeOf (OldMI);
  292. if VioGetMode (OldMI, 0) <> 0 then
  293. DefaultVideoModeSelector := false
  294. else
  295. begin
  296. with MI do
  297. begin
  298. cb := 8;
  299. fbType := 1;
  300. if VideoMode.Color then
  301. Color := Colors_16
  302. else
  303. Color := Colors_2;
  304. Col := VideoMode.Col;
  305. Row := VideoMode.Row;
  306. end;
  307. if VioSetMode (MI, 0) = 0 then
  308. {$IFDEF PPC_VIRTUAL}
  309. if VioGetBuf (pointer (VideoBuf),
  310. PWord (@VideoBufSize)^, 0) = 0 then
  311. begin
  312. SelToFlat (pointer (VideoBuf));
  313. {$ELSE}
  314. if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  315. begin
  316. {$IFDEF BIT_32}
  317. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  318. {$ENDIF}
  319. {$ENDIF}
  320. DefaultVideoModeSelector := true;
  321. SetHighBitBlink (true);
  322. CheckCellHeight;
  323. SetCursorType (LastCursorType);
  324. ClearScreen;
  325. end
  326. else
  327. begin
  328. DefaultVideoModeSelector := false;
  329. VioSetMode (OldMI, 0);
  330. {$IFDEF PPC_VIRTUAL}
  331. VioGetBuf (pointer (VideoBuf),
  332. PWord (@VideoBufSize)^, 0);
  333. SelToFlat (pointer (VideoBuf));
  334. {$ELSE}
  335. VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
  336. {$IFDEF BIT_32}
  337. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  338. {$ENDIF}
  339. {$ENDIF}
  340. SetHighBitBlink (true);
  341. CheckCellHeight;
  342. SetCursorType (LastCursorType);
  343. ClearScreen;
  344. end
  345. else
  346. begin
  347. DefaultVideoModeSelector := false;
  348. {$IFDEF PPC_VIRTUAL}
  349. VioGetBuf (pointer (VideoBuf), PWord (@VideoBufSize)^, 0);
  350. SelToFlat (pointer (VideoBuf));
  351. {$ELSE}
  352. VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
  353. {$IFDEF BIT_32}
  354. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  355. {$ENDIF}
  356. {$ENDIF}
  357. SetHighBitBlink (true);
  358. SetCursorType (LastCursorType);
  359. end;
  360. end;
  361. end;
  362. procedure ClearScreen;
  363. begin
  364. VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
  365. Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
  366. end;
  367. {$IFDEF PPC_FPC}
  368. {$ASMMODE INTEL}
  369. {$ENDIF}
  370. procedure UpdateScreen (Force: boolean);
  371. {$IFDEF BIT_32}
  372. var SOfs, CLen: cardinal;
  373. {$ELSE}
  374. var SOfs, CLen: word;
  375. {$ENDIF}
  376. begin
  377. if LockUpdateScreen = 0 then
  378. begin
  379. if not (Force) then
  380. begin
  381. {$IFDEF BIT_32}
  382. asm
  383. cld
  384. mov esi, VideoBuf
  385. mov edi, OldVideoBuf
  386. mov eax, VideoBufSize
  387. mov ecx, eax
  388. shr ecx
  389. shr ecx
  390. repe
  391. cmpsd
  392. inc cx
  393. mov SOfs, ecx
  394. or ecx, ecx
  395. jz @no_update
  396. mov Force, 1
  397. std
  398. mov edi, eax
  399. mov esi, VideoBuf
  400. add eax, esi
  401. sub eax, 4
  402. mov esi, eax
  403. mov eax, OldVideoBuf
  404. add eax, edi
  405. sub eax, 4
  406. mov edi, eax
  407. repe
  408. cmpsd
  409. inc ecx
  410. shl ecx
  411. shl ecx
  412. mov CLen, ecx
  413. cld
  414. @no_update:
  415. end;
  416. SOfs := VideoBufSize - (SOfs shl 2);
  417. {$ELSE}
  418. asm
  419. cld
  420. push ds
  421. lds si, VideoBuf
  422. les di, OldVideoBuf
  423. mov ax, word ptr VideoBufSize
  424. mov cx, ax
  425. shr cx
  426. repe
  427. cmpsw
  428. inc cx
  429. mov SOfs, cx
  430. or cx, cx
  431. jz @no_update
  432. mov Force, 1
  433. std
  434. mov di, ax
  435. mov si, offset VideoBuf
  436. add ax, si
  437. dec ax
  438. dec ax
  439. mov si, ax
  440. mov ax, offset OldVideoBuf
  441. add ax, di
  442. dec ax
  443. dec ax
  444. mov di, ax
  445. repe
  446. cmpsw
  447. inc cx
  448. shl cx
  449. mov CLen, cx
  450. cld
  451. @no_update:
  452. pop ds
  453. end;
  454. Inc (SOfs);
  455. SOfs := VideoBufSize - (SOfs shl 1);
  456. {$ENDIF}
  457. end else
  458. begin
  459. SOfs := 0;
  460. CLen := VideoBufSize;
  461. end;
  462. if Force then
  463. begin
  464. VioShowBuf (SOfs, CLen, 0);
  465. Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
  466. OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
  467. end;
  468. end;
  469. end;
  470. {
  471. $Log$
  472. Revision 1.11 2000-10-15 20:52:56 hajny
  473. * optimization of UpdateScreen finished
  474. Revision 1.10 2000/10/11 20:10:04 hajny
  475. * compatibility enhancements
  476. Revision 1.9 2000/10/11 05:28:29 hajny
  477. * really a faster version now ;-)
  478. Revision 1.8 2000/10/10 20:28:18 hajny
  479. * screen updates speeded up
  480. Revision 1.7 2000/10/08 18:40:58 hajny
  481. * SetCursorType corrected
  482. Revision 1.6 2000/10/08 14:13:19 hajny
  483. * ClearScreen correction, screen restored on exit
  484. Revision 1.5 2000/10/04 11:53:31 pierre
  485. Add TargetEntry and TargetExit (merged)
  486. Revision 1.4 2000/09/26 18:15:29 hajny
  487. + working with VP/2 already (not FPC yet)!
  488. Revision 1.3 2000/09/24 19:53:03 hajny
  489. * OS/2 implementation almost finished, not debugged yet
  490. Revision 1.2 2000/07/13 11:32:26 michael
  491. + removed logs
  492. }