Microsoft KB Archive/76729

= Microsoft Knowledge Base =

Complete Program to BLOAD/BSAVE Four Plane PICEM Images
Last reviewed: September 25, 1997

Article ID: Q76729

7.00 7.10 MS-DOS kbprg kbcode kbfile

SUMMARY
This article contains a program that combines information from several Microsoft Knowledge Base articles for a more complete example of BLOAD and BSAVE for graphics images. It incorporates information on how to shell to PICEM210 (a shareware utility) to display a graphics image, how to BLOAD/BSAVE the graphics file with four color planes, and how to save the video card palette registers associated with the image.

This information applies to Microsoft Basic Professional Development System (PDS) versions 7.0 and 7.1 for MS-DOS.

NOTE: Some portions of this code may be modified to make it compatible with Microsoft QuickBasic versions 4.0, 4.0b, and 4.5, and Microsoft Basic Compiler versions 6.0 and 6.0b. See the notes below.

You can find BCPICSAV.EXE, a self-extracting file, on these services:

  Microsoft's World Wide Web site on the Internet On the www.microsoft.com home page, click the Support icon Click Knowledge Base, and select the product Enter kbfile BCPICSAV.EXE, and click GO! Open the article, and click the button to download the file   Internet (anonymous FTP) ftp ftp.microsoft.com Change to the Softlib/Mslfiles folder Get BCPICSAV.EXE   The Microsoft Network On the Edit menu, click Go To, and then click Other Location Type &quot;mssupport&quot; (without the quotation marks) Double-click the MS Software Library icon Find the appropriate product area Locate and Download BCPICSAV.EXE   Microsoft Download Service (MSDL) Dial (425) 936-6735 to connect to MSDL Download BCPICSAV.EXE 

For additional information about downloading, please see the following article in the Microsoft Knowledge Base:

ARTICLE-ID: Q119591 TITLE    : How to Obtain Microsoft Support Files from Online Services

MORE INFORMATION
The program below, PIC.BAS, shows one method of using PICEM210 to display a .GIF, .PCX, or .PIC graphics image file and BSAVE the image to disk. This program is intended to save and load images in screen modes with more than one bit plane. Screen modes 9 (640-by-350-by-16) and 12 (640-by-480-by-16) fall into this category (they each have four bit planes). This program can also save screen mode 13 (320-by-200-by-256) graphics images, but PICEM210 already has the ability to save one bit plane images in the Basic BSAVE format without using a separate Basic program.

PICEM210 is a freeware graphics file viewing utility that can display .GIF, .PCX, and .PIC file formats, and is required to make this program run. PICEM210 is available as a shareware product. For more information on PICEM, please read the PICEM README file PICEM210.DOC, or query on the following:

PICEM PICEM210 has the ability to set most of its viewing options from the command line in addition to leaving the image on the screen when it ends. The options used in this program are as follows:

/e   -leaves image on screen after displaying /k   -tells PICEM to not wait for a keypress after displaying image /v:x -which mode to display the image

values for x used are: i   -Screen mode 9, change to &quot;g&quot; for EGA cards m   -Screen mode 12 l   -Screen mode 13 In addition to BSAVEing the graphics image, the program below also saves the palette registers used by the picture. It does so because when you shell to another process then return to Basic, Basic does not know that the screen mode and palette have changed during the shell. If this step is not performed, the next time the image is loaded, Basic's default palette is used rather than the palette needed for the image, so the picture will not display in the correct colors. For more information on saving the palette registers, query on the following words:

SAVE and PALETTE and REGISTERS and INTERRUPT For more information on how to BLOAD/BSAVE graphics images, please query on the following words:

BLOAD and BSAVE and EGA and VGA

Information About the Program
The program first finds if it is loading a previously BSAVEd file or if it is BSAVEing a graphics file. It then gets information about the file to load or save, and which screen mode the file is to be displayed in (valid values are 9, 12, and 13). It then either shells to PICEM or BLOADs the image to the screen.

