PRB: Image Corrupted When Using BLOAD to Load Into Video Memory
ID: Q101516
|
The information in this article applies to:
-
Microsoft Visual Basic Standard and Professional Editions for MS-DOS, version 1.0
-
Microsoft Basic Professional Development System for MS-DOS, version 7.1
-
Microsoft QuickBASIC for MS-DOS
-
Microsoft MS-DOS operating system version 6.0
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 INFORMATIONWARNING: 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
Additional query words:
Keywords :
Version : MS-DOS:1.0,6.0,7.1
Platform : MS-DOS
Issue type : kbprb
|