Chameleon

Chameleon Svn Source Tree

Root/branches/slice/i386/boot2/graphics.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
27 */
28
29#include "boot.h"
30#include "graphics.h"
31#include "vbe.h"
32#include "appleClut8.h"
33#include "bootstruct.h"
34#include "IOHibernatePrivate.h"
35
36#ifndef DEBUG_GR
37#define DEBUG_GR 0
38#endif
39
40#if DEBUG_GR
41#define DBG(x...) printf(x)
42#else
43#define DBG(x...) msglog(x)
44#endif
45
46/*
47 * for spinning disk
48 */
49static int currentIndicator = 0;
50
51int previewTotalSectors = 0;
52int previewLoadedSectors = 0;
53uint8_t *previewSaveunder = 0;
54
55#define VIDEO(x) (bootArgs->Video.v_ ## x)
56
57#define MIN(x, y) ((x) < (y) ? (x) : (y))
58
59#ifndef OPTION_ROM
60#endif
61
62//==========================================================================
63// getVESAModeWithProperties
64//
65// Return the VESA mode that matches the properties specified.
66// If a mode is not found, then return the "best" available mode.
67
68unsigned short
69getVESAModeWithProperties( unsigned short width,
70 unsigned short height,
71 unsigned char bitsPerPixel,
72 unsigned short attributesSet,
73 unsigned short attributesClear,
74 VBEModeInfoBlock * outModeInfo,
75 unsigned short * vesaVersion )
76{
77 VBEInfoBlock vbeInfo;
78 unsigned short * modePtr;
79 VBEModeInfoBlock modeInfo;
80 unsigned char modeBitsPerPixel;
81 unsigned short matchedMode = modeEndOfList;
82 int err;
83
84 // Clear output mode info.
85
86 bzero( outModeInfo, sizeof(*outModeInfo) );
87
88 // Get VBE controller info containing the list of supported modes.
89
90 bzero( &vbeInfo, sizeof(vbeInfo) );
91 strcpy( (char*)&vbeInfo, "VBE2" );
92 err = getVBEInfo( &vbeInfo );
93 if ( err != errSuccess )
94 {
95 return modeEndOfList;
96 }
97
98 // Report the VESA major/minor version number.
99
100 if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;
101
102 // Loop through the mode list, and find the matching mode.
103
104 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
105 *modePtr != modeEndOfList; modePtr++ )
106 {
107 // Get mode information.
108
109 bzero( &modeInfo, sizeof(modeInfo) );
110 err = getVBEModeInfo( *modePtr, &modeInfo );
111 if ( err != errSuccess )
112 {
113 continue;
114 }
115
116#if DEBUG
117 verbose("Mode %x: %dx%dx%d mm:%d attr:%x\n",
118 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
119 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
120 modeInfo.ModeAttributes);
121#endif
122
123 // Filter out unwanted modes based on mode attributes.
124
125 if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
126|| ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
127 {
128 continue;
129 }
130
131 // Pixel depth in bits.
132
133 modeBitsPerPixel = modeInfo.BitsPerPixel;
134
135 if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
136 {
137 // Text mode, 16 colors.
138 }
139 else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
140 {
141 // Packed pixel, 256 colors.
142 }
143 else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
144 && ( modeInfo.MemoryModel == 6 )
145 && ( modeInfo.RedMaskSize == 5 )
146 && ( modeInfo.GreenMaskSize == 5 )
147 && ( modeInfo.BlueMaskSize == 5 ) )
148 {
149 // Direct color, 16 bpp (1:5:5:5).
150 modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
151 }
152 else if ( ( modeBitsPerPixel == 32 )
153 && ( modeInfo.MemoryModel == 6 )
154 && ( modeInfo.RedMaskSize == 8 )
155 && ( modeInfo.GreenMaskSize == 8 )
156 && ( modeInfo.BlueMaskSize == 8 ) )
157 {
158 // Direct color, 32 bpp (8:8:8:8).
159 }
160 else
161 {
162 continue; // Not a supported mode.
163 }
164
165 // Modes larger than the specified dimensions are skipped.
166
167 if ( ( modeInfo.XResolution > width ) ||
168( modeInfo.YResolution > height ) )
169 {
170 continue;
171 }
172
173 // Perfect match, we're done looking.
174
175 if ( ( modeInfo.XResolution == width ) &&
176( modeInfo.YResolution == height ) &&
177( modeBitsPerPixel == bitsPerPixel ) )
178 {
179 matchedMode = *modePtr;
180 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
181 break;
182 }
183
184 // Save the next "best" mode in case a perfect match is not found.
185
186 if ( modeInfo.XResolution == outModeInfo->XResolution &&
187modeInfo.YResolution == outModeInfo->YResolution &&
188modeBitsPerPixel <= outModeInfo->BitsPerPixel )
189 {
190 continue; // Saved mode has more depth.
191 }
192 if ( modeInfo.XResolution < outModeInfo->XResolution ||
193modeInfo.YResolution < outModeInfo->YResolution ||
194modeBitsPerPixel < outModeInfo->BitsPerPixel )
195 {
196 continue; // Saved mode has more resolution.
197 }
198
199 matchedMode = *modePtr;
200 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
201 }
202
203 return matchedMode;
204}
205
206//==========================================================================
207// setupPalette
208
209static void setupPalette( VBEPalette * p, const unsigned char * g )
210{
211 int i;
212 unsigned char * source = (unsigned char *) g;
213
214 for (i = 0; i < 256; i++)
215 {
216 (*p)[i] = 0;
217 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
218 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
219 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
220 }
221}
222
223//==========================================================================
224// Simple decompressor for boot images encoded in RLE format.
225
226char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
227{
228 char *out, *cp;
229
230 struct RLEBlock {
231 unsigned char count;
232 unsigned char value;
233 } * bp = (struct RLEBlock *) rleData;
234
235 out = cp = malloc( outBytes );
236 if ( out == NULL ) return NULL;
237
238 while ( rleBlocks-- )
239 {
240 memset( cp, bp->value, bp->count );
241 cp += bp->count;
242 bp++;
243 }
244
245 return out;
246}
247
248//==========================================================================
249// setVESAGraphicsMode
250
251int setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel, unsigned short refreshRate )
252{
253 VBEModeInfoBlock minfo;
254 unsigned short mode;
255 unsigned short vesaVersion;
256 int err = errFuncNotSupported;
257
258 do {
259 mode = getVESAModeWithProperties( width, height, bitsPerPixel,
260 maColorModeBit |
261 maModeIsSupportedBit |
262 maGraphicsModeBit |
263 maLinearFrameBufferAvailBit,
264 0,
265 &minfo, &vesaVersion );
266 if ( mode == modeEndOfList )
267 {
268 break;
269 }
270
271//
272// FIXME : generateCRTCTiming() causes crash.
273//
274
275// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
276// (gBootMode & kBootModeSafe) == 0 )
277// {
278// VBECRTCInfoBlock timing;
279//
280// // Generate CRTC timing for given refresh rate.
281//
282// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
283// refreshRate, kCRTCParamRefreshRate,
284// &timing );
285//
286// // Find the actual pixel clock supported by the hardware.
287//
288// getVBEPixelClock( mode, &timing.PixelClock );
289//
290// // Re-compute CRTC timing based on actual pixel clock.
291//
292// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
293// timing.PixelClock, kCRTCParamPixelClock,
294// &timing );
295//
296// // Set the video mode and use specified CRTC timing.
297//
298// err = setVBEMode( mode | kLinearFrameBufferBit |
299// kCustomRefreshRateBit, &timing );
300// }
301// else
302// {
303// // Set the mode with default refresh rate.
304//
305// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
306// }
307
308 // Set the mode with default refresh rate.
309
310 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
311
312 if ( err != errSuccess )
313 {
314 break;
315 }
316
317 // Set 8-bit color palette.
318
319 if ( minfo.BitsPerPixel == 8 )
320 {
321 VBEPalette palette;
322 setupPalette( &palette, appleClut8 );
323 if ((err = setVBEPalette(palette)) != errSuccess)
324 {
325 break;
326 }
327 }
328
329 // Is this required for buggy Video BIOS implementations?
330 // On which adapter?
331
332 if ( minfo.BytesPerScanline == 0 )
333minfo.BytesPerScanline = ( minfo.XResolution *
334 minfo.BitsPerPixel ) >> 3;
335
336 // Update KernBootStruct using info provided by the selected
337 // VESA mode.
338
339 bootArgs->Video.v_display = GRAPHICS_MODE;
340//setVideoMode(GRAPHICS_MODE, 0);
341 bootArgs->Video.v_width = minfo.XResolution;
342 bootArgs->Video.v_height = minfo.YResolution;
343 bootArgs->Video.v_depth = minfo.BitsPerPixel;
344 bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
345 bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
346
347 }
348 while ( 0 );
349
350 return err;
351}
352
353
354#ifndef OPTION_ROM
355
356
357//==========================================================================
358// LookUpCLUTIndex
359
360unsigned long lookUpCLUTIndex( unsigned char index,
361 unsigned char depth )
362{
363 long result, red, green, blue;
364
365 red = appleClut8[index * 3 + 0];
366 green = appleClut8[index * 3 + 1];
367 blue = appleClut8[index * 3 + 2];
368
369 switch (depth) {
370 case 16 :
371 result = ((red & 0xF8) << 7) |
372((green & 0xF8) << 2) |
373((blue & 0xF8) >> 3);
374 result |= (result << 16);
375 break;
376
377 case 32 :
378 result = (red << 16) | (green << 8) | blue;
379 break;
380
381 default :
382 result = index | (index << 8);
383 result |= (result << 16);
384 break;
385 }
386
387 return result;
388}
389
390//==========================================================================
391// drawColorRectangle
392
393void * stosl(void * dst, long val, long len)
394{
395 asm volatile ( "rep; stosl"
396 : "=c" (len), "=D" (dst)
397 : "0" (len), "1" (dst), "a" (val)
398 : "memory" );
399
400 return dst;
401}
402
403void drawColorRectangle( unsigned short x,
404unsigned short y,
405unsigned short width,
406unsigned short height,
407unsigned char colorIndex )
408{
409 long pixelBytes;
410 long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
411 char * vram;
412
413 pixelBytes = VIDEO(depth) / 8;
414 vram = (char *) VIDEO(baseAddr) +
415VIDEO(rowBytes) * y + pixelBytes * x;
416
417 width = MIN(width, VIDEO(width) - x);
418 height = MIN(height, VIDEO(height) - y);
419
420 while ( height-- )
421 {
422 int rem = ( pixelBytes * width ) % 4;
423 if ( rem ) bcopy( &color, vram, rem );
424 stosl( vram + rem, color, pixelBytes * width / 4 );
425 vram += VIDEO(rowBytes);
426 }
427}
428
429void
430loadImageScale (void *input, int iw, int ih, int ip, void *output, int ow, int oh, int op, int or)
431{
432int x,y, off;
433int red=0x7f, green=0x7f, blue=0x7f;
434for (x=0;x<ow;x++)
435for (y=0;y<oh;y++)
436{
437off=(x*iw)/ow+((y*ih)/oh)*iw;
438switch (ip)
439{
440case 16:
441{
442uint16_t val;
443val=((uint16_t *)input)[off];
444red=(val>>7)&0xf8;
445green=(val>>2)&0xf8;
446blue=(val<<3)&0xf8;
447break;
448}
449case 32:
450{
451uint32_t val;
452val=((uint32_t *)input)[off];
453red=(val>>16)&0xff;
454green=(val>>8)&0xff;
455blue=(val)&0xff;
456break;
457}
458}
459char *ptr=(char *)output+x*(op/8)+y*or;
460switch (op)
461{
462case 16:
463*((uint16_t *)ptr) = ((red & 0xF8) << 7) |
464((green & 0xF8) << 2) |
465((blue & 0xF8) >> 3);
466break;
467case 32 :
468*((uint32_t *)ptr) = (red << 16) | (green << 8) | blue;
469break;
470}
471}
472}
473
474DECLARE_IOHIBERNATEPROGRESSALPHA
475
476void drawPreview(void *src, uint8_t * saveunder)
477{
478uint8_t * screen;
479uint32_t rowBytes, pixelShift;
480uint32_t x, y;
481int32_t blob;
482uint32_t alpha, in, color, result;
483uint8_t * out;
484void *uncomp;
485int origwidth, origheight, origbpx;
486uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
487
488if (src && (uncomp=DecompressData(src, &origwidth, &origheight, &origbpx)))
489{
490if (!setVESAGraphicsMode(origwidth, origheight, origbpx, 0))
491if (initGraphicsMode () != errSuccess)
492return;
493screen = (uint8_t *) VIDEO (baseAddr);
494rowBytes = VIDEO (rowBytes);
495loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEO(width), VIDEO(height), VIDEO(depth), VIDEO (rowBytes));
496}
497else
498{
499if (initGraphicsMode () != errSuccess)
500return;
501screen = (uint8_t *) VIDEO (baseAddr);
502rowBytes = VIDEO (rowBytes);
503// Set the screen to 75% grey.
504 drawColorRectangle(0, 0, VIDEO(width), VIDEO(height), 0x01 /* color index */);
505}
506
507
508pixelShift = VIDEO (depth) >> 4;
509if (pixelShift < 1) return;
510
511screen += ((VIDEO (width)
512- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
513+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
514
515for (y = 0; y < kIOHibernateProgressHeight; y++)
516{
517out = screen + y * rowBytes;
518for (blob = 0; blob < kIOHibernateProgressCount; blob++)
519{
520color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray;
521for (x = 0; x < kIOHibernateProgressWidth; x++)
522{
523alpha = gIOHibernateProgressAlpha[y][x];
524result = color;
525if (alpha)
526{
527if (0xff != alpha)
528{
529if (1 == pixelShift)
530{
531in = *((uint16_t *)out) & 0x1f;// 16
532in = (in << 3) | (in >> 2);
533}
534else
535in = *((uint32_t *)out) & 0xff;// 32
536saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in;
537result = ((255 - alpha) * in + alpha * result + 0xff) >> 8;
538}
539if (1 == pixelShift)
540{
541result >>= 3;
542*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
543}
544else
545*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
546}
547out += (1 << pixelShift);
548}
549out += (kIOHibernateProgressSpacing << pixelShift);
550}
551}
552}
553
554void updateProgressBar(uint8_t * saveunder, int32_t firstBlob, int32_t select)
555{
556uint8_t * screen;
557uint32_t rowBytes, pixelShift;
558uint32_t x, y;
559int32_t blob, lastBlob;
560uint32_t alpha, in, color, result;
561uint8_t * out;
562uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
563
564pixelShift = VIDEO(depth) >> 4;
565if (pixelShift < 1) return;
566screen = (uint8_t *) VIDEO (baseAddr);
567rowBytes = VIDEO (rowBytes);
568
569screen += ((VIDEO (width)
570- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
571+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
572
573lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1);
574
575screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift;
576
577for (y = 0; y < kIOHibernateProgressHeight; y++)
578{
579out = screen + y * rowBytes;
580for (blob = firstBlob; blob <= lastBlob; blob++)
581{
582color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray;
583for (x = 0; x < kIOHibernateProgressWidth; x++)
584{
585alpha = gIOHibernateProgressAlpha[y][x];
586result = color;
587if (alpha)
588{
589if (0xff != alpha)
590{
591in = saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++];
592result = ((255 - alpha) * in + alpha * result + 0xff) / 255;
593}
594if (1 == pixelShift)
595{
596result >>= 3;
597*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
598}
599else
600*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
601}
602out += (1 << pixelShift);
603}
604out += (kIOHibernateProgressSpacing << pixelShift);
605}
606}
607}
608#endif
609
610
611//==========================================================================
612// setVESATextMode
613
614static int
615setVESATextMode( unsigned short cols,
616unsigned short rows,
617unsigned char bitsPerPixel )
618{
619 VBEModeInfoBlock minfo;
620 unsigned short mode = modeEndOfList;
621
622 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
623 {
624 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
625 maColorModeBit |
626 maModeIsSupportedBit,
627 maGraphicsModeBit,
628 &minfo, NULL );
629 }
630
631 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
632 {
633 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
634 minfo.XResolution = 80;
635 minfo.YResolution = 25;
636 }
637
638 // Update KernBootStruct using info provided by the selected
639 // VESA mode.
640
641 bootArgs->Video.v_display = VGA_TEXT_MODE;
642 bootArgs->Video.v_baseAddr = 0xb8000;
643 bootArgs->Video.v_width = minfo.XResolution;
644 bootArgs->Video.v_height = minfo.YResolution;
645 bootArgs->Video.v_depth = 8;
646 bootArgs->Video.v_rowBytes = 0x8000;
647
648 return errSuccess; // always return success
649}
650
651//==========================================================================
652// getNumberArrayFromProperty
653
654int
655getNumberArrayFromProperty( const char * propKey,
656 unsigned long numbers[],
657 unsigned long maxArrayCount )
658{
659 char * propStr;
660 unsigned long count = 0;
661
662 propStr = newStringForKey( (char *) propKey , &bootInfo->bootConfig );
663 if ( propStr )
664 {
665 char * delimiter = propStr;
666 char * p = propStr;
667
668 while ( count < maxArrayCount && *p != '\0' )
669 {
670 unsigned long val = strtoul( p, &delimiter, 10 );
671 if ( p != delimiter )
672 {
673 numbers[count++] = val;
674 p = delimiter;
675 }
676 while ( ( *p != '\0' ) && !isdigit(*p) )
677 p++;
678 }
679
680 free( propStr );
681 }
682
683 return count;
684}
685
686int initGraphicsMode ()
687{
688unsigned long params[4];
689int count;
690
691params[3] = 0;
692count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
693
694// Try to find a resolution if "Graphics Mode" setting is not available.
695if ( count < 3 )
696{
697 // Use the default resolution if we don't have an initialized GUI.
698/* if (gui.screen.width == 0 || gui.screen.height == 0)
699 {
700 gui.screen.width = DEFAULT_SCREEN_WIDTH;
701 gui.screen.height = DEFAULT_SCREEN_HEIGHT;
702 }
703*/
704 params[0] = DEFAULT_SCREEN_WIDTH; //gui.screen.width;
705 params[1] = DEFAULT_SCREEN_HEIGHT; // gui.screen.height;
706params[2] = 32;
707}
708
709// Map from pixel format to bits per pixel.
710
711if ( params[2] == 256 ) params[2] = 8;
712if ( params[2] == 555 ) params[2] = 16;
713if ( params[2] == 888 ) params[2] = 32;
714
715return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
716}
717
718//==========================================================================
719// setVideoMode
720//
721// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
722
723void
724setVideoMode( int mode, int drawgraphics)
725{
726 unsigned long params[4];
727 int count;
728 int err = errSuccess;
729
730 if ( mode == GRAPHICS_MODE )
731 {
732 if ( (err=initGraphicsMode ()) == errSuccess ) {
733if (gVerboseMode) {
734// Tell the kernel to use text mode on a linear frame buffer display
735bootArgs->Video.v_display = FB_TEXT_MODE;
736//video_mode(2);
737} else {
738bootArgs->Video.v_display = GRAPHICS_MODE;
739//video_mode(1);
740}
741}
742else video_mode(1);
743 }
744
745 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
746 {
747 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
748 if ( count < 2 )
749 {
750 params[0] = 80; // Default text mode is 80x25.
751 params[1] = 25;
752 }
753
754setVESATextMode( params[0], params[1], 4 );
755 bootArgs->Video.v_display = VGA_TEXT_MODE;
756 }
757
758 currentIndicator = 0;
759}
760
761//==========================================================================
762// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
763
764inline int getVideoMode(void)
765{
766 return bootArgs->Video.v_display;
767}
768
769//==========================================================================
770// Display and clear the activity indicator.
771
772static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};
773
774// To prevent a ridiculously fast-spinning indicator,
775// ensure a minimum of 1/9 sec between animation frames.
776#define MIN_TICKS 2
777
778void
779spinActivityIndicator(int sectors)
780{
781 static unsigned long lastTickTime = 0, currentTickTime;
782#ifndef OPTION_ROM
783if (previewTotalSectors && previewSaveunder)
784{
785int blob, lastBlob;
786
787lastBlob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
788previewLoadedSectors+=sectors;
789blob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
790
791if (blob!=lastBlob)
792updateProgressBar (previewSaveunder, lastBlob, blob);
793return;
794}
795#endif
796currentTickTime = time18(); // late binding
797if (currentTickTime < lastTickTime + MIN_TICKS)
798{
799return;
800}
801else
802{
803lastTickTime = currentTickTime;
804}
805
806if (getVideoMode() == VGA_TEXT_MODE)
807{
808if (currentIndicator >= sizeof(indicator))
809{
810currentIndicator = 0;
811}
812putc(indicator[currentIndicator++]);
813putc('\b');
814}
815}
816
817void
818clearActivityIndicator( void )
819{
820 if ( getVideoMode() == VGA_TEXT_MODE )
821 {
822putc(' ');
823putc('\b');
824 }
825}
826
827

Archive Download this file

Revision: 721