When an image is saved, there are four image files (saved as &quot; .B_X&quot;) and one register file (saved as &quot; .REG&quot;) saved. The image files each contain one bit plane of the image, and the register file contains the values of the palette registers for the image.

When an image is loaded, the program looks for the &quot; .REG&quot; to make sure that the image has been previously BSAVED (where is the filename of the image BSAVEd). This is where the code needs to be changed to make the program compatible with QuickBasic version 4.5. The DIR$ function in Basic PDS 7.x checks to see if a specified file exists; if the file does not exist, DIR$ returns a null string. QuickBasic does not support the DIR$ function, but there are ways to work around this (for example, shelling a directory listing into a file, or calling interrupts to load a directory listing into an array). For more information on these techniques, please query on the following words:

LOAD and DIRECTORY and LISTING and ARRAY PIC.BAS will also accept command line parameters. The format is as follows:

pic [ /mode [] ] where

:  /S = Save a GIF, /L = Load a BSAVE file /mode:        /9 = 640x350x16, /12 = 640x480x16, /13 = 320x200x256 :   Filename of .GIF, .PCX, .PIC file to BSAVE, extension required. (Not used when loading a BSAVE file.) : Eight character filename to BLOAD or BSAVE GIF An example of loading the 640-by-480-by-16 GIF file COLORS.GIF and BSAVEing it as COLORS is as follows (where COLORS.GIF is in the current directory):

pic /s /12 colors.gif colors The above command will create five files: COLORS.B_0, COLORS.B_1, COLORS.B_2, COLORS.B_3, and COLORS.REG. To load the BSAVE files back into video memory, use the following command:

pic /l /12 colors The steps used to compile the program are as follows:

bc /o pic;

link pic,,,qbx.lib;

Disclaimer
This program is NOT a retail product of Microsoft Corporation. It was developed by a private technician as a utility to be used by programmers using Microsoft Basic PDS. This program is provided AS IS, without warranty of any kind, either expressed or implied. The entire risk as to the quality and performance of this program is with the user. Neither Microsoft or the programmer of the application shall be responsible for any problems, including, but not limited to, any lost profits, lost savings, or other incidental or consequential damages arising from the use or inability to use this program.

Code Example
'PIC.BAS--An interface for Basic PDS to use with PICEM version 2.1. 'This program requires the user to have a copy of PICEM210.EXE, 'available through bulletin boards. DEFINT A-Z CONST TRUE = -1 CONST FALSE = NOT TRUE

CONST Save = 2       'Constants to tell if we are loading or CONST Load = 1        'saving GIF and bsave files

TYPE ColorType       'Type used to store Palette register information red AS STRING * 1 green AS STRING * 1 blue AS STRING * 1 END TYPE

REM $INCLUDE: 'qbx.bi'                'use qb.bi for QuickBasic 4.50 DECLARE SUB LoadBSAVE (NumRegs%, mode, BSAVEfile$) DECLARE SUB SaveGif (NumRegs%, mode, Giffile$, BSAVEfile$) DECLARE SUB SaveBasicPalette (NumRegs%, LoadSave%) DECLARE SUB EgaVgaSub (filename$, mode AS INTEGER, RW AS INTEGER) DECLARE SUB ComLine (cmd$, SL$, mode%, Bfile$, Gif$)

COMMON SHARED ColorBuf AS ColorType, BasicPalette AS ColorType

'$DYNAMIC 'Buffers for Basic's and PICEM's Palette Registers DIM ColorBuf(0 TO 15) AS ColorType DIM BasicPalette(0 TO 15) AS ColorType DIM NumRegs AS INTEGER

NumRegs = 16       'Initialize variables, assume SCREEN 9 or 12 Giffile$ = &quot; &quot; BSAVEfile$ = &quot; &quot;

cmd$ = COMMAND$    'Check for command line arguements IF cmd$ = &quot;&quot; THEN

