Microsoft KB Archive/101516

= PRB: Image Corrupted When Using BLOAD to Load Into Video Memory =

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 ,,,vbdrt10e.lib mlibce.lib;

<div class="status_section">

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.

<div class="moreinformation_section">

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

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.