PRB: Video Image Corrupted If Stored on Compressed Drive

ID: Q108289

5.10 6.00 6.00a 7.00 | 1.00 1.50

MS-DOS               | WINDOWS
kbother kbprb

The information in this article applies to:

SYMPTOMS

A video image stored in a file on a compressed drive is corrupted when written to video memory. If the file is stored on an uncompressed drive, it displays correctly.

CAUSE

If the amount of data read into a buffer from a file on a compressed drive is less than 8K then DoubleSpace uses an internal buffer for decompression. For larger amounts of data, however, DoubleSpace may use the user's buffer, which in this case is video memory, for temporary storage. DoubleSpace assumes that it can read back from memory the same data it writes. Unfortunately, video memory is write-only on some systems, which results in the video display becoming corrupted.

RESOLUTION

Workarounds are:

STATUS

This behavior is by design and is a limitation of DoubleSpace. Similar behavior may be observed with other drive compression utilities.

Sample Code

FILE1.C and FILE2.C create two data files, FILE1.DAT and FILE2.DAT. Place these files on a compressed drive and then run FILE3.EXE.

/* FILE1. C
   Compile options needed: /AL
*/ 

#include <stdio.h>
#include <graph.h>
#include <dos.h>

FILE *FilePtr;        // File pointer
char far *VidPtr;    // Pointer to video memory
int loop1, loop2;    // Loop variables
int k = 0,l = 10;    // Intermediate loop variables

void main(void)
{
    _setvideomode( _ERESCOLOR );

//  Display some rectangles and lines

    for (loop1 = 0; loop1 < 6 ; loop1++) {
       for ( loop2 = 0 ; loop2 < 500; loop2 +=50 )
           _rectangle( _GBORDER, loop2, k , loop2+10 , l );
       _moveto( 0, k+5);
       _lineto( loop2, k+5);
       k+=50;
       l+=50;
    }
    getch();

//  Set up a pointer to video memory

    FP_SEG( VidPtr ) = 0xA000;
    FP_OFF( VidPtr ) = 0x0000;

//  Open a file to store the video image in

    FilePtr = fopen( "file1.dat", "w+" );
    fwrite( VidPtr, 1, 28000, FilePtr );
    fclose ( FilePtr );

    _setvideomode( _DEFAULTMODE);
}

/* FILE2.C
   Compile options needed: /AL
*/ 

#include <stdio.h>
#include <graph.h>
#include <dos.h>

FILE *FilePtr;      // File pointer
char far *VidPtr;   // Pointer to video memory
int var1;           // Loop variable

void main(void)
{
    _setvideomode( _ERESCOLOR );

//  Draw some lines

    for (var1 = 5 ; var1 < 555; var1+=50 ) {
      _moveto( var1, 0);
      _lineto( var1, 300);
    }
    getch();

//  Initialize the video pointer

    FP_SEG( VidPtr ) = 0xA000;
    FP_OFF( VidPtr ) = 0x0000;

//  Open a file to store the video image

    FilePtr = fopen( "file2.dat", "w+" );
    fwrite( VidPtr, 1, 28000, FilePtr );
    fclose ( FilePtr );

    _setvideomode( _DEFAULTMODE);
}

/* FILE3. C
   Compile options needed: /AL
*/ 

#include <stdio.h>
#include <graph.h>
#include <dos.h>
#include <conio.h>

FILE *FilePtr;           // File pointer
char far *VidPtr;        // Pointer to video memory
int var;                 // Loop variable for workaround #2
char * tmpbuf, *tmpbuf1; // Temporary buffers--se for workaround #3

void main(void)
{
//  Initialize the video pointer

    FP_SEG( VidPtr ) = 0xA000;
    FP_OFF( VidPtr ) = 0x0000;

    _setvideomode( _ERESCOLOR );

//  Load the map mask register with a data value.
//  For further information on this step see the "Programmer's
//  Guide to PC & PS/2 Video Systems" by Richard Wilton,
//  published by Microsoft Press.

    outp( 0x3c4,2);
    outp( 0x3c5,1);

//  Open and read FILE1.DAT into video memory

    FilePtr = fopen( "file1.dat", "rb+" );

/*  Uncomment for workaround #3                       */ 
/*  if ((tmpbuf = (char*)malloc( 28500 )) == NULL)    */ 
/*       exit(5);                                     */ 
/*  setvbuf( FilePtr, tmpbuf, _IOFBF, 28500);         */ 

    fread( VidPtr, 1 , 28000, FilePtr );

/*  Replace the above fread() call with this for workaround #2 */ 
/*  for (var = 0; var < 28000; var+=7000) {                    */ 
/*    fread( VidPtr, 1 , 7000, FilePtr );                      */ 
/*    VidPtr += 7000;                                          */ 
/*  }                                                          */ 

//  Reset the video pointer

    FP_OFF( VidPtr ) = 0x0000;

//  Load the map mask register with a data value

    outp( 0x3c4,2);
    outp( 0x3c5,2);

//  Open and read FILE2.DAT into video memory

    FilePtr = fopen( "file2.dat", "rb+" );

/*  Uncomment for workaround #3                       */ 
/*  if ((tmpbuf1 = (char*)malloc( 28500 )) == NULL)   */ 
/*       exit(5);                                     */ 
/*  setvbuf( FilePtr, tmpbuf1, _IOFBF, 28500);        */ 

    fread( VidPtr, 1 , 28000, FilePtr );

/*  Replace the above fread() call with this for workaround #2 */ 
/*  for (var = 0; var < 28000; var+=7000) {                    */ 
/*    fread( VidPtr, 1 , 7000, FilePtr );                      */ 
/*    VidPtr += 7000;                                          */ 
/*  }                                                          */ 

    getch();
    _setvideomode( _DEFAULTMODE);
}

Additional reference words: 5.10 6.00 6.00a 7.00 1.00 1.50 KBCategory: kbprg kbprb KBSubcategory: VCGenIss Keywords : kb16bitonly

Last Reviewed: July 23, 1997