Article ID: 101516
Article Last Modified on 8/16/2005
APPLIES TO
- Microsoft Visual Basic for MS-DOS
- Microsoft Cinemania 97 Standard Edition
- Microsoft QuickBasic 4.5 for MS-DOS
- Microsoft MS-DOS 6.0 Standard Edition
This article was previously published under Q101516
SYMPTOMS
Using the BLOAD statement to load binary images directly into video memory from a disk drive that uses either the DoubleSpace disk compressor (DBLSPACE.BIN) or the SMARTDrive disk cache (SMARTDRV.EXE or SMARTDRV.SYS) may result in a corrupted image.
CAUSE
The DoubleSpace and SMARTDrive implementations assume they can read back from memory the same data they write. But because graphics screen memory is write-only with some video systems, this can yield incorrect data.
RESOLUTION
Here are several possible workarounds:
- Copy the files to a drive that does not use SMARTDrive or DoubleSpace (such as a RAM drive). Then use BLOAD to load the files from that drive.
Use BLOAD to load the image into the memory occupied by a temporary dynamic array. Then move the image to video memory using PEEK and POKE. This method is slow but it works. For example:
REDIM tmp(0 TO (BitPlaneSize - 1) \ 4) AS LONG ' allocate memory DEF SEG = VARSEG(tmp(0)) BLOAD f$, VARPTR(tmp(0)) DIM j AS LONG FOR j = 0 TO BitPlaneSize - 1 DEF SEG = VARSEG(tmp(0)) DIM byte AS INTEGER byte = PEEK(VARPTR(tmp(0)) + j) DEF SEG = VideoPageSegment POKE j, byte NEXT REDIM tmp(0) AS LONG ' deallocate memory
Use BLOAD to load the image into the memory occupied by a temporary dynamic array. Then move the image to video memory using the Microsoft C function _fmemcpy. This method is fast, but it requires the correct version of Microsoft C. For example:
' put the next statement at the module level, all on one line DECLARE SUB fmemcpy CDECL ALIAS "__fmemcpy" (BYVAL o%, BYVAL s%, SEG s AS ANY, BYVAL n%) ... REDIM tmp(0 TO (BitPlaneSize - 1) \ 4) AS LONG ' allocate memory DEF SEG = VARSEG(tmp(0)) BLOAD f$, VARPTR(tmp(0)) CALL fmemcpy(0, VideoPageSegment, tmp(0), BitPlaneSize) REDIM tmp(0) AS LONG ' deallocate memory
- To use _fmemcpy in the interpreter environment, create a Quicklibrary named FMEMCPY.QLB by using the following commands:
lib mlibce.lib *fmemcpy.obj;
link /q fmemcpy.obj,,,vbdosqlb.lib mlibce.lib; - To link an EXE that uses _fmemcpy, use the following command. Use VBDRT10E.LIB for the run-time module, or VBDCL10E.LIB for stand-alone:
link <objects here>,,,vbdrt10e.lib mlibce.lib;
STATUS
This behavior is by design. It is a limitation of DoubleSpace and SMARTDrive. Note that DoubleSpace comes with the MS-DOS operating system versions listed above, and SMARTDrive comes with many Microsoft products.
MORE INFORMATION
WARNING: One or more of the following functions are discussed in this article; VarPtr, VarPtrArray, VarPtrStringArray, StrPtr, ObjPtr. These functions are not supported by Microsoft Technical Support. They are not documented in the Visual Basic documentation and are provided in this Knowledge Base article "as is." Microsoft does not guarantee that they will be available in future releases of Visual Basic.
Steps to Reproduce Problem
The following program creates a solid rectangle in graphics SCREEN 9. The program saves this image, waits for a key press, then reloads the image. When the image is reloaded from a DoubleSpace or SMARTDrive disk, it is corrupted:
DECLARE SUB BSAVEImage () DECLARE SUB BLOADImage () CONST BitPlaneSize = 28000 ' Amount of disk space needed to save one ' bit plane (in bytes) for SCREEN 9. CONST VideoPageSegment = &HA800 ' Beginning of page 1 for ' SCREEN 9 in video memory. CONST FileName = "IMAGE" SCREEN 9, , 1, 1 ' Set the visual and active pages to 1. CLS LINE (50, 50)-(150, 150),, BF ' Draw a solid box on the screen. CALL BSAVEImage CLS PRINT "Press any key to reload the image " WHILE INKEY$ = "": WEND CALL BLOADImage WHILE INKEY$ = "": WEND END SUB BLOADImage FOR i% = 0 TO 3 OUT &H3C4, 2 ' Indicates index to Map Register. OUT &H3C5, 2 ^ i% ' Select the bit plane to load into. f$ = FileName + CHR$(i% + 48) + ".GRA" ' replace the following two statements with the code for one ' of the workarounds DEF SEG = VideoPageSegment BLOAD f$, 0 NEXT i% DEF SEG END SUB SUB BSAVEImage DEF SEG = VideoPageSegment FOR i% = 0 TO 3 OUT &H3CE, 4 ' Select Read Map Select Register. OUT &H3CF, i% ' Select the bit plane to save. f$ = FileName + CHR$(i% + 48) + ".GRA" BSAVE f$, 0, BitPlaneSize NEXT i% DEF SEG END SUB
Keywords: kbprb KB101516