modes.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. This include implements video mode management.
  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. {-----------------------------------------------------------------------}
  13. { Internal routines }
  14. {-----------------------------------------------------------------------}
  15. {$ifdef newmodes}
  16. procedure res2Mode(x, y, maxColor: longint; var driver,mode: smallInt);
  17. var
  18. l: longint;
  19. begin
  20. case maxColor of
  21. 2: driver := D1bit;
  22. 4: driver := D2bit;
  23. 16: driver := D4bit;
  24. 64: driver := D6bit;
  25. 256: driver := D8bit;
  26. 4096: driver := D12bit;
  27. 32768: driver := D15bit;
  28. 65536: driver := D16bit;
  29. { not yet supported
  30. 65536*256: driver := D24bit;
  31. 65536*65536: driver := D32bit;}
  32. else
  33. begin
  34. driver := maxsmallint;
  35. exit;
  36. end;
  37. end;
  38. { Check whether this is known/predefined mode }
  39. for l := lowNewMode to highNewMode do
  40. if (resolutions[l].x = x) and
  41. (resolutions[l].y = y) then
  42. begin
  43. { Found! }
  44. mode := l;
  45. exit;
  46. end;
  47. { Not Found }
  48. mode := maxsmallint;
  49. end;
  50. function mode2res(modeNr: smallInt; var x,y: longint): boolean;
  51. begin
  52. if (modeNr < lowNewMode) or
  53. (modeNr > highNewMode) then
  54. begin
  55. mode2res := false;
  56. exit;
  57. end;
  58. mode2res := true;
  59. x := resolutions[modeNr].x;
  60. y := resolutions[modeNr].y;
  61. end;
  62. {$endif newmodes}
  63. procedure addmode(const mode: TModeInfo);
  64. {********************************************************}
  65. { Procedure AddMode() }
  66. {--------------------------------------------------------}
  67. { This routine adds <mode> to the list of recognized }
  68. { modes. Duplicates are allowed. }
  69. {********************************************************}
  70. var
  71. {$ifdef newmodes}
  72. driverNr, modeNr: smallint;
  73. prev: PModeInfo;
  74. {$endif newmodes}
  75. list: PModeInfo;
  76. newlst : PModeInfo;
  77. begin
  78. {$ifdef newmodes}
  79. res2Mode(mode.maxx+1,mode.maxy+1,mode.maxColor,driverNr,ModeNr);
  80. { bitdepth supported? }
  81. if (driverNr <> maxsmallint) then
  82. { Yes, add the mode }
  83. if not assigned(newModeList.modeinfo[driverNr]) then
  84. begin
  85. new(newModeList.modeinfo[driverNr]);
  86. newModeList.modeinfo[driverNr]^ := mode;
  87. with newModeList.modeinfo[driverNr]^ do
  88. begin
  89. driverNumber := driverNr;
  90. modeNumber := 1;
  91. next := nil;
  92. end;
  93. newModeList.loHiModeNr[driverNr].lo := 1;
  94. newModeList.loHiModeNr[driverNr].hi := 1;
  95. end
  96. else
  97. begin
  98. prev := nil;
  99. list := newModeList.modeinfo[driverNr];
  100. { sort first by x resolution, then by yresolution }
  101. while assigned(list) and
  102. ((list^.maxx < mode.maxx) or
  103. ((list^.maxx = mode.maxx) and
  104. (list^.maxy < mode.maxy))) do
  105. begin
  106. prev := list;
  107. list := list^.next;
  108. end;
  109. { mode already exists? -> replace (assume later added modes are }
  110. { better) }
  111. if assigned(list) and
  112. (list^.maxx = mode.maxx) and
  113. (list^.maxy = mode.maxy) then
  114. begin
  115. { save/restore next, drivernr and drivermode in list }
  116. driverNr := list^.driverNumber;
  117. modeNr := list^.modeNumber;
  118. prev := list^.next;
  119. list^ := mode;
  120. list^.driverNumber := driverNr;
  121. list^.modeNumber := modeNr;
  122. list^.next := prev;
  123. end
  124. else
  125. begin
  126. new(newLst);
  127. { Increase the number of modes for this driver }
  128. inc(newModeList.loHiModeNr[driverNr].hi);
  129. newLst^ := mode;
  130. newLst^.driverNumber := driverNr;
  131. if assigned(list) then
  132. newLst^.next := list^.next
  133. else
  134. newLst^.next := nil;
  135. if assigned(prev) then
  136. begin
  137. prev^.next := newLst;
  138. newLst^.modeNumber := succ(prev^.modeNumber)
  139. end
  140. else
  141. begin
  142. newModeList.modeinfo[driverNr] := newLst;
  143. newLst^.modeNumber := 1;
  144. end;
  145. { Increase the modenumbers of all modes coming after this one }
  146. { with 1 }
  147. newLst := newLst^.next;
  148. while assigned(newLst) do
  149. begin
  150. inc(newLst^.modeNumber);
  151. newLst := newLst^.next;
  152. end;
  153. end;
  154. end;
  155. {$endif newmodes}
  156. { TP-like mode stuff }
  157. if not assigned(ModeList) then
  158. begin
  159. new(ModeList);
  160. move(mode, ModeList^, sizeof(Mode));
  161. end
  162. else
  163. begin
  164. list := ModeList;
  165. { go to the end of the list }
  166. while assigned(list^.next) do
  167. list:=list^.next;
  168. new(NewLst);
  169. list^.next := NewLst;
  170. move(mode, NewLst^, sizeof(Mode));
  171. end;
  172. end;
  173. procedure initmode(var mode: TModeInfo);
  174. {********************************************************}
  175. { Procedure InitMode() }
  176. {--------------------------------------------------------}
  177. { This routine initialized the mode to default values. }
  178. {********************************************************}
  179. begin
  180. FillChar(mode,sizeof(Mode),#0);
  181. end;
  182. function searchmode(ReqDriver : smallint; var reqmode: smallint): PModeInfo;
  183. {********************************************************}
  184. { Procedure SearchMode() }
  185. {--------------------------------------------------------}
  186. { This routine searches the list of recognized modes, }
  187. { and tries to find the <reqmode> in the <reqdriver> }
  188. { return nil if not found, otherwise returns the found }
  189. { structure. }
  190. { note: if reqmode = -32768, the first mode available }
  191. { for reqdriver is returned (JM) }
  192. { if reqmode = -32767, the last mode available }
  193. { for reqdriver is returned (JM) }
  194. {********************************************************}
  195. var
  196. list, lastModeInfo: PModeInfo;
  197. x,y: longint;
  198. begin
  199. {$ifdef logging}
  200. LogLn('Searching for driver '+strf(reqdriver)+' and mode '+strf(reqmode));
  201. {$endif logging}
  202. {$ifdef newmodes}
  203. if (reqDriver >= lowNewDriver) and
  204. (reqDriver <= highNewDriver) then
  205. begin
  206. case reqMode of
  207. -32768:
  208. begin
  209. reqMode := newModeList.loHiModeNr[reqDriver].lo;
  210. searchMode := newModeList.modeinfo[reqDriver];
  211. end;
  212. -32767:
  213. begin
  214. reqMode := newModeList.loHiModeNr[reqDriver].hi;
  215. searchMode := nil;
  216. { Are there any modes available for this driver? }
  217. if reqMode <> -1 then
  218. begin
  219. list := newModeList.modeinfo[reqDriver];
  220. while assigned(list^.next) do
  221. list := list^.next;
  222. searchMode := list;
  223. end;
  224. end;
  225. else
  226. begin
  227. list := newModeList.modeinfo[reqDriver];
  228. searchMode := nil;
  229. if not assigned(list) then
  230. exit;
  231. if mode2res(reqMode,x,y) then
  232. begin
  233. x := pred(x);
  234. y := pred(y);
  235. while assigned(list) and
  236. ((list^.maxx < x) or
  237. ((list^.maxx = x) and
  238. (list^.maxy < y))) do
  239. list := list^.next;
  240. if not assigned(list) or
  241. (list^.maxx <> x) or
  242. (list^.maxy <> y) then
  243. list := nil;
  244. searchmode := list;
  245. end
  246. else
  247. begin
  248. while assigned(list) and
  249. (list^.modeNumber <> reqMode) do
  250. list := list^.next;
  251. searchMode := list;
  252. end;
  253. end;
  254. end;
  255. exit;
  256. end;
  257. {$endif newmodes}
  258. searchmode := nil;
  259. list := ModeList;
  260. If assigned(list) then
  261. lastModeInfo := list;
  262. { go to the end of the list }
  263. while assigned(list) do
  264. begin
  265. {$ifdef logging}
  266. Log('Found driver '+strf(list^.DriverNumber)+
  267. ' and mode $'+hexstr(list^.ModeNumber,4)+'... ');
  268. {$endif logging}
  269. if ((list^.DriverNumber = ReqDriver) and
  270. ((list^.ModeNumber = ReqMode) or
  271. { search for lowest mode }
  272. (reqMode = -32768))) or
  273. { search for highest mode }
  274. ((reqMode = -32767) and
  275. (lastModeInfo^.driverNumber = reqDriver) and
  276. ((list^.driverNumber <> lastModeInfo^.driverNumber) or
  277. not(assigned(list^.next)))) then
  278. begin
  279. {$ifdef logging}
  280. LogLn('Accepted!');
  281. {$endif logging}
  282. searchmode := list;
  283. If reqMode = -32768 then
  284. reqMode := list^.modeNumber
  285. else if reqMode = -32767 then
  286. begin
  287. reqMode := lastModeInfo^.modeNumber;
  288. searchMode := lastModeInfo;
  289. end;
  290. exit;
  291. end;
  292. {$ifdef logging}
  293. LogLn('Rejected.');
  294. {$endif logging}
  295. lastModeInfo := list;
  296. list:=list^.next;
  297. end;
  298. end;
  299. {-----------------------------------------------------------------------}
  300. { External routines }
  301. {-----------------------------------------------------------------------}
  302. function GetModeName(ModeNumber: smallint): string;
  303. {********************************************************}
  304. { Function GetModeName() }
  305. {--------------------------------------------------------}
  306. { Checks the known video list, and returns ModeName }
  307. { string. On error returns an empty string. }
  308. {********************************************************}
  309. var
  310. mode: PModeInfo;
  311. begin
  312. mode:=nil;
  313. GetModeName:='';
  314. { only search in the current driver modes ... }
  315. mode:=SearchMode(IntCurrentDriver,ModeNumber);
  316. if assigned(mode) then
  317. GetModeName:=Mode^.ModeName
  318. else
  319. _GraphResult := grInvalidMode;
  320. end;
  321. function GetGraphMode: smallint;
  322. begin
  323. GetGraphMode := IntCurrentMode;
  324. end;
  325. function GetMaxMode: word;
  326. { I know , i know, this routine is very slow, and it would }
  327. { be much easier to sort the linked list of possible modes }
  328. { instead of doing this, but I'm lazy!! And anyways, the }
  329. { speed of the routine here is not that important.... }
  330. var
  331. i: word;
  332. mode: PModeInfo;
  333. begin
  334. mode:=nil;
  335. i:=0;
  336. repeat
  337. inc(i);
  338. { mode 0 always exists... }
  339. { start search at 1.. }
  340. mode:=SearchMode(IntCurrentDriver,i);
  341. until not assigned(mode);
  342. GetMaxMode:=i;
  343. end;
  344. procedure GetModeRange(GraphDriver: smallint; var LoMode,
  345. HiMode: smallint);
  346. var
  347. mode : PModeInfo;
  348. begin
  349. {$ifdef logging}
  350. LogLn('GetModeRange : Enter ('+strf(GraphDriver)+')');
  351. {$endif}
  352. HiMode:=-1;
  353. mode := nil;
  354. { First search if the graphics driver is supported .. }
  355. { since mode zero is always supported.. if that driver }
  356. { is supported it should return something... }
  357. { not true, e.g. VESA doesn't have a mode 0. Changed so}
  358. { -32768 means "return lowest mode in second parameter }
  359. { also, under VESA some modes may not be supported }
  360. { (e.g. $108 here) while some with a higher number can }
  361. { be supported ($112 and onward), so I also added that }
  362. { -32767 means "return highest mode in second parameter}
  363. { This whole system should be overhauled though to work}
  364. { without such hacks (JM) }
  365. loMode := -32768;
  366. mode := SearchMode(GraphDriver, loMode);
  367. { driver not supported...}
  368. if not assigned(mode) then
  369. begin
  370. loMode := -1;
  371. exit;
  372. end;
  373. {$ifdef logging}
  374. LogLn('GetModeRange : Mode 0 found');
  375. {$endif}
  376. { now it exists... find highest available mode... }
  377. hiMode := -32767;
  378. mode:=SearchMode(GraphDriver,hiMode);
  379. end;
  380. procedure SetGraphMode(mode: smallint);
  381. var
  382. modeinfo: PModeInfo;
  383. begin
  384. { check if the mode exists... }
  385. modeinfo := searchmode(IntcurrentDriver,mode);
  386. if not assigned(modeinfo) then
  387. begin
  388. {$ifdef logging}
  389. LogLn('Mode setting failed in setgraphmode pos 1');
  390. {$endif logging}
  391. _GraphResult := grInvalidMode;
  392. exit;
  393. end;
  394. { reset all hooks...}
  395. DefaultHooks;
  396. { arccall not reset - tested against VGA BGI driver }
  397. { Setup all hooks if none, keep old defaults...}
  398. { required hooks - returns error if no hooks to these }
  399. { routines. }
  400. if assigned(modeinfo^.DirectPutPixel) then
  401. DirectPutPixel := modeinfo^.DirectPutPixel
  402. else
  403. begin
  404. {$ifdef logging}
  405. LogLn('Mode setting failed in setgraphmode pos 2');
  406. {$endif logging}
  407. _Graphresult := grInvalidMode;
  408. exit;
  409. end;
  410. if assigned(modeinfo^.PutPixel) then
  411. PutPixel := modeinfo^.PutPixel
  412. else
  413. begin
  414. {$ifdef logging}
  415. LogLn('Mode setting failed in setgraphmode pos 3');
  416. {$endif logging}
  417. _Graphresult := grInvalidMode;
  418. exit;
  419. end;
  420. if assigned(modeinfo^.GetPixel) then
  421. GetPixel := modeinfo^.GetPixel
  422. else
  423. begin
  424. {$ifdef logging}
  425. LogLn('Mode setting failed in setgraphmode pos 4');
  426. {$endif logging}
  427. _Graphresult := grInvalidMode;
  428. exit;
  429. end;
  430. if assigned(modeinfo^.SetRGBPalette) then
  431. SetRGBPalette := modeinfo^.SetRGBPalette
  432. else
  433. begin
  434. {$ifdef logging}
  435. LogLn('Mode setting failed in setgraphmode pos 5');
  436. {$endif logging}
  437. _Graphresult := grInvalidMode;
  438. exit;
  439. end;
  440. if assigned(modeinfo^.GetRGBPalette) then
  441. GetRGBPalette := modeinfo^.GetRGBPalette
  442. else
  443. begin
  444. {$ifdef logging}
  445. LogLn('Mode setting failed in setgraphmode pos 6');
  446. {$endif logging}
  447. _Graphresult := grInvalidMode;
  448. exit;
  449. end;
  450. { optional hooks. }
  451. if assigned(modeinfo^.ClearViewPort) then
  452. ClearViewPort := modeinfo^.ClearViewPort;
  453. if assigned(modeinfo^.PutImage) then
  454. PutImage := modeinfo^.PutImage;
  455. if assigned(modeinfo^.GetImage) then
  456. GetImage := modeinfo^.GetImage;
  457. if assigned(modeinfo^.ImageSize) then
  458. ImageSize := modeinfo^.ImageSize;
  459. if assigned(modeinfo^.GetScanLine) then
  460. GetScanLine := modeinfo^.GetScanLine;
  461. if assigned(modeinfo^.Line) then
  462. Line := modeinfo^.Line;
  463. if assigned(modeinfo^.InternalEllipse) then
  464. InternalEllipse := modeinfo^.InternalEllipse;
  465. if assigned(modeinfo^.PatternLine) then
  466. PatternLine := modeinfo^.PatternLine;
  467. if assigned(modeinfo^.HLine) then
  468. Hline := modeinfo^.Hline;
  469. if assigned(modeinfo^.Vline) then
  470. VLine := modeinfo^.VLine;
  471. if assigned(modeInfo^.SetVisualPage) then
  472. SetVisualPage := modeInfo^.SetVisualPage;
  473. if assigned(modeInfo^.SetActivePage) then
  474. SetActivePage := modeInfo^.SetActivePage;
  475. if assigned(modeInfo^.OutTextXY) then
  476. OutTextXY:=modeInfo^.OutTextXY;
  477. IntCurrentMode := modeinfo^.ModeNumber;
  478. IntCurrentDriver := modeinfo^.DriverNumber;
  479. XAspect := modeinfo^.XAspect;
  480. YAspect := modeinfo^.YAspect;
  481. MaxX := modeinfo^.MaxX;
  482. MaxY := modeinfo^.MaxY;
  483. HardwarePages := modeInfo^.HardwarePages;
  484. MaxColor := modeinfo^.MaxColor;
  485. PaletteSize := modeinfo^.PaletteSize;
  486. { is this a direct color mode? }
  487. DirectColor := modeinfo^.DirectColor;
  488. { now actually initialize the video mode...}
  489. { check first if the routine exists }
  490. if not assigned(modeinfo^.InitMode) then
  491. begin
  492. {$ifdef logging}
  493. LogLn('Mode setting failed in setgraphmode pos 7');
  494. {$endif logging}
  495. _GraphResult := grInvalidMode;
  496. exit;
  497. end;
  498. modeinfo^.InitMode;
  499. if _GraphResult <> grOk then exit;
  500. isgraphmode := true;
  501. { It is very important that this call be made }
  502. { AFTER the other variables have been setup. }
  503. { Since it calls some routines which rely on }
  504. { those variables. }
  505. SetActivePage(0);
  506. SetVisualPage(0);
  507. GraphDefaults;
  508. SetViewPort(0,0,MaxX,MaxY,TRUE);
  509. end;
  510. procedure RestoreCrtMode;
  511. {********************************************************}
  512. { Procedure RestoreCRTMode() }
  513. {--------------------------------------------------------}
  514. { Returns to the video mode which was set before the }
  515. { InitGraph. Hardware state is set to the old values. }
  516. {--------------------------------------------------------}
  517. { NOTE: - }
  518. { - }
  519. {********************************************************}
  520. begin
  521. isgraphmode := false;
  522. RestoreVideoState;
  523. end;
  524. {
  525. $Log$
  526. Revision 1.25 2000-06-19 01:18:49 carl
  527. + added modes for Atari/Amiga and bit depth also
  528. Revision 1.24 2000/06/18 14:59:39 jonas
  529. * changed maxint -> maxsmallint (range error because of objpas mod
  530. somewhere)
  531. Revision 1.23 2000/06/17 19:09:23 jonas
  532. * new platform independent mode handling (between -dnewmodes)
  533. Revision 1.22 2000/04/02 12:13:37 florian
  534. * some more procedures can be now hooked by the OS specific implementation
  535. Revision 1.21 2000/03/24 18:16:33 florian
  536. * introduce a DrawBitmapCharHoriz procedure variable to accelerate output on
  537. win32
  538. Revision 1.20 2000/03/24 13:01:15 florian
  539. * ClearViewPort fixed
  540. Revision 1.19 2000/01/07 16:41:39 daniel
  541. * copyright 2000
  542. Revision 1.18 2000/01/07 16:32:26 daniel
  543. * copyright 2000 added
  544. Revision 1.17 2000/01/02 19:02:39 jonas
  545. * removed/commented out (inited but) unused vars and unused types
  546. Revision 1.16 1999/12/21 17:42:18 jonas
  547. * changed vesa.inc do it doesn't try to use linear modes anymore (doesn't work
  548. yet!!)
  549. * fixed mode detection so the low modenumber of a driver doesn't have to be zero
  550. anymore (so VESA autodetection now works)
  551. Revision 1.15 1999/12/20 11:22:36 peter
  552. * integer -> smallint to overcome -S2 switch needed for ggi version
  553. Revision 1.14 1999/12/04 21:20:04 michael
  554. + Additional logging
  555. Revision 1.13 1999/11/28 16:13:55 jonas
  556. * corrected misplacement of call to initvars in initgraph
  557. + some extra debugging commands (for -dlogging) in the mode functions
  558. Revision 1.12 1999/09/28 13:56:31 jonas
  559. * reordered some local variables (first 4 byte vars, then 2 byte vars
  560. etc)
  561. * font data is now disposed in exitproc, exitproc is now called
  562. GraphExitProc (was CleanModes) and resides in graph.pp instead of in
  563. modes.inc
  564. Revision 1.11 1999/09/26 13:31:07 jonas
  565. * changed name of modeinfo variable to vesamodeinfo and fixed
  566. associated errors (fillchar(modeinfo,sizeof(tmodeinfo),#0) instead
  567. of sizeof(TVesamodeinfo) etc)
  568. * changed several sizeof(type) to sizeof(varname) to avoid similar
  569. errors in the future
  570. Revision 1.10 1999/09/24 22:52:39 jonas
  571. * optimized patternline a bit (always use hline when possible)
  572. * isgraphmode stuff cleanup
  573. * vesainfo.modelist now gets disposed in cleanmode instead of in
  574. closegraph (required moving of some declarations from vesa.inc to
  575. new vesah.inc)
  576. * queryadapter gets no longer called from initgraph (is called from
  577. initialization of graph unit)
  578. * bugfix for notput in 32k and 64k vesa modes
  579. * a div replaced by / in fillpoly
  580. Revision 1.9 1999/09/22 13:13:36 jonas
  581. * renamed text.inc -> gtext.inc to avoid conflict with system unit
  582. * fixed textwidth
  583. * isgraphmode now gets properly updated, so mode restoring works
  584. again
  585. Revision 1.8 1999/09/18 22:21:11 jonas
  586. + hlinevesa256 and vlinevesa256
  587. + support for not/xor/or/andput in vesamodes with 32k/64k colors
  588. * lots of changes to avoid warnings under FPC
  589. Revision 1.7 1999/07/12 13:27:14 jonas
  590. + added Log and Id tags
  591. * added first FPC support, only VGA works to some extend for now
  592. * use -dasmgraph to use assembler routines, otherwise Pascal
  593. equivalents are used
  594. * use -dsupportVESA to support VESA (crashes under FPC for now)
  595. * only dispose vesainfo at closegrph if a vesa card was detected
  596. * changed int32 to longint (int32 is not declared under FPC)
  597. * changed the declaration of almost every procedure in graph.inc to
  598. "far;" becquse otherwise you can't assign them to procvars under TP
  599. real mode (but unexplainable "data segnment too large" errors prevent
  600. it from working under real mode anyway)
  601. }