SCREEN 0 CLS COLOR 14, 8 LOCATE 1, 5 PRINT &quot;Welcome to the GIF/PCX/PIC picture BSAVE/BLOAD utility&quot; LOCATE 3, 5 PRINT &quot;Would you like to Save a GIF, Load a BSAVE file, or&quot; LOCATE 4, 5: INPUT &quot;Quit the application? (S,L,Q): &quot;, SaveorLoad$ ELSE

'Parse command$ CALL ComLine(cmd$, SaveorLoad$, mode, BSAVEfile$, Giffile$) END IF SELECT CASE UCASE$(SaveorLoad$)

CASE &quot;S&quot; CALL SaveGif(NumRegs, mode, Giffile$, BSAVEfile$) CASE &quot;L&quot; CALL LoadBSAVE(NumRegs, mode, BSAVEfile$) CASE &quot;H&quot; PRINT &quot;Usage: /s-save GIF, /l-load bsave file,&quot; PRINT PRINT &quot; PIC [<Save/Load> /mode <GIF-file> ]&quot; PRINT PRINT &quot;Save/Load: /s = Save a GIF, /l = Load BSAVE files&quot; PRINT &quot;/mode: /9 = 640x350x16, /12 = 640x480x16, /13 = &quot;; PRINT &quot;320x200x256&quot; PRINT &quot;GIF-file: path, name, and extention of GIF-file to BSAVE&quot; PRINT &quot;bsavefile: 8 character filename to BLOAD, or BSAVE GIF&quot; END SELECT END

SUB ComLine (cmd$, SL$, mode, Bfile$, Gif$)

'This slightly modified code is in the On-Line help for Command$

DIM Args$(1 TO 4) MaxArgs = 4 NumArgs = 0: In = FALSE L = LEN(cmd$) 'Go through the command line a character at a time. FOR I = 1 TO L     C$ = MID$(cmd$, I, 1) 'Test for character being a blank or a tab. IF ((C$ <> &quot; &quot;) AND (C$ <> CHR$(9)) AND (C$ <> &quot;/&quot;)) THEN 'Neither blank nor tab. Test if you're inside an argument. IF NOT In THEN 'You've found the start of a new argument. IF NumArgs = MaxArgs THEN EXIT FOR NumArgs = NumArgs + 1 In = TRUE END IF     'Add the character to the current argument. Args$(NumArgs) = Args$(NumArgs) + C$     ELSE 'Found a blank or a tab. 'Set &quot;Not in an argument&quot; flag to FALSE. In = FALSE END IF  NEXT I

IF NumArgs > 2 THEN      'at least 3 arguments, or print help SL$ = Args$(1)         'first param should be /s or /l mode = VAL(Args$(2))   'next param should be video mode IF SL$ = &quot;S&quot; THEN Gif$ = Args$(3)     'if /s, get GIF-file name Bfile$ = Args$(4)   'assign bsave file-name ELSEIF SL$ = &quot;L&quot; THEN Bfile$ = Args$(3)   'if /l get bsave file-name END IF  ELSE SL$ = &quot;H&quot; END IF END SUB

SUB EgaVgaSub (filename$, mode AS INTEGER, RW AS INTEGER) STATIC

'This code is essentially the same as BLOAD/BSAVE application note, 'the name the file is BSAVEd as is the only thing changed

SELECT CASE mode    'Determine how much to BSAVE.

'Mode 7 is 320x200- save/load 8000 bytes. 'Mode 8 is 640x200- save/load 16000 bytes. 'Modes 9 and 10 are 640x350- save/load 28000 bytes. 'Modes 11 and 12 are 640x480- save/load 38400 bytes. 'Mode 13 is 320x200x(1byte/256 colors)- save/load 64000 bytes.

CASE 7 total! = 8000   CASE 8 total! = 16000   CASE 9 TO 10 total! = 28000   CASE 11 TO 12 total! = 38400   CASE 13 total! = 64000   CASE ELSE PRINT &quot;ERROR: Non EGA/VGA graphics mode!&quot; GOTO NonEGAorVGA END SELECT

