Implemented basic VGA routines
[reactos.git] / reactos / drivers / dd / vga / display / vgavideo / vgavideo.c
1 #include <ddk/ntddk.h>
2 #include <ddk/ntddvid.h>
3
4 #include "vgavideo.h"
5
6 #include <internal/i386/io.h>
7
8 div_t div(int num, int denom)
9 {
10 div_t r;
11 if (num > 0 && denom < 0) {
12 num = -num;
13 denom = -denom;
14 }
15 r.quot = num / denom;
16 r.rem = num % denom;
17 if (num < 0 && denom > 0)
18 {
19 if (r.rem > 0)
20 {
21 r.quot++;
22 r.rem -= denom;
23 }
24 }
25 return r;
26 }
27
28 int mod(int num, int denom)
29 {
30 div_t dvt = div(num, denom);
31 return dvt.rem;
32 }
33
34 VOID vgaPreCalc()
35 {
36 ULONG j;
37
38 startmasks[1] = 127;
39 startmasks[2] = 63;
40 startmasks[3] = 31;
41 startmasks[4] = 15;
42 startmasks[5] = 7;
43 startmasks[6] = 3;
44 startmasks[7] = 1;
45 startmasks[8] = 255;
46
47 endmasks[0] = 128;
48 endmasks[1] = 192;
49 endmasks[2] = 224;
50 endmasks[3] = 240;
51 endmasks[4] = 248;
52 endmasks[5] = 252;
53 endmasks[6] = 254;
54 endmasks[7] = 255;
55 endmasks[8] = 255;
56
57 for(j=0; j<80; j++)
58 {
59 maskbit[j*8] = 128;
60 maskbit[j*8+1] = 64;
61 maskbit[j*8+2] = 32;
62 maskbit[j*8+3] = 16;
63 maskbit[j*8+4] = 8;
64 maskbit[j*8+5] = 4;
65 maskbit[j*8+6] = 2;
66 maskbit[j*8+7] = 1;
67
68 bit8[j*8] = 7;
69 bit8[j*8+1] = 6;
70 bit8[j*8+2] = 5;
71 bit8[j*8+3] = 4;
72 bit8[j*8+4] = 3;
73 bit8[j*8+5] = 2;
74 bit8[j*8+6] = 1;
75 bit8[j*8+7] = 0;
76 }
77 for(j=0; j<480; j++)
78 {
79 y80[j] = j*80;
80 }
81 for(j=0; j<640; j++)
82 {
83 xconv[j] = j >> 3;
84 }
85 }
86
87 void vgaPutPixel(int x, int y, unsigned char c)
88 {
89 unsigned offset;
90 unsigned char a;
91
92 offset = xconv[x]+y80[y];
93
94 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
95 WRITE_PORT_UCHAR((PUCHAR)0x3cf,maskbit[x]);
96
97 a = READ_REGISTER_UCHAR(vidmem + offset);
98 WRITE_REGISTER_UCHAR(vidmem + offset, c);
99 }
100
101 void vgaPutByte(int x, int y, unsigned char c)
102 {
103 unsigned offset;
104
105 offset = xconv[x]+y80[y];
106
107 // Set the write mode
108 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
109 WRITE_PORT_UCHAR((PUCHAR)0x3cf,0xff);
110
111 WRITE_REGISTER_UCHAR(vidmem + offset, c);
112 }
113
114 void vgaGetByte(unsigned offset,
115 unsigned char *b, unsigned char *g,
116 unsigned char *r, unsigned char *i)
117 {
118 // fixme: use READ_REGISTER_UCHAR
119
120 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0304);
121 *i = vidmem[offset];
122 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0204);
123 *r = vidmem[offset];
124 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0104);
125 *g = vidmem[offset];
126 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0004);
127 *b = vidmem[offset];
128 }
129
130 int vgaGetPixel(int x, int y)
131 {
132 unsigned char mask, b, g, r, i;
133 unsigned offset;
134
135 offset = xconv[x]+y80[y];
136 mask=maskbit[x];
137 vgaGetByte(offset, &b, &g, &r, &i);
138 b=b&mask;
139 g=g&mask;
140 r=r&mask;
141 i=i&mask;
142
143 mask=bit8[x];
144 g=g>>mask;
145 b=b>>mask;
146 r=r>>mask;
147 i=i>>mask;
148
149 return(b+2*g+4*r+8*i);
150 }
151
152 BOOL vgaHLine(int x, int y, int len, unsigned char c)
153 {
154 unsigned char a;
155 unsigned int pre1, i;
156 unsigned int orgpre1, orgx, midpre1;
157 unsigned long leftpixs, midpixs, rightpixs, temp;
158
159 orgx=x;
160
161 if(len<8)
162 {
163 for (i=x; i<x+len; i++)
164 vgaPutPixel(i, y, c);
165 } else {
166
167 leftpixs=x;
168 while(leftpixs>8) leftpixs-=8;
169 temp = len;
170 midpixs = 0;
171
172 while(temp>7)
173 {
174 temp-=8;
175 midpixs++;
176 }
177 if((temp>=0) && (midpixs>0)) midpixs--;
178
179 pre1=xconv[x]+y80[y];
180 orgpre1=pre1;
181
182 // Left
183 if(leftpixs==8) {
184 // Left edge should be an entire middle bar
185 x=orgx;
186 leftpixs=0;
187 }
188 else if(leftpixs>0)
189 {
190 // Write left pixels
191 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask
192 WRITE_PORT_UCHAR((PUCHAR)0x3cf,startmasks[leftpixs]);
193
194 a = READ_REGISTER_UCHAR(vidmem + pre1);
195 WRITE_REGISTER_UCHAR(vidmem + pre1, c);
196
197 // Middle
198 x=orgx+(8-leftpixs)+leftpixs;
199
200 } else {
201 // leftpixs == 0
202 midpixs+=1;
203 }
204
205 if(midpixs>0)
206 {
207 midpre1=xconv[x]+y80[y];
208
209 // Set mask to all pixels in byte
210 WRITE_PORT_UCHAR((PUCHAR)0x3ce, 0x08);
211 WRITE_PORT_UCHAR((PUCHAR)0x3cf, 0xff);
212 memset(vidmem+midpre1, c, midpixs); // write middle pixels, no need to read in latch because of the width
213 }
214
215 rightpixs = len - ((midpixs*8) + leftpixs);
216
217 if((rightpixs>0))
218 {
219 x=(orgx+len)-rightpixs;
220
221 // Go backwards till we reach the 8-byte boundary
222 while(mod(x, 8)!=0) { x--; rightpixs++; }
223
224 while(rightpixs>7)
225 {
226 // This is a BAD case as this should have been a midpixs
227
228 vgaPutByte(x, y, c);
229 rightpixs-=8;
230 x+=8;
231 }
232
233 pre1=xconv[x]+y80[y];
234
235 // Write right pixels
236 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask bits
237 WRITE_PORT_UCHAR((PUCHAR)0x3cf,endmasks[rightpixs]);
238
239 a = READ_REGISTER_UCHAR(vidmem + pre1);
240 WRITE_REGISTER_UCHAR(vidmem + pre1, c);
241 }
242 }
243
244 return TRUE;
245 }
246
247 BOOL vgaVLine(int x, int y, int len, unsigned char c)
248 {
249 unsigned offset, i;
250 unsigned char a;
251
252 offset = xconv[x]+y80[y];
253
254 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask
255 WRITE_PORT_UCHAR((PUCHAR)0x3cf,maskbit[x]);
256
257 len++;
258
259 for(i=y; i<y+len; i++)
260 {
261 a = READ_REGISTER_UCHAR(vidmem + offset);
262 WRITE_REGISTER_UCHAR(vidmem + offset, c);
263 offset+=80;
264 }
265
266 return TRUE;
267 }