GRAPHI.MOD 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * GRAPHI.MOD - OS/2 graphics functions requiring IOPL *
  5. * *
  6. * COPYRIGHT (C) 1987..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. (*# call(o_a_copy=>off) *)
  11. (*# module(implementation=>off) *)
  12. (*%F _fdata *)
  13. (*# data(seg_name => null) *)
  14. (*%E *)
  15. (*# check(stack=>off,
  16. index=>off,
  17. range=>off,
  18. overflow=>off,
  19. nil_ptr=>off) *)
  20. IMPLEMENTATION MODULE GraphI;
  21. (*# call(near_call=>off,
  22. seg_name=>GRAPH_IOPL,
  23. iopl=>on) *)
  24. IMPORT Graph, Dos;
  25. CONST
  26. CGAWidth = 320 ;
  27. CGADepth = 200 ;
  28. CGANumColor = 4 ;
  29. EGAWidth = 640 ;
  30. EGADepth = 350 ;
  31. VGAWidth = 640 ;
  32. VGADepth = 350 ;
  33. EGANumColor = 16 ;
  34. VGA256Width = 320 ;
  35. VGA256Depth = 200 ;
  36. VGANumColor = 16 ;
  37. CONST
  38. HercWidth = 720 ;
  39. HercDepth = 348 ;
  40. HercNumColor = 2 ;
  41. ATTWidth = 640 ;
  42. ATTDepth = 400 ;
  43. ATTNumColor = 2 ;
  44. PROCEDURE SaveScreen;
  45. VAR
  46. BitMap : CARDINAL;
  47. bp : CGABuffPtr;
  48. BEGIN
  49. IF IsCGA THEN
  50. bp := FarADR(CBuffer);
  51. GRCopy(bp, [VideoSel:0 CGABuffPtr], 4000H);
  52. ELSE
  53. FOR BitMap := 0 TO MaxBitMap DO
  54. Out(3CEH,4);
  55. Out(3CFH,SHORTCARD(BitMap));
  56. GRCopy(Buffer[BitMap], [VideoSel:0 BMP], BitMapSize);
  57. END;
  58. END;
  59. END SaveScreen;
  60. PROCEDURE RestoreScreen();
  61. VAR
  62. BitMap : CARDINAL;
  63. BEGIN
  64. IF IsCGA THEN
  65. GRCopy([VideoSel:0 CGABuffPtr], FarADR(CBuffer), 4000H);
  66. ELSE
  67. FOR BitMap := 0 TO MaxBitMap DO
  68. Out( 3C4H,2);Out( 3C5H,SHORTCARD(1<<BitMap));
  69. GRCopy([VideoSel:0 BMP], Buffer[BitMap], BitMapSize);
  70. END;
  71. END ;
  72. END RestoreScreen;
  73. PROCEDURE EGAPlot( x,y,c : CARDINAL); (* Also VGA *)
  74. VAR
  75. (*# save, data(volatile=>on) *)
  76. t:BS;
  77. (*# restore *)
  78. p,b,s,i,bi:CARDINAL;
  79. BEGIN
  80. IF (x < EGAWidth) AND (y < Graph.Depth) THEN
  81. bi := (7-(x MOD 8));
  82. p := y*80+(x DIV 8);
  83. IF Virtual THEN
  84. FOR i := 0 TO 3 DO
  85. IF i IN BS(c) THEN
  86. INCL(BS(Buffer[i]^[p]),bi)
  87. ELSE
  88. EXCL(BS(Buffer[i]^[p]),bi);
  89. END;
  90. END;
  91. ELSE
  92. b := 1 << bi;
  93. Out( 3CEH,8);Out( 3CFH,SHORTCARD(b));
  94. Out( 3C4H,2);Out( 3C5H,0FH);
  95. s := VideoSel;
  96. t := [s:p BP]^;
  97. [s:p BP]^ := BS{};
  98. Out( 3C4H,2);Out( 3C5H,SHORTCARD(c));
  99. [s:p BP]^ := BS{0..7};
  100. Out( 3CEH,8);Out( 3CFH,0FFH);
  101. Out( 3C4H,2);Out( 3C5H,0FH);
  102. END;
  103. END;
  104. END EGAPlot;
  105. PROCEDURE EGAPoint(x,y:CARDINAL) : CARDINAL; (* Also VGA *)
  106. VAR
  107. t:BS;
  108. p,b,s,i:CARDINAL;
  109. c:CARDINAL;
  110. BEGIN
  111. c := 0;
  112. IF (x < EGAWidth) AND (y < Graph.Depth) THEN
  113. b := 1 << (7-(x MOD 8));
  114. p := y*80+(x DIV 8 );
  115. IF Virtual THEN
  116. FOR i := 3 TO 0 BY -1 DO
  117. t := BS(Buffer[i]^[p])*BS(b);
  118. c := c * 2 + CARDINAL( SHORTCARD(t) );
  119. END;
  120. ELSE
  121. s := VideoSel;
  122. Out( 3CEH, 4 ); (* read map sel *)
  123. Out( 3CFH, 3 );
  124. t := [s:p BP]^;
  125. t := t * BS(b);
  126. c := CARDINAL( SHORTCARD(t) );
  127. Out( 3CFH, 2 );
  128. t := [s:p BP]^;
  129. t := t * BS(b);
  130. c := c * 2 + CARDINAL( SHORTCARD(t) );
  131. Out( 3CFH, 1 );
  132. t := [s:p BP]^;
  133. t := t * BS(b);
  134. c := c * 2 + CARDINAL( SHORTCARD(t) );
  135. Out( 3CFH, 0 );
  136. t := [s:p BP]^;
  137. t := t * BS(b);
  138. c := c * 2 + CARDINAL( SHORTCARD(t) );
  139. END;
  140. c := c >> ( 7 - ( x MOD 8 ) );
  141. END;
  142. RETURN c;
  143. END EGAPoint;
  144. PROCEDURE EGAHLine ( x,y,x2 : CARDINAL; c:CARDINAL ); (* Also VGA *)
  145. VAR c1,c2,i : CARDINAL;
  146. BEGIN
  147. IF y >= Graph.Depth THEN RETURN END;
  148. IF INTEGER(x) >= INTEGER(EGAWidth) THEN RETURN END;
  149. IF INTEGER(x) < 0 THEN x := 0; END;
  150. IF x2 >= EGAWidth THEN x2 := EGAWidth-1 END;
  151. WHILE (x MOD 8 # 0) AND (x <= x2) DO
  152. EGAPlot( x , y , c ); INC( x );
  153. END;
  154. WHILE (x2 MOD 8 # 7) AND (x <= x2) DO
  155. EGAPlot( x2 , y , c ); DEC( x2 );
  156. END;
  157. IF INTEGER(x) > INTEGER(x2) THEN RETURN; END;
  158. y := y*80;
  159. x := x DIV 8;
  160. x2 := x2 DIV 8;
  161. IF Virtual THEN
  162. INC(y,x);
  163. WHILE x <= x2 DO
  164. FOR i := 0 TO 3 DO
  165. IF i IN BS(c) THEN
  166. Buffer[i]^[y] := BS{0..7};
  167. ELSE
  168. Buffer[i]^[y] := BS{};
  169. END;
  170. END;
  171. INC( x );
  172. INC( y );
  173. END;
  174. ELSE
  175. Out( 3CEH,8);Out( 3CFH,0FFH);
  176. Out( 3C4H,2);Out( 3C5H,0FH);
  177. Out( 3CEH,5);Out( 3CFH,2);
  178. WHILE x <= x2 DO
  179. [VideoSel:y+x BP]^ := BS(c);
  180. INC( x );
  181. END;
  182. END ;
  183. Out( 3CEH,5);Out( 3CFH,0);
  184. END EGAHLine;
  185. (* -- CGA routines -- *)
  186. PROCEDURE SaveCGAScreen;
  187. BEGIN
  188. GRCopy([VideoSel:0 CGABuffPtr], FarADR(CBuffer), 4000H);
  189. END SaveCGAScreen;
  190. PROCEDURE RestoreCGAScreen();
  191. VAR
  192. bp : CGABuffPtr;
  193. BEGIN
  194. bp := FarADR(CBuffer);
  195. GRCopy(bp, [VideoSel:0 CGABuffPtr], 4000H);
  196. END RestoreCGAScreen;
  197. PROCEDURE CGAPlot(x,y:CARDINAL;c:CARDINAL);
  198. VAR
  199. off : CARDINAL;
  200. seg : CARDINAL;
  201. tmp : CARDINAL;
  202. BEGIN
  203. IF (x >= CGAWidth) OR (y >= CGADepth) THEN RETURN END;
  204. off := x >> 2;
  205. IF ODD(y) THEN INC( off, 2000H - 40 ) END;
  206. INC( y, y << 2 );
  207. INC( off, y << 3 );
  208. x := 3 - CARDINAL( BITSET(x) * BITSET(3) );
  209. x := x << 1;
  210. seg := VideoSel;
  211. [seg:off BP]^ := ( [seg:off BP]^ - BS(3<<x) ) + BS(c<<x);
  212. END CGAPlot;
  213. PROCEDURE CGAPoint(x,y:CARDINAL) : CARDINAL;
  214. VAR
  215. off : CARDINAL;
  216. seg : CARDINAL;
  217. tmp : CARDINAL;
  218. BEGIN
  219. IF (x >= CGAWidth) OR (y >= CGADepth) THEN RETURN MAX(CARDINAL) END;
  220. off := x >> 2;
  221. IF ODD(y) THEN INC( off, 2000H - 40 ) END;
  222. INC( y, y << 2 );
  223. INC( off, y << 3 );
  224. x := 3 - CARDINAL( BITSET(x) * BITSET(3) );
  225. x := x << 1;
  226. seg := VideoSel;
  227. RETURN CARDINAL( [seg:off BP]^ * BS(3<<x) ) >> x;
  228. END CGAPoint;
  229. PROCEDURE CGAHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  230. VAR
  231. off : CARDINAL;
  232. seg : CARDINAL;
  233. tmp : CARDINAL;
  234. n,i : CARDINAL;
  235. w : BS;
  236. mask : BS;
  237. fillc: SHORTCARD;
  238. BEGIN
  239. IF y > CGADepth-1 THEN RETURN END;
  240. IF INTEGER(x) >= INTEGER(CGAWidth) THEN RETURN END;
  241. IF INTEGER(x) < 0 THEN x := 0; END;
  242. IF x2 >= CGAWidth THEN x2 := CGAWidth-1 END;
  243. n := ( x2 - x ) + 1;
  244. off := x >> 2;
  245. IF ODD(y) THEN
  246. INC( off, 2000H - 40 );
  247. c := ( c >> 2 + c << 2 ) MOD 16;
  248. END;
  249. c := c + c * 16;
  250. INC( y, y << 2 );
  251. INC( off, y << 3 );
  252. x := 3 - CARDINAL( BITSET(x) * BITSET(3) );
  253. x := x << 1;
  254. seg := VideoSel;
  255. w := [seg:off BP]^;
  256. REPEAT
  257. mask := BS(3 << x);
  258. w := ( w - mask ) + BS(c)*mask;
  259. DEC(n);
  260. DEC(x,2);
  261. UNTIL (n=0) OR (x=CARDINAL(-2));
  262. [seg:off BP]^ := w;
  263. INC(off);
  264. FOR i := 1 TO (n>>2) DO
  265. [seg:off BP]^ := BS(c);
  266. INC(off);
  267. END;
  268. n := n MOD 4;
  269. x := 6;
  270. w := [seg:off BP]^;
  271. WHILE n <> 0 DO
  272. mask := BS(3 << x);
  273. w := ( w - mask ) + BS(c)*mask;
  274. DEC(n);
  275. DEC(x,2);
  276. END;
  277. [seg:off BP]^ := w;
  278. END CGAHLine;
  279. PROCEDURE Plot( x,y,c : CARDINAL); (* CGA/EGA/VGA *)
  280. BEGIN
  281. IF IsCGA THEN
  282. CGAPlot(x,y,c);
  283. ELSE
  284. EGAPlot(x,y,c);
  285. END;
  286. END Plot;
  287. PROCEDURE HLine ( x,y,x2 : CARDINAL; c:CARDINAL ); (* CGA/EGA/VGA *)
  288. BEGIN
  289. IF IsCGA THEN
  290. CGAHLine(x,y,x2,c);
  291. ELSE
  292. EGAHLine(x,y,x2,c);
  293. END;
  294. END HLine;
  295. PROCEDURE Line(x1,y1,x2,y2: CARDINAL; c: CARDINAL);
  296. VAR
  297. dx,dy,e,tmp : INTEGER;
  298. BEGIN
  299. IF x1 > x2 THEN (* ensure that x2 >= x1 *)
  300. tmp := x1; x1 := x2; x2 := tmp;
  301. tmp := y1; y1 := y2; y2 := tmp;
  302. END;
  303. dx := x2-x1;
  304. e := 0;
  305. IF y1 <= y2 THEN (* case where y increases *)
  306. dy := (y2-y1);
  307. IF dx >= dy THEN
  308. LOOP
  309. Plot( x1,y1,c );
  310. IF x1 = x2 THEN EXIT END;
  311. INC(x1);
  312. INC(e,dy);
  313. INC(e,dy);
  314. IF e > dx THEN
  315. DEC(e,dx);
  316. DEC(e,dx);
  317. INC(y1);
  318. END;
  319. END;
  320. ELSE
  321. LOOP
  322. Plot( x1,y1,c );
  323. IF y1 = y2 THEN EXIT END;
  324. INC(y1);
  325. INC(e,dx);
  326. INC(e,dx);
  327. IF e > dy THEN
  328. DEC(e,dy);
  329. DEC(e,dy);
  330. INC(x1);
  331. END;
  332. END;
  333. END;
  334. ELSE
  335. (* case where y decreases *)
  336. dy := (y1-y2);
  337. IF dx >= dy THEN
  338. LOOP
  339. Plot( x1,y1,c );
  340. IF x1 = x2 THEN EXIT END;
  341. INC(x1);
  342. INC(e,dy);
  343. INC(e,dy);
  344. IF e > dx THEN
  345. DEC(e,dx);
  346. DEC(e,dx);
  347. DEC(y1);
  348. END;
  349. END;
  350. ELSE
  351. LOOP
  352. Plot( x1,y1,c );
  353. IF y1 = y2 THEN EXIT END;
  354. DEC(y1);
  355. INC(e,dx);
  356. INC(e,dx);
  357. IF e > dy THEN
  358. DEC(e,dy);
  359. DEC(e,dy);
  360. INC(x1);
  361. END;
  362. END;
  363. END;
  364. END;
  365. END Line;
  366. CONST
  367. dx = 2;
  368. dy = 2;
  369. PROCEDURE Disc(x0,y0,r: CARDINAL; c: CARDINAL);
  370. VAR
  371. e : INTEGER;
  372. x,y : CARDINAL;
  373. BEGIN
  374. x := r; y := 0; e := 0;
  375. WHILE INTEGER(y) <= INTEGER(x) DO
  376. HLine(x0-x,y0+y,x0+x,c);
  377. HLine(x0-x,y0-y,x0+x,c);
  378. INC(y);
  379. INC(e,y*dy-1);
  380. IF e > INTEGER(x) THEN
  381. DEC(x);
  382. DEC(e,x*dx+1);
  383. HLine(x0-y,y0+x,x0+y,c);
  384. HLine(x0-y,y0-x,x0+y,c);
  385. END;
  386. END;
  387. END Disc;
  388. PROCEDURE Circle(x0,y0,r: CARDINAL; c: CARDINAL);
  389. VAR
  390. e : INTEGER;
  391. x,y : CARDINAL;
  392. BEGIN
  393. x := r; y := 0; e := 0;
  394. WHILE INTEGER(y) <= INTEGER(x) DO
  395. Plot(x0+x,y0+y,c);
  396. Plot(x0-x,y0+y,c);
  397. Plot(x0+x,y0-y,c);
  398. Plot(x0-x,y0-y,c);
  399. Plot(x0+y,y0+x,c);
  400. Plot(x0-y,y0+x,c);
  401. Plot(x0+y,y0-x,c);
  402. Plot(x0-y,y0-x,c);
  403. INC(y);
  404. INC(e,y*dy-1);
  405. IF e > INTEGER(x) THEN
  406. DEC(x);
  407. DEC(e,x*dx+1);
  408. END;
  409. END;
  410. END Circle;
  411. PROCEDURE Ellipse ( x0,y0 : CARDINAL ; (* center *)
  412. a0,b0 : CARDINAL ; (* semi-axes *)
  413. c : CARDINAL ; (* color *)
  414. fill : BOOLEAN ) ; (* wether filled *)
  415. VAR
  416. x,y : CARDINAL ;
  417. a,b : LONGINT ;
  418. asq,asq2,bsq,bsq2 : LONGINT ;
  419. d,dx,dy : LONGINT ;
  420. BEGIN
  421. x := 0 ;
  422. y := b0 ;
  423. a := LONGINT(a0) ;
  424. b := LONGINT(b0) ;
  425. asq := a*a ;
  426. asq2 := asq*2 ;
  427. bsq := b*b ;
  428. bsq2 := bsq*2 ;
  429. d := bsq-(asq*b)+(asq DIV 4) ;
  430. dx := 0 ;
  431. dy := asq2*b ;
  432. WHILE dx<dy DO
  433. IF fill THEN
  434. HLine(x0-x,y0+y,x0+x,c);
  435. HLine(x0-x,y0-y,x0+x,c);
  436. ELSE
  437. Plot(x0+x,y0+y,c) ;
  438. Plot(x0-x,y0+y,c) ;
  439. Plot(x0+x,y0-y,c) ;
  440. Plot(x0-x,y0-y,c) ;
  441. END ;
  442. IF d>0 THEN
  443. DEC(y) ;
  444. DEC(dy,asq2) ;
  445. DEC(d,dy) ;
  446. END ;
  447. INC(x) ;
  448. INC(dx,bsq2) ;
  449. INC(d,bsq+dx) ;
  450. END ;
  451. INC(d,(3*(asq-bsq)DIV 2-(dx+dy))DIV 2) ;
  452. WHILE INTEGER(y)>=0 DO
  453. IF fill THEN
  454. HLine(x0-x,y0+y,x0+x,c);
  455. HLine(x0-x,y0-y,x0+x,c);
  456. ELSE
  457. Plot(x0+x,y0+y,c) ;
  458. Plot(x0-x,y0+y,c) ;
  459. Plot(x0+x,y0-y,c) ;
  460. Plot(x0-x,y0-y,c) ;
  461. END ;
  462. IF d<0 THEN
  463. INC(x) ;
  464. INC(dx,bsq2) ;
  465. INC(d,dx) ;
  466. END ;
  467. DEC(y) ;
  468. DEC(dy,asq2) ;
  469. INC(d,asq-dy) ;
  470. END ;
  471. END Ellipse ;
  472. PROCEDURE Polygon(n: CARDINAL; px,py: ARRAY OF CARDINAL; c: CARDINAL);
  473. CONST
  474. MaxPts = 20;
  475. VAR
  476. y,miny,maxy,x0,y0,x1,y1,temp,i,edge,next_edge,active : INTEGER;
  477. xord : ARRAY [0..MaxPts] OF INTEGER;
  478. x : ARRAY [0..MaxPts] OF CARDINAL;
  479. e : ARRAY [0..MaxPts] OF INTEGER;
  480. (*# save *)
  481. (*# call(reg_saved=>(ax,bx,cx,ds,si,di,st1,st2)) *)
  482. PROCEDURE quicksort(l,r: INTEGER);
  483. VAR
  484. i,j,temp : INTEGER;
  485. key : CARDINAL;
  486. BEGIN
  487. WHILE ( l < r ) DO
  488. i := l; j := r; key := x[xord[j]];
  489. REPEAT
  490. WHILE ( i < j ) AND ( x[xord[i]] <= key ) DO i := i + 1 END;
  491. WHILE ( i < j ) AND ( key <= x[xord[j]] ) DO j := j - 1 END;
  492. IF i < j THEN
  493. temp := xord[i]; xord[i] := xord[j]; xord[j] := temp;
  494. END;
  495. UNTIL ( i >= j );
  496. temp := xord[i]; xord[i] := xord[r]; xord[r] := temp;
  497. IF (i-l < r-i) THEN
  498. quicksort( l, i-1 ); l := i+1;
  499. ELSE
  500. quicksort( i+1, r ); r := i-1;
  501. END;
  502. END;
  503. END quicksort;
  504. (*# restore *)
  505. BEGIN
  506. IF n > MaxPts THEN n := MaxPts END;
  507. (* find extremal y points *)
  508. miny := py[0]; maxy := miny;
  509. FOR i := 0 TO n-1 DO
  510. IF INTEGER(py[i]) < miny THEN miny := py[i]; END;
  511. IF INTEGER(py[i]) > maxy THEN maxy := py[i]; END;
  512. END;
  513. FOR y := miny TO maxy DO
  514. active := -1;
  515. FOR edge := 0 TO n-1 DO
  516. IF edge = INTEGER(n-1) THEN next_edge := 0 ELSE next_edge := edge + 1; END;
  517. x0 := px[edge]; y0 := py[edge];
  518. x1 := px[next_edge]; y1 := py[next_edge];
  519. IF y0 > y1 THEN temp := x0; x0 := x1; x1 := temp;
  520. temp := y0; y0 := y1; y1 := temp END;
  521. IF y = y0 THEN e[edge] := 0; x[edge] := x0
  522. ELSIF ( y0 <= y ) AND ( y <= y1 ) THEN
  523. IF x1 >= x0 THEN (* x increases with y *)
  524. INC( e[edge], 2*(x1-x0) );
  525. WHILE e[edge] > INTEGER(y1-y0) DO
  526. DEC( e[edge], 2*(y1-y0) ); INC(x[edge]);
  527. END;
  528. ELSE (* x decreases with y *)
  529. INC( e[edge], 2*(x0-x1) );
  530. WHILE e[edge] > INTEGER(y1-y0) DO
  531. DEC( e[edge], 2*(y1-y0) ); DEC(x[edge]);
  532. END;
  533. END;
  534. active := active + 1;
  535. xord[active] := edge;
  536. END;
  537. END;
  538. quicksort(0,active);
  539. i := 0;
  540. WHILE i < active DO
  541. HLine( x[xord[i]], y, x[xord[i+1]], c );
  542. i := i + 2;
  543. END;
  544. END; (* for y := .. *)
  545. END Polygon;
  546. BEGIN
  547. Dos.PortAccess(0, 0, 3C4H, 3C5H);
  548. Dos.PortAccess(0, 0, 3CEH, 3CFH);
  549. END GraphI.
  550.