Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 635