minor corrections by M.Taguchi
[reactos.git] / freeldr / freeldr / video / pixel.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <freeldr.h>
21 #include <video.h>
22 #include <portio.h>
23 #include <debug.h>
24
25
26
27
28
29 //
30 // Arrrggh!
31 // I really really hate 16 color bit plane modes.
32 // They should all burn in hell for what they've
33 // done to my sleeping habits. And I still can't
34 // get this code to work and I have absolutely
35 // no idea why...
36 //
37 // Someone else can take up this portion of the
38 // boot loader because my give up...
39 //
40 // I was going to store the offscreen buffer as
41 // a big array of bytes (as opposed to four bits)
42 // and that makes it a bit easier to set a pixel
43 // on the offscreen buffer, but will have to be
44 // handled in the VideoCopyOffScreenBufferToVRAM()
45 // function.
46 //
47 VOID VideoSetPixel16(U32 X, U32 Y, U8 Color)
48 {
49 //U8 CurrentColor;
50 U8* MemoryPointer;
51 U32 ByteOffset;
52 U8 BitInByte;
53 U8 ReadByte;
54 U8 BitToChange;
55
56 MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
57
58 // Calculate the byte offset into the bit-plane
59 // where the pixel is to be set and the bit
60 // offset in that byte.
61 //ByteOffset = (Y * VideoGetBytesPerScanLine()) + (X >> 3);
62 //ByteOffset = (Y * 80) + (X >> 3);
63 ByteOffset = (Y * 640) + X;
64 BitInByte = ByteOffset & 7;
65 ByteOffset = ByteOffset >> 3;
66 //BitToChange = 0x80 >> BitInByte;
67 BitToChange = 0x80;
68
69 DbgPrint((DPRINT_WARNING, "X = %d Y = %d Color = %d ByteOffset = %d BitInByte = %d BitToChange = %d\n", X, Y, Color, ByteOffset, BitInByte, BitToChange));
70 //getch();
71
72 // Read the byte of memory to be changed. This is a
73 // read for the video card latches and the data read
74 // from memory does not need to be used.
75 ReadByte = MemoryPointer[ByteOffset];
76
77 // Select the bit or bits in the byte that need to be
78 // changed through index 8 of the VGA card address
79 // register by sending an 8 out to I/O port 3CEh.
80 // Next get the bits to be changed (a one-bit represents
81 // a bit to be changed) and send this out to I/O
82 // port 3CFh, the bit mask register (BMR).
83 //WRITE_PORT_USHORT((U16*)0x3CE, (((U16)BitToChange) << 8) + 0x08);
84 WRITE_PORT_UCHAR((U8*)0x3CE, 0x08);
85 //WRITE_PORT_UCHAR((U8*)0x3CF, BitToChange);
86 WRITE_PORT_UCHAR((U8*)0x3CF, BitInByte);
87
88 // Next set all mask bits to 1111 in the map mask register
89 // (MMR) at sequencer offset 2, and write color 0 to the
90 // VGA card to set the color to black. The mask bits select
91 // the bit planes to be changed. If all are selected and a
92 // color of 0 is written, all four bit-planes are clear to zero.
93 WRITE_PORT_USHORT((U16*)0x3C4, 0x0F02);
94 //WRITE_PORT_UCHAR((U8*)0x3C4, 0x02);
95 //WRITE_PORT_UCHAR((U8*)0x3C5, 0x0F); // Mask to 1111 binary
96 MemoryPointer[ByteOffset] = 0x00;
97
98 // Send the desired color number to the map mask register and
99 // write an FFh to the video memory. This places a logic one
100 // in only the selected bit planes to write a new color to
101 // a pixel or dot on the screen.
102 WRITE_PORT_UCHAR((U8*)0x3C4, 0x02);
103 //WRITE_PORT_UCHAR((U8*)0x3C5, Color);
104 WRITE_PORT_UCHAR((U8*)0x3C5, 0x0F);
105 //WRITE_PORT_USHORT((U16*)0x3C4, 0x0A02);
106 MemoryPointer[ByteOffset] = 0xFF;
107
108
109 /*CurrentColor = Color;
110
111 MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
112
113 WRITE_PORT_USHORT((U16*)0x3CE, 0x00 | (CurrentColor << 8));
114 WRITE_PORT_USHORT((U16*)0x3CE, 0x08 | 0x8000 >> (X & 7));
115
116 MemoryPointer += (Y * VideoGetBytesPerScanLine()) + (X >> 3);
117
118 *MemoryPointer = *MemoryPointer;
119 getch();*/
120
121
122 // First select the color plane
123 //ColorPlane = Color;
124 //ColorPlane = (ColorPlane << 8) + 0x02;
125 //WRITE_PORT_USHORT((U16*)0x3C4, ColorPlane);
126
127 // Now calculate the byte offset in the
128 // color plane that contains our pixel
129 // Since there are 8 pixels per byte we
130 // have to adjust accordingly
131 /*ByteOffset = (Y * VideoGetCurrentModeResolutionX()) + X;
132 BitInByte = ByteOffset % 8;
133 ByteOffset = ByteOffset / 8;
134
135 // Shift the color to the right bit
136 Color = 1;
137 Color = Color << BitInByte;
138
139 // Get the current color
140 CurrentColor = MemoryPointer[ByteOffset];
141
142 // Add the new color
143 CurrentColor = CurrentColor | Color;
144
145 // Now set the color
146 MemoryPointer[ByteOffset] = CurrentColor;*/
147 }
148
149 VOID VideoSetPixel256(U32 X, U32 Y, U8 Color)
150 {
151 U32 Bank;
152 U32 Offset;
153 U8* MemoryPointer;
154
155 MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
156
157 Bank = VideoGetMemoryBankForPixel(X, Y);
158 Offset = VideoGetBankOffsetForPixel(X, Y);
159
160 VideoSetMemoryBank(Bank);
161
162 MemoryPointer[Offset] = Color;
163 }
164
165 VOID VideoSetPixelRGB_15Bit(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
166 {
167 U32 Bank;
168 U32 Offset;
169 U8* MemoryPointer;
170 U16 Pixel;
171
172 MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
173
174 Bank = VideoGetMemoryBankForPixel(X, Y);
175 Offset = VideoGetBankOffsetForPixel(X, Y);
176
177 VideoSetMemoryBank(Bank);
178
179 Red = Red >> 3;
180 Green = Green >> 3;
181 Blue = Blue >> 3;
182
183 Pixel = Red << 11 | Green << 6 | Blue << 1;
184
185 MemoryPointer[Offset] = Pixel & 0xFF;
186 MemoryPointer[Offset+1] = Pixel >> 8;
187 }
188
189 VOID VideoSetPixelRGB_16Bit(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
190 {
191 U32 Bank;
192 U32 Offset;
193 U8* MemoryPointer;
194 U16 Pixel;
195
196 MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
197
198 Bank = VideoGetMemoryBankForPixel(X, Y);
199 Offset = VideoGetBankOffsetForPixel(X, Y);
200
201 VideoSetMemoryBank(Bank);
202
203 Red = Red >> 3;
204 Green = Green >> 2;
205 Blue = Blue >> 3;
206
207 Pixel = (U16)Red << 11 | (U16)Green << 5 | (U16)Blue << 0;
208
209 MemoryPointer[Offset] = Pixel & 0xFF;
210 MemoryPointer[Offset+1] = Pixel >> 8;
211 }
212
213 VOID VideoSetPixelRGB_24Bit(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
214 {
215 U32 Bank;
216 U32 Offset;
217 U8* MemoryPointer;
218
219 MemoryPointer = (U8*)(VIDEOVGA_MEM_ADDRESS);
220
221 Bank = VideoGetMemoryBankForPixel(X, Y);
222 Offset = VideoGetBankOffsetForPixel(X, Y);
223
224 VideoSetMemoryBank(Bank);
225
226 MemoryPointer[Offset] = Blue;
227 MemoryPointer[Offset+1] = Green;
228 MemoryPointer[Offset+2] = Red;
229 }
230
231 VOID VideoSetPixelRGB(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
232 {
233 if (VesaVideoModeInformation.BitsPerPixel >= 24)
234 {
235 VideoSetPixelRGB_24Bit(X, Y, Red, Green, Blue);
236 }
237 else if (VesaVideoModeInformation.BitsPerPixel >= 16)
238 {
239 // 16-bit color modes give green an extra bit (5:6:5)
240 // 15-bit color modes have just 5:5:5 for R:G:B
241 if (VesaVideoModeInformation.GreenMaskSize == 6)
242 {
243 VideoSetPixelRGB_16Bit(X, Y, Red, Green, Blue);
244 }
245 else
246 {
247 VideoSetPixelRGB_15Bit(X, Y, Red, Green, Blue);
248 }
249 }
250 else
251 {
252 BugCheck((DPRINT_UI, "This function does not support %d bits per pixel!", VesaVideoModeInformation.BitsPerPixel));
253 }
254 }
255
256 VOID VideoSetPixel16_OffScreen(U32 X, U32 Y, U8 Color)
257 {
258 }
259
260 VOID VideoSetPixel256_OffScreen(U32 X, U32 Y, U8 Color)
261 {
262 U8* MemoryPointer;
263
264 MemoryPointer = (U8*)(VideoOffScreenBuffer + VideoGetOffScreenMemoryOffsetForPixel(X, Y));
265
266 *MemoryPointer = Color;
267 }
268
269 VOID VideoSetPixelRGB_15Bit_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
270 {
271 U32 Offset;
272 U8* MemoryPointer;
273 U16 Pixel;
274
275 MemoryPointer = (U8*)(VideoOffScreenBuffer);
276 Offset = VideoGetOffScreenMemoryOffsetForPixel(X, Y);
277
278 Red = Red >> 3;
279 Green = Green >> 3;
280 Blue = Blue >> 3;
281
282 Pixel = Red << 11 | Green << 6 | Blue << 1;
283
284 MemoryPointer[Offset] = Pixel & 0xFF;
285 MemoryPointer[Offset+1] = Pixel >> 8;
286 }
287
288 VOID VideoSetPixelRGB_16Bit_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
289 {
290 U32 Offset;
291 U8* MemoryPointer;
292 U16 Pixel;
293
294 MemoryPointer = (U8*)(VideoOffScreenBuffer);
295 Offset = VideoGetOffScreenMemoryOffsetForPixel(X, Y);
296
297 Red = Red >> 3;
298 Green = Green >> 2;
299 Blue = Blue >> 3;
300
301 Pixel = (U16)Red << 11 | (U16)Green << 5 | (U16)Blue << 0;
302
303 MemoryPointer[Offset] = Pixel & 0xFF;
304 MemoryPointer[Offset+1] = Pixel >> 8;
305 }
306
307 VOID VideoSetPixelRGB_24Bit_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
308 {
309 U32 Offset;
310 U8* MemoryPointer;
311
312 MemoryPointer = (U8*)(VideoOffScreenBuffer);
313 Offset = VideoGetOffScreenMemoryOffsetForPixel(X, Y);
314
315 MemoryPointer[Offset] = Blue;
316 MemoryPointer[Offset+1] = Green;
317 MemoryPointer[Offset+2] = Red;
318 }
319
320 VOID VideoSetPixelRGB_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue)
321 {
322 if (VesaVideoModeInformation.BitsPerPixel >= 24)
323 {
324 VideoSetPixelRGB_24Bit_OffScreen(X, Y, Red, Green, Blue);
325 }
326 else if (VesaVideoModeInformation.BitsPerPixel >= 16)
327 {
328 // 16-bit color modes give green an extra bit (5:6:5)
329 // 15-bit color modes have just 5:5:5 for R:G:B
330 if (VesaVideoModeInformation.GreenMaskSize == 6)
331 {
332 VideoSetPixelRGB_16Bit_OffScreen(X, Y, Red, Green, Blue);
333 }
334 else
335 {
336 VideoSetPixelRGB_15Bit_OffScreen(X, Y, Red, Green, Blue);
337 }
338 }
339 else
340 {
341 BugCheck((DPRINT_UI, "This function does not support %d bits per pixel!", VesaVideoModeInformation.BitsPerPixel));
342 }
343 }