video.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2006 by Karoly Balogh
  4. member of the Free Pascal development team
  5. Video unit for Amiga and MorphOS
  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 Video;
  13. interface
  14. uses
  15. intuition;
  16. {$i videoh.inc}
  17. var
  18. videoWindow : pWindow;
  19. implementation
  20. uses
  21. // dos
  22. exec,graphics;
  23. {$i video.inc}
  24. {$i videodata.inc}
  25. const
  26. LastCursorType: word = crUnderline;
  27. OrigScreen: PVideoBuf = nil;
  28. OrigScreenSize: cardinal = 0;
  29. var
  30. videoColorMap : pColorMap;
  31. videoPens : array[0..15] of longint;
  32. oldCursorX, oldCursorY: longint;
  33. visibleCursor: boolean;
  34. oldvisibleCursor: boolean;
  35. procedure SysInitVideo;
  36. var counter: longint;
  37. begin
  38. // writeln('sysinitvideo');
  39. InitGraphicsLibrary;
  40. InitIntuitionLibrary;
  41. {
  42. ScreenColor:=true;
  43. GetConsoleScreenBufferInfo(TextRec(Output).Handle, OrigConsoleInfo);
  44. GetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
  45. OrigCP := GetConsoleCP;
  46. ConsoleInfo:=OrigConsoleInfo;
  47. ConsoleCursorInfo:=OrigConsoleCursorInfo;
  48. {
  49. About the ConsoleCursorInfo record: There are 3 possible
  50. structures in it that can be regarded as the 'screen':
  51. - dwsize : contains the cols & row in current screen buffer.
  52. - srwindow : Coordinates (relative to buffer) of upper left
  53. & lower right corners of visible console.
  54. - dmMaximumWindowSize : Maximal size of Screen buffer.
  55. The first implementation of video used srWindow. After some
  56. bug-reports, this was switched to dwMaximumWindowSize.
  57. }
  58. with ConsoleInfo.dwMaximumWindowSize do
  59. begin
  60. ScreenWidth:=X;
  61. ScreenHeight:=Y;
  62. end;
  63. { TDrawBuffer only has FVMaxWidth elements
  64. larger values lead to crashes }
  65. if ScreenWidth> FVMaxWidth then
  66. ScreenWidth:=FVMaxWidth;
  67. CursorX:=ConsoleInfo.dwCursorPosition.x;
  68. CursorY:=ConsoleInfo.dwCursorPosition.y;
  69. if not ConsoleCursorInfo.bvisible then
  70. CursorLines:=0
  71. else
  72. CursorLines:=ConsoleCursorInfo.dwSize;
  73. }
  74. videoWindow:=OpenWindowTags(Nil, [
  75. WA_Left,50,
  76. WA_Top,50,
  77. WA_InnerWidth,80*8,
  78. WA_InnerHeight,25*16,
  79. // WA_IDCMP,IDCMP_MOUSEBUTTONS Or IDCMP_RAWKEYS,
  80. WA_IDCMP,IDCMP_VANILLAKEY Or IDCMP_RAWKEY,
  81. WA_Title,DWord(PChar('Free Pascal Video Output')),
  82. WA_Flags,(WFLG_GIMMEZEROZERO Or WFLG_SMART_REFRESH Or WFLG_NOCAREREFRESH Or WFLG_ACTIVATE Or WFLG_DRAGBAR Or WFLG_DEPTHGADGET)
  83. ]);
  84. ScreenWidth := 80;
  85. ScreenHeight := 25;
  86. ScreenColor := true;
  87. videoColorMap := pScreen(videoWindow^.WScreen)^.ViewPort.ColorMap;
  88. for counter:=0 to 15 do begin
  89. videoPens[counter]:=ObtainPen(videoColorMap,-1,
  90. vgacolors[counter,0] shl 24,vgacolors[counter,1] shl 24,vgacolors[counter,2] shl 24,
  91. PEN_EXCLUSIVE);
  92. // writeln(videoPens[counter]);
  93. // XXX: do checks for -1 colors (KB)
  94. end;
  95. CursorX:=0;
  96. CursorY:=0;
  97. oldCursorX:=0;
  98. oldCursorY:=0;
  99. visibleCursor:=true;
  100. oldvisibleCursor:=true;
  101. end;
  102. procedure SysDoneVideo;
  103. var counter: longint;
  104. begin
  105. if videoWindow<>nil then CloseWindow(videoWindow);
  106. for counter:=0 to 15 do ReleasePen(videoColorMap,videoPens[counter]);
  107. {
  108. SetConsoleScreenBufferSize (TextRec (Output).Handle, OrigConsoleInfo.dwSize);
  109. SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, OrigConsoleInfo.srWindow);
  110. SetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
  111. SetConsoleCP(OrigCP);
  112. }
  113. end;
  114. function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
  115. {
  116. var MI: Console_Screen_Buffer_Info;
  117. C: Coord;
  118. SR: Small_Rect;
  119. }
  120. begin
  121. {
  122. if not (GetConsoleScreenBufferInfo (TextRec (Output).Handle, MI)) then
  123. SysVideoModeSelector := false
  124. else
  125. begin
  126. with MI do
  127. begin
  128. C.X := VideoMode.Col;
  129. C.Y := VideoMode.Row;
  130. end;
  131. with SR do
  132. begin
  133. Top := 0;
  134. Left := 0;
  135. { First, we need to make sure we reach the minimum window size
  136. to always fit in the new buffer after changing buffer size. }
  137. Right := MI.srWindow.Right - MI.srWindow.Left;
  138. if VideoMode.Col <= Right then
  139. Right := Pred (VideoMode.Col);
  140. Bottom := MI.srWindow.Bottom - MI.srWindow.Top;
  141. if VideoMode.Row <= Bottom then
  142. Bottom := Pred (VideoMode.Row);
  143. end;
  144. if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
  145. if SetConsoleScreenBufferSize (TextRec (Output).Handle, C) then
  146. begin
  147. with SR do
  148. begin
  149. { Now, we can resize the window to the final size. }
  150. Right := Pred (VideoMode.Col);
  151. Bottom := Pred (VideoMode.Row);
  152. end;
  153. if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
  154. begin
  155. SysVideoModeSelector := true;
  156. SetCursorType (LastCursorType);
  157. ClearScreen;
  158. end
  159. else
  160. begin
  161. SysVideoModeSelector := false;
  162. SetConsoleScreenBufferSize (TextRec (Output).Handle, MI.dwSize);
  163. SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
  164. SetCursorType (LastCursorType);
  165. end
  166. end
  167. else
  168. begin
  169. SysVideoModeSelector := false;
  170. SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
  171. SetCursorType (LastCursorType);
  172. end
  173. else
  174. SysVideoModeSelector := false;
  175. end;
  176. }
  177. end;
  178. Const
  179. SysVideoModeCount = 6;
  180. SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
  181. (Col: 40; Row: 25; Color: True),
  182. (Col: 80; Row: 25; Color: True),
  183. (Col: 80; Row: 30; Color: True),
  184. (Col: 80; Row: 43; Color: True),
  185. (Col: 80; Row: 50; Color: True),
  186. (Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
  187. );
  188. Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
  189. Var
  190. I : Integer;
  191. begin
  192. I:=SysVideoModeCount-1;
  193. SysSetVideoMode:=False;
  194. While (I>=0) and Not SysSetVideoMode do
  195. If (Mode.col=SysVMD[i].col) and
  196. (Mode.Row=SysVMD[i].Row) and
  197. (Mode.Color=SysVMD[i].Color) then
  198. SysSetVideoMode:=True
  199. else
  200. Dec(I);
  201. If SysSetVideoMode then
  202. begin
  203. if SysVideoModeSelector(Mode) then
  204. begin
  205. ScreenWidth:=SysVMD[I].Col;
  206. ScreenHeight:=SysVMD[I].Row;
  207. ScreenColor:=SysVMD[I].Color;
  208. end else SysSetVideoMode := false;
  209. end;
  210. end;
  211. Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
  212. begin
  213. SysGetVideoModeData:=(Index<=high(SysVMD));
  214. If SysGetVideoModeData then
  215. Data:=SysVMD[Index];
  216. end;
  217. Function SysGetVideoModeCount : Word;
  218. begin
  219. SysGetVideoModeCount:=SysVideoModeCount;
  220. end;
  221. procedure SysClearScreen;
  222. begin
  223. UpdateScreen(true);
  224. end;
  225. procedure DrawChar(x,y: longint; bitmap: pBitmap; drawCursor: boolean);
  226. var tmpCharData: word;
  227. tmpChar : byte;
  228. tmpFGColor : byte;
  229. tmpBGColor : byte;
  230. var
  231. counterX, counterY:longint;
  232. sX,sY: longint;
  233. begin
  234. tmpCharData:=VideoBuf^[y*ScreenWidth+x];
  235. tmpChar :=tmpCharData and $0ff;
  236. tmpFGColor :=(tmpCharData shr 8) and %00001111;
  237. tmpBGColor :=(tmpCharData shr 12) and %00000111;
  238. sX:=x*8;
  239. sY:=y*16;
  240. SetAPen(videoWindow^.Rport,videoPens[tmpFGColor]);
  241. SetBPen(videoWindow^.RPort,videoPens[tmpBGColor]);
  242. BltTemplate(@vgafont[tmpChar,0],0,1,videoWindow^.RPort,sX,sY,8,16);
  243. if drawCursor then begin
  244. gfxMove(videoWindow^.RPort,sX,sY+14); Draw(videoWindow^.RPort,sX+7,sY+14);
  245. gfxMove(videoWindow^.RPort,sX,sY+15); Draw(videoWindow^.RPort,sX+7,sY+15);
  246. end;
  247. end;
  248. procedure SysUpdateScreen(force: boolean);
  249. var
  250. BufCounter : Longint;
  251. smallforce : boolean;
  252. counter, counterX, counterY: longint;
  253. var
  254. tmpBitmap : tBitmap;
  255. begin
  256. if force then
  257. smallforce:=true
  258. else begin
  259. counter:=0;
  260. while not smallforce and (counter<(VideoBufSize div 4)-1) do begin
  261. if PDWord(VideoBuf)[counter]<>PDWord(OldVideoBuf)[counter] then smallforce:=true;
  262. counter+=1;
  263. end;
  264. end;
  265. BufCounter:=0;
  266. if smallforce then begin
  267. for counterY:=0 to ScreenHeight-1 do begin
  268. for counterX:=0 to ScreenWidth-1 do begin
  269. if VideoBuf^[BufCounter]<>OldVideoBuf^[BufCounter] then
  270. DrawChar(counterX,counterY,@tmpBitmap,false);
  271. Inc(BufCounter);
  272. end;
  273. end;
  274. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  275. end;
  276. if (oldvisibleCursor<>visibleCursor) or (CursorX<>oldCursorX) or (CursorY<>oldCursorY) then begin
  277. writeln('kurzor:',cursorx,' ',cursory);
  278. DrawChar(oldCursorY,oldCursorX,@tmpBitmap,false);
  279. DrawChar(CursorY,CursorX,@tmpBitmap,visibleCursor);
  280. oldCursorX:=CursorX;
  281. oldCursorY:=CursorY;
  282. oldVisibleCursor:=visibleCursor;
  283. end;
  284. end;
  285. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  286. begin
  287. CursorX:=NewCursorY;
  288. CursorY:=NewCursorX;
  289. SysUpdateScreen(false);
  290. end;
  291. function SysGetCapabilities: Word;
  292. begin
  293. SysGetCapabilities:=cpColor or cpChangeCursor;
  294. end;
  295. function SysGetCursorType: Word;
  296. begin
  297. if not visibleCursor then SysGetCursorType:=crHidden
  298. else SysGetCursorType:=crUnderline;
  299. {
  300. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  301. if not ConsoleCursorInfo.bvisible then
  302. SysGetCursorType:=crHidden
  303. else
  304. case ConsoleCursorInfo.dwSize of
  305. 1..30:
  306. SysGetCursorType:=crUnderline;
  307. 31..70:
  308. SysGetCursorType:=crHalfBlock;
  309. 71..100:
  310. SysGetCursorType:=crBlock;
  311. end;
  312. }
  313. end;
  314. procedure SysSetCursorType(NewType: Word);
  315. begin
  316. if newType=crHidden then visibleCursor:=false
  317. else visibleCursor:=true;
  318. SysUpdateScreen(false);
  319. {
  320. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  321. if newType=crHidden then
  322. ConsoleCursorInfo.bvisible:=false
  323. else
  324. begin
  325. ConsoleCursorInfo.bvisible:=true;
  326. case NewType of
  327. crUnderline:
  328. ConsoleCursorInfo.dwSize:=10;
  329. crHalfBlock:
  330. ConsoleCursorInfo.dwSize:=50;
  331. crBlock:
  332. ConsoleCursorInfo.dwSize:=99;
  333. end
  334. end;
  335. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  336. }
  337. end;
  338. const
  339. SysVideoDriver : TVideoDriver = (
  340. InitDriver : @SysInitVideo;
  341. DoneDriver : @SysDoneVideo;
  342. UpdateScreen : @SysUpdateScreen;
  343. ClearScreen : @SysClearScreen;
  344. SetVideoMode : @SysSetVideoMode;
  345. GetVideoModeCount : @SysGetVideoModeCount;
  346. GetVideoModeData : @SysGetVideoModeData;
  347. SetCursorPos : @SysSetCursorPos;
  348. GetCursorType : @SysGetCursorType;
  349. SetCursorType : @SysSetCursorType;
  350. GetCapabilities : @SysGetCapabilities
  351. );
  352. initialization
  353. SetVideoDriver(SysVideoDriver);
  354. end.