graph16.inc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. {************************************************************************}
  2. {* 4-bit planar VGA mode routines *}
  3. {************************************************************************}
  4. const
  5. VideoOfs = 0;
  6. var
  7. VidMem: PByteArray;
  8. ScrWidth: Integer;
  9. procedure bytemove(var source, dest; count: Integer);
  10. var
  11. s, d: PByte;
  12. begin
  13. s := PByte(@source);
  14. d := PByte(@dest);
  15. while count > 0 do begin
  16. d^ := s^;
  17. Inc(d);
  18. Inc(s);
  19. Dec(count);
  20. end;
  21. end;
  22. procedure PutPixel16(X,Y : Integer; Pixel: Word);
  23. var
  24. offset: word;
  25. dummy: byte;
  26. begin
  27. Inc(x, StartXViewPort);
  28. Inc(y, StartYViewPort);
  29. { convert to absolute coordinates and then verify clipping...}
  30. if ClipPixels then
  31. begin
  32. if (X < StartXViewPort) or (X > (StartXViewPort + ViewWidth)) then
  33. exit;
  34. if (Y < StartYViewPort) or (Y > (StartYViewPort + ViewHeight)) then
  35. exit;
  36. end;
  37. offset := y * 80 + (x shr 3) + VideoOfs;
  38. WritePortW($3ce, $0f01); { Index 01 : Enable ops on all 4 planes }
  39. WritePortW($3ce, (Pixel and $ff) shl 8); { Index 00 : Enable correct plane and write color }
  40. WritePortW($3ce, 8 or ($8000 shr (x and $7)));{ Select correct bits to modify }
  41. dummy := VidMem^[offset]; { Read data byte into VGA latch register }
  42. VidMem^[offset] := dummy; { Write the data into video memory }
  43. end;
  44. function GetPixel16(X,Y: Integer):word;
  45. var
  46. dummy, offset: Word;
  47. shift: byte;
  48. begin
  49. Inc(x, StartXViewPort);
  50. Inc(y, StartYViewPort);
  51. offset := Y * 80 + (x shr 3) + VideoOfs;
  52. WritePortW($3ce, 4);
  53. shift := 7 - (X and 7);
  54. dummy := (VidMem^[offset] shr shift) and 1;
  55. WritePortB($3cf, 1);
  56. dummy := dummy or (((VidMem^[offset] shr shift) and 1) shl 1);
  57. WritePortB($3cf, 2);
  58. dummy := dummy or (((VidMem^[offset] shr shift) and 1) shl 2);
  59. WritePortB($3cf, 3);
  60. dummy := dummy or (((VidMem^[offset] shr shift) and 1) shl 3);
  61. GetPixel16 := dummy;
  62. end;
  63. procedure GetScanLine16(x1, x2, y: integer; var data);
  64. var
  65. dummylong: longint;
  66. Offset, count, count2, amount, index: word;
  67. plane: byte;
  68. begin
  69. inc(x1,StartXViewPort);
  70. inc(x2,StartXViewPort);
  71. {$ifdef logging}
  72. LogLn('GetScanLine16 start, length to get: '+strf(x2-x1+1)+' at y = '+strf(y));
  73. {$Endif logging}
  74. offset := (Y + StartYViewPort) * 80 + (x1 shr 3) + VideoOfs;
  75. {$ifdef logging}
  76. LogLn('Offset: '+HexStr(offset,4)+' - ' + strf(offset));
  77. {$Endif logging}
  78. { first get enough pixels so offset is 32bit aligned }
  79. amount := 0;
  80. index := 0;
  81. If ((x1 and 31) <> 0) Or
  82. ((x2-x1+1) < 32) Then
  83. Begin
  84. If ((x2-x1+1) >= 32+32-(x1 and 31)) Then
  85. amount := 32-(x1 and 31)
  86. Else amount := x2-x1+1;
  87. {$ifdef logging}
  88. LogLn('amount to align to 32bits or to get all: ' + strf(amount));
  89. {$Endif logging}
  90. For count := 0 to amount-1 do
  91. WordArray(Data)[Count] := getpixel16(x1-StartXViewPort+Count,y);
  92. index := amount;
  93. Inc(Offset,(amount+7) shr 3);
  94. {$ifdef logging}
  95. LogLn('offset now: '+HexStr(offset,4)+' - ' + strf(offset));
  96. LogLn('index now: '+strf(index));
  97. {$Endif logging}
  98. End;
  99. amount := x2-x1+1 - amount;
  100. {$ifdef logging}
  101. LogLn('amount left: ' + strf(amount));
  102. {$Endif logging}
  103. If amount = 0 Then Exit;
  104. WritePortB($3ce, 4);
  105. { first get everything from plane 3 (4th plane) }
  106. WritePortB($3cf, 3);
  107. Count := 0;
  108. For Count := 1 to (amount shr 5) Do
  109. Begin
  110. dummylong := PLongInt(@VidMem^[offset+(Count-1)*4])^;
  111. dummylong :=
  112. ((dummylong and $ff) shl 24) or
  113. ((dummylong and $ff00) shl 8) or
  114. ((dummylong and $ff0000) shr 8) or
  115. ((dummylong and $ff000000) shr 24);
  116. For Count2 := 31 downto 0 Do
  117. Begin
  118. WordArray(Data)[index+Count2] := DummyLong and 1;
  119. DummyLong := DummyLong shr 1;
  120. End;
  121. Inc(Index, 32);
  122. End;
  123. { Now get the data from the 3 other planes }
  124. plane := 3;
  125. Repeat
  126. Dec(Index,Count*32);
  127. Dec(plane);
  128. WritePortB($3cf, plane);
  129. Count := 0;
  130. For Count := 1 to (amount shr 5) Do
  131. Begin
  132. dummylong := PLongInt(@VidMem^[offset+(Count-1)*4])^;
  133. dummylong :=
  134. ((dummylong and $ff) shl 24) or
  135. ((dummylong and $ff00) shl 8) or
  136. ((dummylong and $ff0000) shr 8) or
  137. ((dummylong and $ff000000) shr 24);
  138. For Count2 := 31 downto 0 Do
  139. Begin
  140. WordArray(Data)[index+Count2] :=
  141. (WordArray(Data)[index+Count2] shl 1) or (DummyLong and 1);
  142. DummyLong := DummyLong shr 1;
  143. End;
  144. Inc(Index, 32);
  145. End;
  146. Until plane = 0;
  147. amount := amount and 31;
  148. Dec(index);
  149. {$ifdef Logging}
  150. LogLn('Last array index written to: '+strf(index));
  151. LogLn('amount left: '+strf(amount)+' starting at x = '+strf(index+1));
  152. {$Endif logging}
  153. For Count := 1 to amount Do
  154. WordArray(Data)[index+Count] := getpixel16(index+Count,y);
  155. {$ifdef logging}
  156. LogLn('First 32 bytes gotten with getscanline16: ');
  157. If x2-x1+1 >= 32 Then
  158. Count2 := 32
  159. Else Count2 := x2-x1+1;
  160. For Count := 0 to Count2-1 Do
  161. Log(strf(WordArray(Data)[Count])+' ');
  162. LogLn('');
  163. If x2-x1+1 >= 32 Then
  164. Begin
  165. LogLn('Last 32 bytes gotten with getscanline16: ');
  166. For Count := 31 downto 0 Do
  167. Log(strf(WordArray(Data)[x2-x1-Count])+' ');
  168. End;
  169. LogLn('');
  170. GetScanLineDefault(x1-StartXViewPort,x2-StartXViewPort,y,Data);
  171. LogLn('First 32 bytes gotten with getscanlinedef: ');
  172. If x2-x1+1 >= 32 Then
  173. Count2 := 32
  174. Else Count2 := x2-x1+1;
  175. For Count := 0 to Count2-1 Do
  176. Log(strf(WordArray(Data)[Count])+' ');
  177. LogLn('');
  178. If x2-x1+1 >= 32 Then
  179. Begin
  180. LogLn('Last 32 bytes gotten with getscanlinedef: ');
  181. For Count := 31 downto 0 Do
  182. Log(strf(WordArray(Data)[x2-x1-Count])+' ');
  183. End;
  184. LogLn('');
  185. LogLn('GetScanLine16 end');
  186. {$Endif logging}
  187. end;
  188. procedure DirectPutPixel16(X,Y : Integer);
  189. { x,y -> must be in global coordinates. No clipping. }
  190. var
  191. color: word;
  192. offset: word;
  193. dummy: byte;
  194. begin
  195. case CurrentWriteMode of
  196. XORPut:
  197. begin
  198. { getpixel wants local/relative coordinates }
  199. Color := GetPixel(x - StartXViewPort, y - StartYViewPort);
  200. Color := CurrentColor xor Color;
  201. end;
  202. OrPut:
  203. begin
  204. { getpixel wants local/relative coordinates }
  205. Color := GetPixel(x - StartXViewPort, y - StartYViewPort);
  206. Color := CurrentColor or Color;
  207. end;
  208. AndPut:
  209. begin
  210. { getpixel wants local/relative coordinates }
  211. Color := GetPixel(x - StartXViewPort, y - StartYViewPort);
  212. Color := CurrentColor and Color;
  213. end;
  214. NotPut:
  215. Color := Not Color;
  216. else
  217. Color := CurrentColor;
  218. end;
  219. offset := Y * 80 + (X shr 3) + VideoOfs;
  220. WritePortW($3ce, $f01);
  221. WritePortW($3ce, Color shl 8);
  222. WritePortW($3ce, 8 or $8000 shr (X and 7));
  223. dummy := VidMem^[offset];
  224. VidMem^[offset] := dummy;
  225. end;
  226. procedure HLine16(x, x2, y: Integer);
  227. var
  228. xtmp: Integer;
  229. ScrOfs, HLength: Word;
  230. LMask, RMask: Byte;
  231. begin
  232. { must we swap the values? }
  233. if x > x2 then
  234. begin
  235. xtmp := x2;
  236. x2 := x;
  237. x:= xtmp;
  238. end;
  239. { First convert to global coordinates }
  240. Inc(x, StartXViewPort);
  241. Inc(x2, StartXViewPort);
  242. Inc(y, StartYViewPort);
  243. if ClipPixels and LineClipped(x,y,x2,y,StartXViewPort,StartYViewPort,
  244. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  245. exit;
  246. ScrOfs := y * ScrWidth + x div 8;
  247. HLength := x2 div 8 - x div 8;
  248. LMask := $ff shr (x and 7);
  249. {$ifopt r+}
  250. {$define rangeOn}
  251. {$r-}
  252. {$endif}
  253. {$ifopt q+}
  254. {$define overflowOn}
  255. {$q-}
  256. {$endif}
  257. RMask:=$ff shl (7 - (x2 and 7));
  258. {$ifdef rangeOn}
  259. {$undef rangeOn}
  260. {$r+}
  261. {$endif}
  262. {$ifdef overflowOn}
  263. {$undef overflowOn}
  264. {$q+}
  265. {$endif}
  266. if HLength=0 then
  267. LMask:=LMask and RMask;
  268. WritePortB($3ce, 0);
  269. if CurrentWriteMode <> NotPut Then
  270. WritePortB($3cf, CurrentColor)
  271. else
  272. WritePortB($3cf, not CurrentColor);
  273. WritePortW($3ce, $0f01);
  274. WritePortB($3ce, 3);
  275. case CurrentWriteMode of
  276. XORPut:
  277. WritePortB($3cf, 3 shl 3);
  278. ANDPut:
  279. WritePortB($3cf, 1 shl 3);
  280. ORPut:
  281. WritePortB($3cf, 2 shl 3);
  282. NormalPut, NotPut:
  283. WritePortB($3cf, 0)
  284. else
  285. WritePortB($3cf, 0)
  286. end;
  287. WritePortB($3ce, 8);
  288. WritePortB($3cf, LMask);
  289. {$ifopt r+}
  290. {$define rangeOn}
  291. {$r-}
  292. {$endif}
  293. {$ifopt q+}
  294. {$define overflowOn}
  295. {$q-}
  296. {$endif}
  297. VidMem^[ScrOfs] := VidMem^[ScrOfs] + 1;
  298. {$ifdef rangeOn}
  299. {$undef rangeOn}
  300. {$r+}
  301. {$endif}
  302. {$ifdef overflowOn}
  303. {$undef overflowOn}
  304. {$q+}
  305. {$endif}
  306. if HLength>0 then
  307. begin
  308. Dec(HLength);
  309. Inc(ScrOfs);
  310. if HLength>0 then
  311. begin
  312. WritePortW($3ce, $ff08);
  313. bytemove(VidMem^[ScrOfs], VidMem^[ScrOfs], HLength);
  314. Inc(ScrOfs, HLength);
  315. end else
  316. WritePortB($3ce, 8);
  317. WritePortB($3cf, RMask);
  318. {$ifopt r+}
  319. {$define rangeOn}
  320. {$r-}
  321. {$endif}
  322. {$ifopt q+}
  323. {$define overflowOn}
  324. {$q-}
  325. {$endif}
  326. VidMem^[ScrOfs] := VidMem^[ScrOfs] + 1;
  327. {$ifdef rangeOn}
  328. {$undef rangeOn}
  329. {$r+}
  330. {$endif}
  331. {$ifdef overflowOn}
  332. {$undef overflowOn}
  333. {$q+}
  334. {$endif}
  335. end;
  336. end;
  337. procedure VLine16(x,y,y2: integer);
  338. var
  339. ytmp: integer;
  340. ScrOfs,i: longint;
  341. BitMask: byte;
  342. begin
  343. { must we swap the values? }
  344. if y > y2 then
  345. begin
  346. ytmp := y2;
  347. y2 := y;
  348. y:= ytmp;
  349. end;
  350. { First convert to global coordinates }
  351. Inc(x, StartXViewPort);
  352. Inc(y, StartYViewPort);
  353. Inc(y2, StartYViewPort);
  354. if ClipPixels and LineClipped(x,y,x,y2,StartXViewPort,StartYViewPort,
  355. StartXViewPort+ViewWidth, StartYViewPort+ViewHeight) then
  356. exit;
  357. ScrOfs:=y*ScrWidth+x div 8;
  358. BitMask:=$80 shr (x and 7);
  359. WritePortB($3ce, 0);
  360. if CurrentWriteMode <> NotPut then
  361. WritePortB($3cf, CurrentColor)
  362. else
  363. WritePortB($3cf, not CurrentColor);
  364. WritePortW($3ce, $0f01);
  365. WritePortB($3ce, 8);
  366. WritePortB($3cf, BitMask);
  367. WritePortB($3ce, 3);
  368. case CurrentWriteMode of
  369. XORPut:
  370. WritePortB($3cf, 3 shl 3);
  371. ANDPut:
  372. WritePortB($3cf, 1 shl 3);
  373. ORPut:
  374. WritePortB($3cf, 2 shl 3);
  375. NormalPut, NotPut:
  376. WritePortB($3cf, 0)
  377. else
  378. WritePortB($3cf, 0)
  379. end;
  380. for i:=y to y2 do
  381. begin
  382. {$ifopt r+}
  383. {$define rangeOn}
  384. {$r-}
  385. {$endif}
  386. {$ifopt q+}
  387. {$define overflowOn}
  388. {$q-}
  389. {$endif}
  390. VidMem^[ScrOfs]:=VidMem^[ScrOfs]+1;
  391. {$ifdef rangeOn}
  392. {$undef rangeOn}
  393. {$r+}
  394. {$endif}
  395. {$ifdef overflowOn}
  396. {$undef overflowOn}
  397. {$q+}
  398. {$endif}
  399. Inc(ScrOfs, ScrWidth);
  400. end;
  401. end;
  402. {
  403. $Log$
  404. Revision 1.2 2002-09-07 16:01:27 peter
  405. * old logs removed and tabs fixed
  406. }