xref: /haiku/src/add-ons/accelerants/s3/trio64_mode.cpp (revision 35db13ea5a14c9f6fee81f3de4d54a2fe42502b8)
1*35db13eaSAxel Dörfler /*
2*35db13eaSAxel Dörfler 	Haiku S3 Trio64 driver adapted from the X.org S3 driver.
3*35db13eaSAxel Dörfler 
4*35db13eaSAxel Dörfler 	Copyright 2001	Ani Joshi <ajoshi@unixbox.com>
5*35db13eaSAxel Dörfler 
6*35db13eaSAxel Dörfler 	Copyright 2008 Haiku, Inc.  All rights reserved.
7*35db13eaSAxel Dörfler 	Distributed under the terms of the MIT license.
8*35db13eaSAxel Dörfler 
9*35db13eaSAxel Dörfler 	Authors:
10*35db13eaSAxel Dörfler 	Gerald Zajac 2008
11*35db13eaSAxel Dörfler */
12*35db13eaSAxel Dörfler 
13*35db13eaSAxel Dörfler 
14*35db13eaSAxel Dörfler #include "accel.h"
15*35db13eaSAxel Dörfler #include "trio64.h"
16*35db13eaSAxel Dörfler 
17*35db13eaSAxel Dörfler 
18*35db13eaSAxel Dörfler #define BASE_FREQ		14.31818	// MHz
19*35db13eaSAxel Dörfler 
20*35db13eaSAxel Dörfler 
21*35db13eaSAxel Dörfler static void
22*35db13eaSAxel Dörfler Trio64_CalcClock(long freq, int min_m, int min_n1, int max_n1,
23*35db13eaSAxel Dörfler 				int min_n2, int max_n2, long freq_min, long freq_max,
24*35db13eaSAxel Dörfler 				uint8* mdiv, uint8* ndiv)
25*35db13eaSAxel Dörfler {
26*35db13eaSAxel Dörfler 	uint8 best_n1 = 18, best_n2 = 2, best_m = 127;
27*35db13eaSAxel Dörfler 
28*35db13eaSAxel Dörfler 	double ffreq = freq / 1000.0 / BASE_FREQ;
29*35db13eaSAxel Dörfler 	double ffreq_min = freq_min / 1000.0 / BASE_FREQ;
30*35db13eaSAxel Dörfler 	double ffreq_max = freq_max / 1000.0 / BASE_FREQ;
31*35db13eaSAxel Dörfler 
32*35db13eaSAxel Dörfler 	if (ffreq < ffreq_min / (1 << max_n2)) {
33*35db13eaSAxel Dörfler 		TRACE("Trio64_CalcClock() invalid frequency %1.3f Mhz [freq >= %1.3f Mhz]\n",
34*35db13eaSAxel Dörfler 			   ffreq*BASE_FREQ, ffreq_min*BASE_FREQ / (1 << max_n2));
35*35db13eaSAxel Dörfler 		ffreq = ffreq_min / (1 << max_n2);
36*35db13eaSAxel Dörfler 	}
37*35db13eaSAxel Dörfler 	if (ffreq > ffreq_max / (1 << min_n2)) {
38*35db13eaSAxel Dörfler 		TRACE("Trio64_CalcClock() invalid frequency %1.3f Mhz [freq <= %1.3f Mhz]\n",
39*35db13eaSAxel Dörfler 			   ffreq*BASE_FREQ, ffreq_max*BASE_FREQ / (1 << min_n2));
40*35db13eaSAxel Dörfler 		ffreq = ffreq_max / (1 << min_n2);
41*35db13eaSAxel Dörfler 	}
42*35db13eaSAxel Dörfler 
43*35db13eaSAxel Dörfler 	double best_diff = ffreq;
44*35db13eaSAxel Dörfler 
45*35db13eaSAxel Dörfler 	for (uint8 n2 = min_n2; n2 <= max_n2; n2++) {
46*35db13eaSAxel Dörfler 		for (uint8 n1 = min_n1 + 2; n1 <= max_n1 + 2; n1++) {
47*35db13eaSAxel Dörfler 			int m = (int)(ffreq * n1 * (1 << n2) + 0.5);
48*35db13eaSAxel Dörfler 			if (m < min_m + 2 || m > 127 + 2)
49*35db13eaSAxel Dörfler 				continue;
50*35db13eaSAxel Dörfler 
51*35db13eaSAxel Dörfler 			double div = (double)(m) / (double)(n1);
52*35db13eaSAxel Dörfler 			if ((div >= ffreq_min) && (div <= ffreq_max)) {
53*35db13eaSAxel Dörfler 				double diff = ffreq - div / (1 << n2);
54*35db13eaSAxel Dörfler 				if (diff < 0.0)
55*35db13eaSAxel Dörfler 					diff = -diff;
56*35db13eaSAxel Dörfler 				if (diff < best_diff) {
57*35db13eaSAxel Dörfler 					best_diff = diff;
58*35db13eaSAxel Dörfler 					best_m = m;
59*35db13eaSAxel Dörfler 					best_n1 = n1;
60*35db13eaSAxel Dörfler 					best_n2 = n2;
61*35db13eaSAxel Dörfler 				}
62*35db13eaSAxel Dörfler 			}
63*35db13eaSAxel Dörfler 		}
64*35db13eaSAxel Dörfler 	}
65*35db13eaSAxel Dörfler 
66*35db13eaSAxel Dörfler 	if (max_n1 == 63)
67*35db13eaSAxel Dörfler 		*ndiv = (best_n1 - 2) | (best_n2 << 6);
68*35db13eaSAxel Dörfler 	else
69*35db13eaSAxel Dörfler 		*ndiv = (best_n1 - 2) | (best_n2 << 5);
70*35db13eaSAxel Dörfler 	*mdiv = best_m - 2;
71*35db13eaSAxel Dörfler }
72*35db13eaSAxel Dörfler 
73*35db13eaSAxel Dörfler 
74*35db13eaSAxel Dörfler 
75*35db13eaSAxel Dörfler static bool
76*35db13eaSAxel Dörfler Trio64_ModeInit(const DisplayModeEx& mode)
77*35db13eaSAxel Dörfler {
78*35db13eaSAxel Dörfler 	SharedInfo& si = *gInfo.sharedInfo;
79*35db13eaSAxel Dörfler 
80*35db13eaSAxel Dörfler 	TRACE("Trio64_ModeInit(%d x %d, %d KHz)\n",
81*35db13eaSAxel Dörfler 		mode.timing.h_display, mode.timing.v_display, mode.timing.pixel_clock);
82*35db13eaSAxel Dörfler 
83*35db13eaSAxel Dörfler 	uint32 videoRamMB = si.videoMemSize / (1024 * 1024);	// MB's of video RAM
84*35db13eaSAxel Dörfler 
85*35db13eaSAxel Dörfler 	WriteCrtcReg(0x38, 0x48);			// unlock sys regs
86*35db13eaSAxel Dörfler 	WriteCrtcReg(0x39, 0xa5);			// unlock sys regs
87*35db13eaSAxel Dörfler 	WriteSeqReg(0x08, 0x06);			// unlock extended sequencer regs
88*35db13eaSAxel Dörfler 
89*35db13eaSAxel Dörfler 	WriteCrtcReg(0x45, 0x00, 0x01);		// turn off hardware cursor
90*35db13eaSAxel Dörfler 
91*35db13eaSAxel Dörfler 	uint8 sr12, sr13;
92*35db13eaSAxel Dörfler 	Trio64_CalcClock(mode.timing.pixel_clock, 1, 1, 31, 0, 3, 135000, 270000,
93*35db13eaSAxel Dörfler 					 &sr13, &sr12);
94*35db13eaSAxel Dörfler 
95*35db13eaSAxel Dörfler 	// Set clock registers.
96*35db13eaSAxel Dörfler 
97*35db13eaSAxel Dörfler 	WriteSeqReg(0x12, sr12);
98*35db13eaSAxel Dörfler 	WriteSeqReg(0x13, sr13);
99*35db13eaSAxel Dörfler 
100*35db13eaSAxel Dörfler 	// Activate clock
101*35db13eaSAxel Dörfler 
102*35db13eaSAxel Dörfler 	uint8 tmp = ReadSeqReg(0x15) & ~0x21;
103*35db13eaSAxel Dörfler 	WriteSeqReg(0x15, tmp | 0x02);
104*35db13eaSAxel Dörfler 	WriteSeqReg(0x15, tmp | 0x22);
105*35db13eaSAxel Dörfler 	WriteSeqReg(0x15, tmp | 0x02);
106*35db13eaSAxel Dörfler 
107*35db13eaSAxel Dörfler 	uint8 cr33 = ReadCrtcReg(0x33) & ~0x28;
108*35db13eaSAxel Dörfler 	uint8 cr50 = 0;
109*35db13eaSAxel Dörfler 	uint8 pixmux = 0;
110*35db13eaSAxel Dörfler 
111*35db13eaSAxel Dörfler 	if (si.chipType == S3_TRIO64_V2)
112*35db13eaSAxel Dörfler 		cr33 |= 0x20;
113*35db13eaSAxel Dörfler 
114*35db13eaSAxel Dörfler 	switch (mode.bpp) {
115*35db13eaSAxel Dörfler 		case 8:
116*35db13eaSAxel Dörfler 			break;
117*35db13eaSAxel Dörfler 		case 15:
118*35db13eaSAxel Dörfler 			cr33 |= 0x08;
119*35db13eaSAxel Dörfler 			cr50 = 0x10;
120*35db13eaSAxel Dörfler 			pixmux = 0x30;
121*35db13eaSAxel Dörfler 			break;
122*35db13eaSAxel Dörfler 		case 16:
123*35db13eaSAxel Dörfler 			cr33 |= 0x08;
124*35db13eaSAxel Dörfler 			cr50 = 0x10;
125*35db13eaSAxel Dörfler 			pixmux = 0x50;
126*35db13eaSAxel Dörfler 			break;
127*35db13eaSAxel Dörfler 		case 32:
128*35db13eaSAxel Dörfler 			cr50 = 0x30;
129*35db13eaSAxel Dörfler 			pixmux = 0xd0;
130*35db13eaSAxel Dörfler 			break;
131*35db13eaSAxel Dörfler 	}
132*35db13eaSAxel Dörfler 
133*35db13eaSAxel Dörfler 	bool bEnableAccelFuncs = true;
134*35db13eaSAxel Dörfler 
135*35db13eaSAxel Dörfler 	switch (mode.timing.h_display) {
136*35db13eaSAxel Dörfler 		case 640:
137*35db13eaSAxel Dörfler 			cr50 |= 0x40;
138*35db13eaSAxel Dörfler 			break;
139*35db13eaSAxel Dörfler 		case 800:
140*35db13eaSAxel Dörfler 			cr50 |= 0x80;
141*35db13eaSAxel Dörfler 			break;
142*35db13eaSAxel Dörfler 		case 1024:
143*35db13eaSAxel Dörfler 			cr50 |= 0x00;
144*35db13eaSAxel Dörfler 			break;
145*35db13eaSAxel Dörfler 		case 1152:
146*35db13eaSAxel Dörfler 			cr50 |= 0x01;
147*35db13eaSAxel Dörfler 			break;
148*35db13eaSAxel Dörfler 		case 1280:
149*35db13eaSAxel Dörfler 			cr50 |= 0xc0;
150*35db13eaSAxel Dörfler 			break;
151*35db13eaSAxel Dörfler 		case 1600:
152*35db13eaSAxel Dörfler 			cr50 |= 0x81;
153*35db13eaSAxel Dörfler 			break;
154*35db13eaSAxel Dörfler 		default:
155*35db13eaSAxel Dörfler 			bEnableAccelFuncs = false;	// use app_server default accel functions
156*35db13eaSAxel Dörfler 			break;
157*35db13eaSAxel Dörfler 	}
158*35db13eaSAxel Dörfler 
159*35db13eaSAxel Dörfler 	WriteCrtcReg(0x33, cr33);
160*35db13eaSAxel Dörfler 	WriteCrtcReg(0x50, cr50);		// set number of bits per pixel & display width
161*35db13eaSAxel Dörfler 	WriteCrtcReg(0x67, pixmux);		// set pixel format
162*35db13eaSAxel Dörfler 
163*35db13eaSAxel Dörfler 	WriteSeqReg(0x15, 0x00, 0x10);		// turn off pixel multiplex
164*35db13eaSAxel Dörfler 	WriteSeqReg(0x18, 0x00, 0x80);
165*35db13eaSAxel Dörfler 
166*35db13eaSAxel Dörfler 	// Note that the 2D acceleration (drawing) functions in this accelerant work
167*35db13eaSAxel Dörfler 	// only with the display widths defined in the above switch statement.  For
168*35db13eaSAxel Dörfler 	// the other widths, the default functions in the app_server will be used.
169*35db13eaSAxel Dörfler 
170*35db13eaSAxel Dörfler 	if (bEnableAccelFuncs)
171*35db13eaSAxel Dörfler 	{
172*35db13eaSAxel Dörfler 		gInfo.FillRectangle = Trio64_FillRectangle;
173*35db13eaSAxel Dörfler 		gInfo.FillSpan = Trio64_FillSpan;
174*35db13eaSAxel Dörfler 		gInfo.InvertRectangle = Trio64_InvertRectangle;
175*35db13eaSAxel Dörfler 		gInfo.ScreenToScreenBlit = Trio64_ScreenToScreenBlit;
176*35db13eaSAxel Dörfler 	}
177*35db13eaSAxel Dörfler 	else
178*35db13eaSAxel Dörfler 	{
179*35db13eaSAxel Dörfler 		gInfo.FillRectangle = NULL;
180*35db13eaSAxel Dörfler 		gInfo.FillSpan = NULL;
181*35db13eaSAxel Dörfler 		gInfo.InvertRectangle = NULL;
182*35db13eaSAxel Dörfler 		gInfo.ScreenToScreenBlit = NULL;
183*35db13eaSAxel Dörfler 	}
184*35db13eaSAxel Dörfler 
185*35db13eaSAxel Dörfler 	// Set the standard CRTC vga regs.
186*35db13eaSAxel Dörfler 
187*35db13eaSAxel Dörfler 	uint8 crtc[25], cr3b, cr3c, cr5d, cr5e;
188*35db13eaSAxel Dörfler 
189*35db13eaSAxel Dörfler 	InitCrtcTimingValues(mode, (mode.bpp > 8) ? 2 : 1, crtc, cr3b, cr3c, cr5d, cr5e);
190*35db13eaSAxel Dörfler 	crtc[0x17] = 0xe3;
191*35db13eaSAxel Dörfler 
192*35db13eaSAxel Dörfler 	WriteCrtcReg(0x11, 0x00, 0x80);	// unlock CRTC reg's 0-7 by clearing bit 7 of cr11
193*35db13eaSAxel Dörfler 
194*35db13eaSAxel Dörfler 	for (int k = 0; k < NUM_ELEMENTS(crtc); k++) {
195*35db13eaSAxel Dörfler 		WriteCrtcReg(k, crtc[k]);
196*35db13eaSAxel Dörfler 	}
197*35db13eaSAxel Dörfler 
198*35db13eaSAxel Dörfler 	WriteCrtcReg(0x3b, cr3b);
199*35db13eaSAxel Dörfler 	WriteCrtcReg(0x3c, cr3c);
200*35db13eaSAxel Dörfler 	WriteCrtcReg(0x5d, cr5d);
201*35db13eaSAxel Dörfler 	WriteCrtcReg(0x5e, cr5e);
202*35db13eaSAxel Dörfler 
203*35db13eaSAxel Dörfler 	uint8 miscOutReg = 0x2f;
204*35db13eaSAxel Dörfler 
205*35db13eaSAxel Dörfler 	if ( ! (mode.timing.flags & B_POSITIVE_HSYNC))
206*35db13eaSAxel Dörfler 		miscOutReg |= 0x40;
207*35db13eaSAxel Dörfler 	if ( ! (mode.timing.flags & B_POSITIVE_VSYNC))
208*35db13eaSAxel Dörfler 		miscOutReg |= 0x80;
209*35db13eaSAxel Dörfler 
210*35db13eaSAxel Dörfler 	WriteMiscOutReg(miscOutReg);
211*35db13eaSAxel Dörfler 
212*35db13eaSAxel Dörfler 	uint8 cr58;
213*35db13eaSAxel Dörfler 	if (videoRamMB <= 1)
214*35db13eaSAxel Dörfler 		cr58 = 0x01;
215*35db13eaSAxel Dörfler 	else if (videoRamMB <= 2)
216*35db13eaSAxel Dörfler 		cr58 = 0x02;
217*35db13eaSAxel Dörfler 	else
218*35db13eaSAxel Dörfler 		cr58 = 0x03;
219*35db13eaSAxel Dörfler 
220*35db13eaSAxel Dörfler 	WriteCrtcReg(0x58, cr58 | 0x10, 0x13);	// enable linear addressing & set memory size
221*35db13eaSAxel Dörfler 
222*35db13eaSAxel Dörfler 	WriteCrtcReg(0x31, 0x08);
223*35db13eaSAxel Dörfler 	WriteCrtcReg(0x32, 0x00);
224*35db13eaSAxel Dörfler 	WriteCrtcReg(0x34, 0x10);
225*35db13eaSAxel Dörfler 	WriteCrtcReg(0x3a, 0x15);
226*35db13eaSAxel Dörfler 
227*35db13eaSAxel Dörfler 	WriteCrtcReg(0x51, mode.bytesPerRow >> 7, 0x30);
228*35db13eaSAxel Dörfler 	WriteCrtcReg(0x53, 0x18, 0x18);
229*35db13eaSAxel Dörfler 
230*35db13eaSAxel Dörfler 	int n = 255;
231*35db13eaSAxel Dörfler 	int clock2 = mode.timing.pixel_clock * (mode.bpp / 8);
232*35db13eaSAxel Dörfler 	if (videoRamMB < 2)
233*35db13eaSAxel Dörfler 		clock2 *= 2;
234*35db13eaSAxel Dörfler 	int m = (int)((gInfo.sharedInfo->mclk / 1000.0 * .72 + 16.867) * 89.736
235*35db13eaSAxel Dörfler 			/ (clock2 / 1000.0 + 39) - 21.1543);
236*35db13eaSAxel Dörfler 	if (videoRamMB < 2)
237*35db13eaSAxel Dörfler 		m /= 2;
238*35db13eaSAxel Dörfler 	if (m > 31)
239*35db13eaSAxel Dörfler 		m = 31;
240*35db13eaSAxel Dörfler 	else if (m < 0) {
241*35db13eaSAxel Dörfler 		m = 0;
242*35db13eaSAxel Dörfler 		n = 16;
243*35db13eaSAxel Dörfler 	}
244*35db13eaSAxel Dörfler 
245*35db13eaSAxel Dörfler 	if (n < 0)
246*35db13eaSAxel Dörfler 		n = 0;
247*35db13eaSAxel Dörfler 	else if (n > 255)
248*35db13eaSAxel Dörfler 		n = 255;
249*35db13eaSAxel Dörfler 
250*35db13eaSAxel Dörfler 	WriteCrtcReg(0x54, m << 3);
251*35db13eaSAxel Dörfler 	WriteCrtcReg(0x60, n);
252*35db13eaSAxel Dörfler 
253*35db13eaSAxel Dörfler 	WriteCrtcReg(0x42, 0x00, 0x20);		// disable interlace mode
254*35db13eaSAxel Dörfler 	WriteCrtcReg(0x66, 0x89, 0x8f);
255*35db13eaSAxel Dörfler 
256*35db13eaSAxel Dörfler 	WriteReg16(ADVFUNC_CNTL, 0x0001);		// enable enhanced functions
257*35db13eaSAxel Dörfler 
258*35db13eaSAxel Dörfler 	WriteReg16(SUBSYS_CNTL, 0x8000);		// reset graphics engine
259*35db13eaSAxel Dörfler 	WriteReg16(SUBSYS_CNTL, 0x4000);		// enable graphics engine
260*35db13eaSAxel Dörfler 	ReadReg16(SUBSYS_STAT);
261*35db13eaSAxel Dörfler 
262*35db13eaSAxel Dörfler 	WriteReg16(MULTIFUNC_CNTL, 0x5000 | 0x0004 | 0x000c);
263*35db13eaSAxel Dörfler 
264*35db13eaSAxel Dörfler 	gInfo.WaitQueue(5);
265*35db13eaSAxel Dörfler 	WriteReg16(MULTIFUNC_CNTL, SCISSORS_L | 0);
266*35db13eaSAxel Dörfler 	WriteReg16(MULTIFUNC_CNTL, SCISSORS_T | 0);
267*35db13eaSAxel Dörfler 	WriteReg16(MULTIFUNC_CNTL, SCISSORS_R | (mode.timing.h_display - 1));
268*35db13eaSAxel Dörfler 	WriteReg16(MULTIFUNC_CNTL, SCISSORS_B | ((si.maxFrameBufferSize / mode.bytesPerRow) - 1));
269*35db13eaSAxel Dörfler 
270*35db13eaSAxel Dörfler 	WriteReg32(WRT_MASK, ~0);		// enable all planes
271*35db13eaSAxel Dörfler 
272*35db13eaSAxel Dörfler 	TRACE("Trio64_ModeInit() exit\n");
273*35db13eaSAxel Dörfler 	return true;
274*35db13eaSAxel Dörfler }
275*35db13eaSAxel Dörfler 
276*35db13eaSAxel Dörfler 
277*35db13eaSAxel Dörfler bool
278*35db13eaSAxel Dörfler Trio64_SetDisplayMode(const DisplayModeEx& mode)
279*35db13eaSAxel Dörfler {
280*35db13eaSAxel Dörfler 	// The code to actually configure the display.
281*35db13eaSAxel Dörfler 	// All the error checking must be done in ProposeDisplayMode(),
282*35db13eaSAxel Dörfler 	// and assume that the mode values we get here are acceptable.
283*35db13eaSAxel Dörfler 
284*35db13eaSAxel Dörfler 	WriteSeqReg(0x01, 0x20, 0x20);		// blank the screen
285*35db13eaSAxel Dörfler 
286*35db13eaSAxel Dörfler 	if ( ! Trio64_ModeInit(mode)) {
287*35db13eaSAxel Dörfler 		TRACE("Trio64_ModeInit() failed\n");
288*35db13eaSAxel Dörfler 		return false;
289*35db13eaSAxel Dörfler 	}
290*35db13eaSAxel Dörfler 
291*35db13eaSAxel Dörfler 	Trio64_AdjustFrame(mode);
292*35db13eaSAxel Dörfler 
293*35db13eaSAxel Dörfler 	WriteSeqReg(0x01, 0x00, 0x20);		// unblank the screen
294*35db13eaSAxel Dörfler 
295*35db13eaSAxel Dörfler 	return true;
296*35db13eaSAxel Dörfler }
297*35db13eaSAxel Dörfler 
298*35db13eaSAxel Dörfler 
299*35db13eaSAxel Dörfler 
300*35db13eaSAxel Dörfler void
301*35db13eaSAxel Dörfler Trio64_AdjustFrame(const DisplayModeEx& mode)
302*35db13eaSAxel Dörfler {
303*35db13eaSAxel Dörfler 	// Adjust start address in frame buffer.
304*35db13eaSAxel Dörfler 
305*35db13eaSAxel Dörfler 	int base = (((mode.v_display_start * mode.virtual_width + mode.h_display_start)
306*35db13eaSAxel Dörfler 			* (mode.bpp / 8)) >> 2) & ~1;
307*35db13eaSAxel Dörfler 	base += gInfo.sharedInfo->frameBufferOffset;
308*35db13eaSAxel Dörfler 
309*35db13eaSAxel Dörfler 	WriteCrtcReg(0x0c, (base >> 8) & 0xff);
310*35db13eaSAxel Dörfler 	WriteCrtcReg(0x0d, base & 0xff);
311*35db13eaSAxel Dörfler 	WriteCrtcReg(0x31, base >> 12, 0x30);	// put bits 16-17 in bits 4-5 of CR31
312*35db13eaSAxel Dörfler 	WriteCrtcReg(0x51, base >> 18, 0x03);	// put bits 18-19 in bits 0-1 of CR51
313*35db13eaSAxel Dörfler }
314*35db13eaSAxel Dörfler 
315*35db13eaSAxel Dörfler 
316*35db13eaSAxel Dörfler void
317*35db13eaSAxel Dörfler Trio64_SetIndexedColors(uint count, uint8 first, uint8* colorData, uint32 flags)
318*35db13eaSAxel Dörfler {
319*35db13eaSAxel Dörfler 	// Set the indexed color palette for 8-bit color depth mode.
320*35db13eaSAxel Dörfler 
321*35db13eaSAxel Dörfler 	(void)flags;		// avoid compiler warning for unused arg
322*35db13eaSAxel Dörfler 
323*35db13eaSAxel Dörfler 	if (gInfo.sharedInfo->displayMode.space != B_CMAP8)
324*35db13eaSAxel Dörfler 		return ;
325*35db13eaSAxel Dörfler 
326*35db13eaSAxel Dörfler 	while (count--) {
327*35db13eaSAxel Dörfler 		WriteIndexedColor(first++,	// color index
328*35db13eaSAxel Dörfler 			colorData[0] >> 2,		// red
329*35db13eaSAxel Dörfler 			colorData[1] >> 2,		// green
330*35db13eaSAxel Dörfler 			colorData[2] >> 2);		// blue
331*35db13eaSAxel Dörfler 		colorData += 3;
332*35db13eaSAxel Dörfler 	}
333*35db13eaSAxel Dörfler }
334