IF mode = 10 THEN  'SCREEN mode 10 only has two bit planes cycle = 1        'because it is used on a monochrome display. ELSE cycle = 3        'SCREEN modes 7, 8, 9, 11, and 12 have four END IF             'bit planes.

DEF SEG = &HA000  'Define the segment for EGA/VGA graphics. 'BSAVEing and BLOADing SCREEN mode 13 does not IF mode = 13 THEN 'require the use of the graphics map register. IF RW = 1 THEN                  'BLOAD the file. f$ = filename$ + &quot;.B_0&quot;       'Load the file into VGA memory. BLOAD f$, 0                   '0 is the offset to page 0. ELSE                            'BSAVE the file. f$ = filename$ + &quot;.B_0&quot;   'Save VGA memory in a file. BSAVE f$, 0, total! 'Save the visual page, at offset 0. END IF ELSE FOR I = 0 TO cycle    'Cycle through each bit plane of EGA/VGA. IF RW = 1 THEN         'BLOAD files. OUT &H3C4, 2        'We want to index the map register. OUT &H3C5, 2 ^ I    'Bit plane we want to reference.

'Load each file into its corresponding bit plane. f$ = filename$ + &quot;.B_&quot; + CHR$(I + 48) BLOAD f$, 0         '0 is the offset to page 0. ELSE                   'BSAVE files. OUT &H3CE, 4        'Select Read Map Select Register. OUT &H3CF, I        'Select the bit plane to save.

'Save each bit plane in its own file. f$ = filename$ + &quot;.B_&quot; + CHR$(I + 48) BSAVE f$, 0, total! 'Save the visual page, at offset 0. END IF   NEXT I  END IF  DEF SEG                      'Restore the segment. NonEGAorVGA: END SUB

SUB LoadBSAVE (NumRegs, mode, SaveFile$)

'This sub loads BSAVE files from disk into video 'memory, also restores the Picture's Palette registers 'The DIR$ function is code that needs to be changed for QB4.50

DIM inregx AS RegTypeX DIM outregx AS RegTypeX

DO UNTIL DIR$(SaveFile$ + &quot;.reg&quot;) <> &quot;&quot;  'Get valid filename LOCATE 3, 1: PRINT SPACE$(79)          'Clear previous print lines LOCATE 4, 1: PRINT SPACE$(79) LOCATE 3, 5 INPUT &quot;Please enter the BSAVE filename (8 chars,no ext):&quot;, SaveFile$ LOOP 'Get valid screen mode DO UNTIL (mode = 9) OR (mode = 12) OR (mode = 13) LOCATE 4, 5: INPUT &quot;Which screen mode is it? (9,12,13): &quot;, mode LOOP

IF mode = 13 THEN                'if screen 13, change array sizes REDIM ColorBuf(0 TO 255) AS ColorType REDIM BasicPalette(0 TO 255) AS ColorType NumRegs = 256 END IF

SCREEN mode    'Change to the specified screen mode CLS

CALL SaveBasicPalette(NumRegs, Save)      'Save Basic's Palette

DEF SEG = VARSEG(ColorBuf(0))    'Bload the picture's Palette BLOAD SaveFile$ + &quot;.reg&quot;, VARPTR(ColorBuf(0)) 'into an array DEF SEG

inregx.ax = &H1012                  'restore picture's palette inregx.bx = 0                       'to the palette registers inregx.cx = NumRegs inregx.es = VARSEG(ColorBuf(0)) inregx.dx = VARPTR(ColorBuf(0)) CALL InterruptX(&H10, inregx, outregx)

CALL EgaVgaSub(SaveFile$, mode, Load) 'reload the BSAVEd picture

COLOR 3 PRINT &quot;Picture should be displayed, hit key to continue&quot; DO: LOOP UNTIL INKEY$ <> &quot;&quot; ERASE ColorBuf

