video.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Video unit for OS/2
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit Video;
  14. interface
  15. {$i videoh.inc}
  16. implementation
  17. uses
  18. DosCalls, VioCalls;
  19. {$i video.inc}
  20. const
  21. LastCursorType: word = crUnderline;
  22. EmptyCell: cardinal = $0720;
  23. OrigScreen: PVideoBuf = nil;
  24. OrigScreenSize: cardinal = 0;
  25. var OrigCurType: TVioCursorInfo;
  26. OrigVioMode: TVioModeInfo;
  27. OrigHighBit: TVioIntensity;
  28. OrigCurRow: word;
  29. OrigCurCol: word;
  30. CellHeight: byte;
  31. procedure CheckCellHeight;
  32. var OldCD, CD: TVioCursorInfo;
  33. begin
  34. VioGetCurType (OldCD, 0);
  35. Move (OldCD, CD, SizeOf (CD));
  36. with CD do
  37. begin
  38. Attr := 0;
  39. yStart := word (-90);
  40. cEnd := word (-100);
  41. end;
  42. VioSetCurType (CD, 0);
  43. VioGetCurType (CD, 0);
  44. CellHeight := CD.cEnd;
  45. VioSetCurType (OldCD, 0);
  46. end;
  47. procedure SetHighBitBlink (Blink: boolean);
  48. var VI: TVioIntensity;
  49. begin
  50. with VI do
  51. begin
  52. cb := 6;
  53. rType := 2;
  54. fs := byte (not (Blink));
  55. end;
  56. VioSetState (VI, 0);
  57. end;
  58. Var
  59. SysVideoBuf : PVideoBuf;
  60. procedure SysInitVideo;
  61. var MI: TVioModeInfo;
  62. begin
  63. MI.cb := SizeOf (MI);
  64. VioGetMode (MI, 0);
  65. with MI do
  66. begin
  67. ScreenWidth := Col;
  68. ScreenHeight := Row;
  69. ScreenColor := Color >= Colors_16;
  70. end;
  71. VioGetCurPos (CursorY, CursorX, 0);
  72. LowAscii := true;
  73. SetCursorType (LastCursorType);
  74. { Get the address of the videobuffer.}
  75. if VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  76. begin
  77. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  78. SetHighBitBlink (true);
  79. end
  80. else
  81. ErrorHandler (errVioInit, nil);
  82. end;
  83. procedure SysSetCursorPos (NewCursorX, NewCursorY: word);
  84. begin
  85. if VioSetCurPos (NewCursorY, NewCursorX, 0) = 0 then
  86. begin
  87. CursorX := NewCursorX;
  88. CursorY := NewCursorY;
  89. end
  90. else
  91. {Do not set an error code; people should fix invalid NewCursorX
  92. or NewCursorY values when designing, there is no need for detecting
  93. these errors at runtime.}
  94. RunError (225);
  95. end;
  96. function SysGetCursorType: word;
  97. var CD: TVioCursorInfo;
  98. begin
  99. VioGetCurType (CD, 0); {Never fails, because handle is default handle.}
  100. with CD do
  101. begin
  102. CursorLines := Succ (cEnd) - yStart;
  103. if Attr = word (-1) then
  104. SysGetCursorType := crHidden
  105. else
  106. {Because the cursor's start and end lines are returned, we'll have
  107. to guess heuristically what cursor type we have.}
  108. if CursorLines = 0 then
  109. {Probably this does not occur, but you'll never know.}
  110. SysGetCursorType := crHidden
  111. else if CursorLines <= Succ (CellHeight div 4) then
  112. SysGetCursorType := crUnderline
  113. else if CursorLines <= Succ (CellHeight div 2) then
  114. SysGetCursorType := crHalfBlock
  115. else
  116. SysGetCursorType := crBlock;
  117. end;
  118. end;
  119. procedure SysSetCursorType (NewType: word);
  120. var CD: TVioCursorInfo;
  121. begin
  122. VioGetCurType (CD, 0);
  123. with CD do
  124. begin
  125. case NewType of
  126. crHidden: Attr := word (-1);
  127. crUnderline:
  128. begin
  129. Attr := 0;
  130. yStart := word (-90);
  131. cEnd := word (-100);
  132. end;
  133. crHalfBlock:
  134. begin
  135. Attr := 0;
  136. yStart := word (-50);
  137. cEnd := word (-100);
  138. end;
  139. crBlock:
  140. begin
  141. Attr := 0;
  142. yStart := 0;
  143. cEnd := word (-100);
  144. end;
  145. end;
  146. VioSetCurType (CD, 0);
  147. VioGetCurType (CD, 0);
  148. CursorLines := Succ (cEnd) - yStart;
  149. end;
  150. end;
  151. procedure SysClearScreen;
  152. begin
  153. VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
  154. FillWord (SysVideoBuf^, VideoBufSize shr 1, PWord (@EmptyCell)^);
  155. end;
  156. procedure SysDoneVideo;
  157. var PScr: pointer;
  158. ScrSize: cardinal;
  159. begin
  160. LastCursorType := GetCursorType;
  161. SysClearScreen;
  162. {Restore original settings}
  163. VioSetMode (OrigVioMode, 0);
  164. CheckCellHeight;
  165. {Set CursorX and CursorY}
  166. SetCursorPos (0, 0);
  167. VioSetState (OrigHighBit, 0);
  168. VioSetCurType (OrigCurType, 0);
  169. VioSetCurPos (OrigCurRow, OrigCurCol, 0);
  170. if (OrigScreenSize <> 0) and (OrigScreen <> nil) then
  171. begin
  172. ScrSize := 0;
  173. if (VioGetBuf (PScr, PWord (@ScrSize)^, 0) = 0) and
  174. (ScrSize = OrigScreenSize) then
  175. begin
  176. PScr := SelToFlat (cardinal (PScr));
  177. Move (OrigScreen^, PScr^, OrigScreenSize);
  178. VioShowBuf (0, ScrSize, 0);
  179. end;
  180. end;
  181. end;
  182. function SysGetCapabilities: word;
  183. begin
  184. SysGetCapabilities := $3F;
  185. end;
  186. function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
  187. var OldMI, MI: TVioModeInfo;
  188. begin
  189. OldMI.cb := SizeOf (OldMI);
  190. if VioGetMode (OldMI, 0) <> 0 then
  191. SysVideoModeSelector := false
  192. else
  193. begin
  194. with MI do
  195. begin
  196. cb := 8;
  197. fbType := 1;
  198. if VideoMode.Color then
  199. Color := Colors_16
  200. else
  201. Color := Colors_2;
  202. Col := VideoMode.Col;
  203. Row := VideoMode.Row;
  204. end;
  205. if VioSetMode (MI, 0) = 0 then
  206. if VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  207. begin
  208. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  209. SysVideoModeSelector := true;
  210. SetHighBitBlink (true);
  211. CheckCellHeight;
  212. SetCursorType (LastCursorType);
  213. SysClearScreen;
  214. end
  215. else
  216. begin
  217. SysVideoModeSelector := false;
  218. VioSetMode (OldMI, 0);
  219. VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0);
  220. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  221. SetHighBitBlink (true);
  222. CheckCellHeight;
  223. SetCursorType (LastCursorType);
  224. SysClearScreen;
  225. end
  226. else
  227. begin
  228. SysVideoModeSelector := false;
  229. VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0);
  230. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  231. SetHighBitBlink (true);
  232. SetCursorType (LastCursorType);
  233. end;
  234. end;
  235. end;
  236. Const
  237. SysVideoModeCount = 6;
  238. SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
  239. (Col: 40; Row: 25; Color: True),
  240. (Col: 80; Row: 25; Color: True),
  241. (Col: 80; Row: 30; Color: True),
  242. (Col: 80; Row: 43; Color: True),
  243. (Col: 80; Row: 50; Color: True),
  244. (Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
  245. );
  246. { .MVC. were commented:
  247. BW modes are rejected on my (colour) configuration. I can't imagine
  248. OS/2 running on MCGA anyway... ;-)
  249. (Col: 40; Row: 25;Color: False),
  250. (Col: 80; Row: 25;Color: False),
  251. The following modes wouldn't work on plain VGA; is it useful to check
  252. for their availability on the program startup?
  253. (Col: 132;Row: 25;Color: True),
  254. (Col: 132;Row: 30;Color: True),
  255. (Col: 132;Row: 43;Color: True),
  256. (Col: 132;Row: 50;Color: True),
  257. }
  258. Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
  259. Var
  260. I : Integer;
  261. begin
  262. I:=SysVideoModeCount-1;
  263. SysSetVideoMode:=False;
  264. While (I>=0) and Not SysSetVideoMode do
  265. If (Mode.col=SysVMD[i].col) and
  266. (Mode.Row=SysVMD[i].Row) and
  267. (Mode.Color=SysVMD[i].Color) then
  268. SysSetVideoMode:=True
  269. else
  270. Dec(I);
  271. If SysSetVideoMode then
  272. begin
  273. if SysVideoModeSelector(Mode) then
  274. begin;
  275. ScreenWidth:=SysVMD[I].Col;
  276. ScreenHeight:=SysVMD[I].Row;
  277. ScreenColor:=SysVMD[I].Color;
  278. end else SysSetVideoMode := false;
  279. end;
  280. end;
  281. Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
  282. begin
  283. SysGetVideoModeData:=(Index<=SysVideoModeCount);
  284. If SysGetVideoModeData then
  285. Data:=SysVMD[Index];
  286. end;
  287. Function SysGetVideoModeCount : Word;
  288. begin
  289. SysGetVideoModeCount:=SysVideoModeCount;
  290. end;
  291. {$ASMMODE INTEL}
  292. procedure SysUpdateScreen (Force: boolean);
  293. var SOfs, CLen: cardinal;
  294. begin
  295. if not (Force) then
  296. asm
  297. push ebx
  298. push esi
  299. push edi
  300. cld
  301. mov esi, VideoBuf
  302. mov edi, OldVideoBuf
  303. mov eax, VideoBufSize
  304. mov ecx, eax
  305. shr ecx, 1
  306. shr ecx, 1
  307. repe
  308. cmpsd
  309. je @no_update
  310. inc ecx
  311. mov edx, eax
  312. mov ebx, ecx
  313. shl ebx, 1
  314. shl ebx, 1
  315. sub edx, ebx
  316. mov SOfs, edx
  317. mov Force, 1
  318. std
  319. mov edi, eax
  320. mov esi, VideoBuf
  321. add eax, esi
  322. sub eax, 4
  323. mov esi, eax
  324. mov eax, OldVideoBuf
  325. add eax, edi
  326. sub eax, 4
  327. mov edi, eax
  328. repe
  329. cmpsd
  330. inc ecx
  331. shl ecx, 1
  332. shl ecx, 1
  333. mov CLen, ecx
  334. @no_update:
  335. pop edi
  336. pop esi
  337. pop ebx
  338. end ['eax', 'ecx', 'edx']
  339. else
  340. begin
  341. SOfs := 0;
  342. CLen := VideoBufSize;
  343. end;
  344. // .MVC. Move video buffer to system video buffer.
  345. Move(VideoBuf^,SysVideoBuf^,VideoBufSize);
  346. if Force then
  347. begin
  348. VioShowBuf (SOfs, CLen, 0);
  349. Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
  350. OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
  351. end;
  352. end;
  353. Const
  354. SysVideoDriver : TVideoDriver = (
  355. InitDriver : @SysInitVideo;
  356. DoneDriver : @SysDoneVideo;
  357. UpdateScreen : @SysUpdateScreen;
  358. ClearScreen : @SysClearScreen;
  359. SetVideoMode : @SysSetVideoMode;
  360. GetVideoModeCount : @SysGetVideoModeCount;
  361. GetVideoModeData : @SysGetVideoModedata;
  362. SetCursorPos : @SysSetCursorPos;
  363. GetCursorType : @SysGetCursorType;
  364. SetCursorType : @SysSetCursorType;
  365. GetCapabilities : @SysGetCapabilities
  366. );
  367. procedure TargetEntry;
  368. var
  369. PScr: pointer;
  370. begin
  371. {Remember original video mode, cursor type and high bit behaviour setting}
  372. OrigVioMode.cb := SizeOf (OrigVioMode);
  373. VioGetMode (OrigVioMode, 0);
  374. VioGetCurType (OrigCurType, 0);
  375. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  376. with OrigHighBit do
  377. begin
  378. cb := 6;
  379. rType := 2;
  380. end;
  381. VioGetState (OrigHighBit, 0);
  382. { Register the curent video mode in reserved slot in System Modes}
  383. with OrigVioMode do
  384. begin
  385. {Assume we have at least 16 colours available in "colour" modes}
  386. SysVMD[SysVideoModeCount-1].Col:=Col;
  387. SysVMD[SysVideoModeCount-1].Row:=Row;
  388. SysVMD[SysVideoModeCount-1].Color:=(Color >= Colors_16);
  389. end;
  390. {Get the address of the original videobuffer and size.}
  391. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  392. begin
  393. PScr := SelToFlat (cardinal (PScr));
  394. GetMem (OrigScreen, OrigScreenSize);
  395. Move (PScr^, OrigScreen^, OrigScreenSize);
  396. end;
  397. end;
  398. initialization
  399. SetVideoDriver(SysVideoDriver);
  400. TargetEntry;
  401. end.
  402. {
  403. $Log$
  404. Revision 1.12 2004-12-27 18:44:45 hajny
  405. * fix for SIGSEGV when switching to higher resolution
  406. Revision 1.11 2004/09/13 20:58:58 hajny
  407. * SysSetVideoMode corrected to reflect SysVideoModeSelector result
  408. Revision 1.10 2004/05/24 19:33:22 hajny
  409. * regcall update
  410. Revision 1.9 2003/10/07 21:26:35 hajny
  411. * stdcall fixes and asm routines cleanup
  412. Revision 1.8 2003/10/03 21:46:41 peter
  413. * stdcall fixes
  414. Revision 1.7 2002/09/07 16:01:25 peter
  415. * old logs removed and tabs fixed
  416. }