video.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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. videoColorMap := pScreen(videoWindow^.WScreen)^.ViewPort.ColorMap;
  87. for counter:=0 to 15 do begin
  88. videoPens[counter]:=ObtainPen(videoColorMap,-1,
  89. vgacolors[counter,0] shl 24,vgacolors[counter,1] shl 24,vgacolors[counter,2] shl 24,
  90. PEN_EXCLUSIVE);
  91. // writeln(videoPens[counter]);
  92. // XXX: do checks for -1 colors (KB)
  93. end;
  94. CursorX:=0;
  95. CursorY:=0;
  96. oldCursorX:=0;
  97. oldCursorY:=0;
  98. visibleCursor:=true;
  99. oldvisibleCursor:=true;
  100. end;
  101. procedure SysDoneVideo;
  102. var counter: longint;
  103. begin
  104. if videoWindow<>nil then CloseWindow(videoWindow);
  105. for counter:=0 to 15 do ReleasePen(videoColorMap,videoPens[counter]);
  106. {
  107. SetConsoleScreenBufferSize (TextRec (Output).Handle, OrigConsoleInfo.dwSize);
  108. SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, OrigConsoleInfo.srWindow);
  109. SetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
  110. SetConsoleCP(OrigCP);
  111. }
  112. end;
  113. function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
  114. {
  115. var MI: Console_Screen_Buffer_Info;
  116. C: Coord;
  117. SR: Small_Rect;
  118. }
  119. begin
  120. {
  121. if not (GetConsoleScreenBufferInfo (TextRec (Output).Handle, MI)) then
  122. SysVideoModeSelector := false
  123. else
  124. begin
  125. with MI do
  126. begin
  127. C.X := VideoMode.Col;
  128. C.Y := VideoMode.Row;
  129. end;
  130. with SR do
  131. begin
  132. Top := 0;
  133. Left := 0;
  134. { First, we need to make sure we reach the minimum window size
  135. to always fit in the new buffer after changing buffer size. }
  136. Right := MI.srWindow.Right - MI.srWindow.Left;
  137. if VideoMode.Col <= Right then
  138. Right := Pred (VideoMode.Col);
  139. Bottom := MI.srWindow.Bottom - MI.srWindow.Top;
  140. if VideoMode.Row <= Bottom then
  141. Bottom := Pred (VideoMode.Row);
  142. end;
  143. if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
  144. if SetConsoleScreenBufferSize (TextRec (Output).Handle, C) then
  145. begin
  146. with SR do
  147. begin
  148. { Now, we can resize the window to the final size. }
  149. Right := Pred (VideoMode.Col);
  150. Bottom := Pred (VideoMode.Row);
  151. end;
  152. if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
  153. begin
  154. SysVideoModeSelector := true;
  155. SetCursorType (LastCursorType);
  156. ClearScreen;
  157. end
  158. else
  159. begin
  160. SysVideoModeSelector := false;
  161. SetConsoleScreenBufferSize (TextRec (Output).Handle, MI.dwSize);
  162. SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
  163. SetCursorType (LastCursorType);
  164. end
  165. end
  166. else
  167. begin
  168. SysVideoModeSelector := false;
  169. SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
  170. SetCursorType (LastCursorType);
  171. end
  172. else
  173. SysVideoModeSelector := false;
  174. end;
  175. }
  176. end;
  177. Const
  178. SysVideoModeCount = 6;
  179. SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
  180. (Col: 40; Row: 25; Color: True),
  181. (Col: 80; Row: 25; Color: True),
  182. (Col: 80; Row: 30; Color: True),
  183. (Col: 80; Row: 43; Color: True),
  184. (Col: 80; Row: 50; Color: True),
  185. (Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
  186. );
  187. Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
  188. Var
  189. I : Integer;
  190. begin
  191. {
  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. }
  211. end;
  212. Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
  213. begin
  214. SysGetVideoModeData:=(Index<=high(SysVMD));
  215. If SysGetVideoModeData then
  216. Data:=SysVMD[Index];
  217. end;
  218. Function SysGetVideoModeCount : Word;
  219. begin
  220. SysGetVideoModeCount:=SysVideoModeCount;
  221. end;
  222. procedure SysClearScreen;
  223. begin
  224. UpdateScreen(true);
  225. end;
  226. procedure DrawChar(x,y: longint; bitmap: pBitmap; drawCursor: boolean);
  227. var tmpCharData: word;
  228. tmpChar : byte;
  229. tmpRow : byte;
  230. tmpFGColor : byte;
  231. tmpBGColor : byte;
  232. var
  233. counterX, counterY:longint;
  234. sX,sY: longint;
  235. begin
  236. tmpCharData:=VideoBuf^[y*ScreenWidth+x];
  237. tmpChar :=tmpCharData and $0ff;
  238. tmpFGColor :=(tmpCharData shr 8) and %00001111;
  239. tmpBGColor :=(tmpCharData shr 12) and %00000111;
  240. // write('"',char(tmpChar),'" ',tmpChar);
  241. sX:=x*8;
  242. sY:=y*16;
  243. SetAPen(videoWindow^.RPort,videoPens[tmpBGColor]);
  244. RectFill(videoWindow^.RPort, sX, sY, sX + 7, sY + 15);
  245. SetAPen(videoWindow^.Rport,videoPens[tmpFGColor]);
  246. for counterY:=0 to 15 do begin
  247. tmpRow:=vgafont[tmpChar,counterY];
  248. if (tmpRow>0) then begin
  249. for counterX:=0 to 7 do begin
  250. if ((tmpRow and (1 shl counterX)) > 0) then
  251. WritePixel(videoWindow^.RPort,sX+counterX,sY+counterY);
  252. end;
  253. end;
  254. end;
  255. if drawCursor then begin
  256. gfxMove(videoWindow^.RPort,sX,sY+14); Draw(videoWindow^.RPort,sX+7,sY+14);
  257. gfxMove(videoWindow^.RPort,sX,sY+15); Draw(videoWindow^.RPort,sX+7,sY+15);
  258. end;
  259. end;
  260. procedure SysUpdateScreen(force: boolean);
  261. var
  262. BufCounter : Longint;
  263. smallforce : boolean;
  264. counter, counterX, counterY: longint;
  265. var
  266. tmpBitmap : tBitmap;
  267. begin
  268. if force then
  269. smallforce:=true
  270. else begin
  271. counter:=0;
  272. while not smallforce and (counter<(VideoBufSize div 4)-1) do begin
  273. if PDWord(VideoBuf)[counter]<>PDWord(OldVideoBuf)[counter] then smallforce:=true;
  274. counter+=1;
  275. end;
  276. end;
  277. BufCounter:=0;
  278. if smallforce then begin
  279. for counterY:=0 to ScreenHeight-1 do begin
  280. for counterX:=0 to ScreenWidth-1 do begin
  281. if VideoBuf^[BufCounter]<>OldVideoBuf^[BufCounter] then
  282. DrawChar(counterX,counterY,@tmpBitmap,false);
  283. Inc(BufCounter);
  284. end;
  285. end;
  286. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  287. end;
  288. if (oldvisibleCursor<>visibleCursor) or (CursorX<>oldCursorX) or (CursorY<>oldCursorY) then begin
  289. writeln('kurzor:',cursorx,' ',cursory);
  290. DrawChar(oldCursorY,oldCursorX,@tmpBitmap,false);
  291. DrawChar(CursorY,CursorX,@tmpBitmap,visibleCursor);
  292. oldCursorX:=CursorX;
  293. oldCursorY:=CursorY;
  294. oldVisibleCursor:=visibleCursor;
  295. end;
  296. end;
  297. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  298. begin
  299. CursorX:=NewCursorY;
  300. CursorY:=NewCursorX;
  301. SysUpdateScreen(false);
  302. end;
  303. function SysGetCapabilities: Word;
  304. begin
  305. SysGetCapabilities:=cpColor or cpChangeCursor;
  306. end;
  307. function SysGetCursorType: Word;
  308. begin
  309. if not visibleCursor then SysGetCursorType:=crHidden
  310. else SysGetCursorType:=crUnderline;
  311. {
  312. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  313. if not ConsoleCursorInfo.bvisible then
  314. SysGetCursorType:=crHidden
  315. else
  316. case ConsoleCursorInfo.dwSize of
  317. 1..30:
  318. SysGetCursorType:=crUnderline;
  319. 31..70:
  320. SysGetCursorType:=crHalfBlock;
  321. 71..100:
  322. SysGetCursorType:=crBlock;
  323. end;
  324. }
  325. end;
  326. procedure SysSetCursorType(NewType: Word);
  327. begin
  328. if newType=crHidden then visibleCursor:=false
  329. else visibleCursor:=true;
  330. SysUpdateScreen(false);
  331. {
  332. GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  333. if newType=crHidden then
  334. ConsoleCursorInfo.bvisible:=false
  335. else
  336. begin
  337. ConsoleCursorInfo.bvisible:=true;
  338. case NewType of
  339. crUnderline:
  340. ConsoleCursorInfo.dwSize:=10;
  341. crHalfBlock:
  342. ConsoleCursorInfo.dwSize:=50;
  343. crBlock:
  344. ConsoleCursorInfo.dwSize:=99;
  345. end
  346. end;
  347. SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
  348. }
  349. end;
  350. const
  351. SysVideoDriver : TVideoDriver = (
  352. InitDriver : @SysInitVideo;
  353. DoneDriver : @SysDoneVideo;
  354. UpdateScreen : @SysUpdateScreen;
  355. ClearScreen : @SysClearScreen;
  356. SetVideoMode : @SysSetVideoMode;
  357. GetVideoModeCount : @SysGetVideoModeCount;
  358. GetVideoModeData : @SysGetVideoModeData;
  359. SetCursorPos : @SysSetCursorPos;
  360. GetCursorType : @SysGetCursorType;
  361. SetCursorType : @SysSetCursorType;
  362. GetCapabilities : @SysGetCapabilities
  363. );
  364. initialization
  365. SetVideoDriver(SysVideoDriver);
  366. end.