CALL SaveBasicPalette(NumRegs, Load) 'Restore Basic's Palette SCREEN 0 CLS END SUB

SUB SaveBasicPalette (NumRegs, LoadSave)

'This sub Saves/Restores Basic's internal Palette registers

DIM inregx AS RegTypeX DIM outregx AS RegTypeX

IF LoadSave = Save THEN inregx.ax = &H1017                'Save Basic's palette ELSE inregx.ax = &H1012                'Load Basic's palette END IF inregx.bx = 0 inregx.cx = NumRegs inregx.es = VARSEG(BasicPalette(0)) inregx.dx = VARPTR(BasicPalette(0)) CALL InterruptX(&H10, inregx, outregx) 'interrupt to load/save 'palette registers END SUB

SUB SaveGif (NumRegs, mode, Giffile$, SaveName$)

'This sub shells to PICEM210 to display the 'GIF file, then BSAVEs the image to disk

DIM inregx AS RegTypeX DIM outregx AS RegTypeX

DO UNTIL DIR$(Giffile$) <> &quot;&quot;        'Get a valid file name LOCATE 3, 5: PRINT SPACE$(70)      'Clear previous print lines LOCATE 4, 5: PRINT SPACE$(70) LOCATE 3, 5: PRINT &quot;Please enter the drive,path and name&quot; LOCATE 4, 5 INPUT &quot;of the GIF file you would like to save: &quot;, Giffile$ Giffile$ = LTRIM$(RTRIM$(Giffile$)) LOOP 'Get valid screen mode DO UNTIL (mode = 9) OR (mode = 12) OR (mode = 13) LOCATE 6, 5: INPUT &quot;which screen mode? (9,12,13): &quot;, mode LOOP 'Get valid filename for BSAVE DO UNTIL (LEN(SaveName$) < 9) AND (SaveName$ <> &quot; &quot;) LOCATE 7, 5 INPUT &quot;Filename you want to save it as? (8 chars): &quot;, SaveName$ LOOP

IF mode = 9 THEN      'values used by PICEM210 to select screen mode view$ = &quot;i&quot;        'for EGA cards this should be &quot;g&quot; ELSEIF mode = 12 THEN view$ = &quot;m&quot; ELSEIF mode = 13 THEN REDIM ColorBuf(0 TO 255) AS ColorType REDIM BasicPalette(0 TO 255) AS ColorType view$ = &quot;l&quot; NumRegs = 256 END IF

SCREEN mode CALL SaveBasicPalette(NumRegs, Save)      'Save Basic's Palette

LOCATE 1, 1 shellstr$ = view$ + &quot; &quot; + Giffile$ picem$ = &quot;picem210 /e /k /v:&quot; + shellstr$ 'Shell string for picem210 PRINT &quot;hit a key when ready to display picture&quot; PRINT picem$ DO: LOOP UNTIL INKEY$ <> &quot;&quot;

SHELL picem$                   'shell to picem

inregx.ax = &H1017             'save picture's palette registers inregx.bx = 0 inregx.cx = NumRegs inregx.es = VARSEG(ColorBuf(0)) inregx.dx = VARPTR(ColorBuf(0)) CALL InterruptX(&H10, inregx, outregx)

DEF SEG = VARSEG(ColorBuf(0))  'BSAVE registers to file BSAVE SaveName$ + &quot;.reg&quot;, VARPTR(ColorBuf(0)), 3 * NumRegs DEF SEG

CALL EgaVgaSub(SaveName$, mode, Save)             'BSAVE picture

ERASE ColorBuf COLOR 3 LOCATE 1, 1: PRINT &quot;Picture has been saved, press key to quit&quot; DO: LOOP UNTIL INKEY$ <> &quot;&quot;

'Restore Basic's Palette CALL SaveBasicPalette(NumRegs, Load) SCREEN 0 CLS END SUB

Additional Reference Words: BasicCom 4.00 4.00a 4.00b 6.00 6.00b 7.00 7.10