'===========================================================================
' Subject: LOAD/SAVE 320X200 BITMAPS          Date: 07-06-98 (22:27)      
'  Author: Anders Olofsson                    Code: QB, QBasic, PDS       
'  Origin: anders.olofsson@mail.bip.net     Packet: GRAPHICS.ABC
'===========================================================================
'
' Fast BMP-viewer for screen 13, by Anders Olofsson 1998.
' This program loads a 320 x 200 256 color bitmap picture in about 0.15
' seconds. (On my 486/66 mhz in QB 4.5)
'
' Thanks to Jonathan Leger for the Memcopy
' routine and Davey W. taylor for his BMPSNOW.BAS, where i found
' the BmpInfo type def.
'
'   E-mail: anders.olofsson@mail.bip.net
'

DEFINT A-Z
DECLARE SUB ShowBMP (File$)
DECLARE SUB SaveBMP (Filename$)
DECLARE FUNCTION getfilename$ (Text$)
DECLARE SUB Memcopy (fromseg%, fromoffset%, toseg%, tooffset%, bytes%)


TYPE BmpInfo
 id AS STRING * 2
 filesize AS LONG
 reserved AS STRING * 4
 Offset AS LONG
 SizeOfHeader AS LONG
 BMPWidth AS LONG
 BmpHeight AS LONG
 Bitplanes AS INTEGER
 Bitsperpixel AS INTEGER
 Compression AS LONG
 Imagesize AS LONG
 Pelspermetrex AS LONG
 Pelspermetrey AS LONG
 UsedColors AS LONG
 importantcolors AS LONG
END TYPE


Z$ = getfilename$("Select 320x200 256 color BMP file to view: ")

SCREEN 13

T! = TIMER
ShowBMP Z$
PRINT USING "It took##.### seconds."; TIMER - T!

SLEEP

CLS : ShowBMP Z$
LOCATE 1, 1
PRINT "Saving BMP...";
T! = TIMER
SaveBMP "TEMP.BMP"
PRINT "done."
PRINT USING "It took##.### seconds."; TIMER - T!

WHILE LEN(INKEY$) = 0: WEND

FUNCTION getfilename$ (Text$)
SCREEN 0: WIDTH 80, 25: CLS
LOCATE 1, 1
PRINT Text$
LINE INPUT I$
IF I$ = "" THEN END
getfilename$ = I$
END FUNCTION

SUB Memcopy (fromseg%, fromoffset%, toseg%, tooffset%, bytes%)

DIM MemCopy.ASM AS STRING
MemCopy.ASM = ""
MemCopy.ASM = MemCopy.ASM + CHR$(85)                             'PUSH BP
MemCopy.ASM = MemCopy.ASM + CHR$(137) + CHR$(229)                'MOV BP,SP
MemCopy.ASM = MemCopy.ASM + CHR$(30)                             'PUSH DS
MemCopy.ASM = MemCopy.ASM + CHR$(139) + CHR$(70) + CHR$(10)      'MOV AX,[BP+0A]
MemCopy.ASM = MemCopy.ASM + CHR$(142) + CHR$(192)                'MOV ES,AX
MemCopy.ASM = MemCopy.ASM + CHR$(139) + CHR$(70) + CHR$(14)      'MOV AX,[BP+0E]
MemCopy.ASM = MemCopy.ASM + CHR$(142) + CHR$(216)                'MOV DS,AX
MemCopy.ASM = MemCopy.ASM + CHR$(139) + CHR$(118) + CHR$(12)     'MOV SI,[BP+0C]
MemCopy.ASM = MemCopy.ASM + CHR$(139) + CHR$(126) + CHR$(8)      'MOV DI,[BP+08]
MemCopy.ASM = MemCopy.ASM + CHR$(139) + CHR$(78) + CHR$(6)       'MOV CX,[BP+06]
MemCopy.ASM = MemCopy.ASM + CHR$(243)                            'REPZ
MemCopy.ASM = MemCopy.ASM + CHR$(164)                            'MOVSB
MemCopy.ASM = MemCopy.ASM + CHR$(31)                             'POP DS
MemCopy.ASM = MemCopy.ASM + CHR$(93)                             'POP BP
MemCopy.ASM = MemCopy.ASM + CHR$(203)                            'RETF

DEF SEG = VARSEG(MemCopy.ASM)
        CALL Absolute(BYVAL fromseg%, BYVAL fromoffset%, BYVAL toseg%, BYVAL tooffset%, BYVAL bytes%, SADD(MemCopy.ASM))
DEF SEG

END SUB

SUB SaveBMP (Filename$)
DIM BMPHeader AS BmpInfo

BMPHeader.id = "BM"
BMPHeader.SizeOfHeader = 40
BMPHeader.BMPWidth = 320
BMPHeader.BmpHeight = 200
BMPHeader.Bitsperpixel = 8
BMPHeader.Imagesize = 64000
BMPHeader.UsedColors = 255
BMPHeader.Bitplanes = 1
BMPHeader.Offset = 1078
BMPHeader.Pelspermetrex = 3780
BMPHeader.Pelspermetrey = 3790


F = FREEFILE
OPEN Filename$ FOR BINARY AS #F

 PUT #F, , BMPHeader

FOR C = 0 TO 255
 OUT &H3C7, C
 B = INP(&H3C9): G = INP(&H3C9): R = INP(&H3C9)
 PData$ = CHR$(R * 4) + CHR$(G * 4) + CHR$(B * 4) + " "
 PUT #F, , PData$
NEXT

DIM Buffer AS STRING
Segment = &HA000 + (64000 \ 16) - 20

FOR y = 200 TO 1 STEP -1
 Buffer = SPACE$(320)
 Memcopy Segment, 0, VARSEG(Buffer), SADD(Buffer), 320
 PUT #F, , Buffer
 Segment = Segment - 20
NEXT

CLOSE #F

END SUB

SUB ShowBMP (File$)

DIM BMPHeader AS BmpInfo

F = FREEFILE
OPEN File$ FOR BINARY ACCESS READ AS #F
GET #F, 1, BMPHeader

IF BMPHeader.id <> "BM" OR BMPHeader.SizeOfHeader <> 40 THEN
 PRINT File$; " is not a valid bitmap file": END
ELSEIF BMPHeader.BMPWidth <> 320 OR BMPHeader.BmpHeight <> 200 THEN
 PRINT "Size of image has to bee 320x200!": END
ELSEIF BMPHeader.Compression THEN
 PRINT "This program does'nt show rle compressed bmp's!": END
ELSEIF BMPHeader.Bitsperpixel <> 8 THEN
 PRINT "Only 256 color bitmaps can be displayed!": END
END IF

Pal$ = INPUT$(1024, F)
FOR C = 0 TO 255  'Set palette to black while drawing to screen
 OUT &H3C8, C: OUT &H3C9, 0: OUT &H3C9, 0: OUT &H3C9, 0
NEXT

DIM Buffer AS STRING
Segment = &HA000 + (64000 - 1280) \ 16

FOR y = 199 TO 0 STEP -4
 Buffer = SPACE$(320)
 GET #F, , Buffer
 Buffer = INPUT$(320, F) + Buffer
 Buffer = INPUT$(320, F) + Buffer
 Buffer = INPUT$(320, F) + Buffer
 Memcopy VARSEG(Buffer), SADD(Buffer), Segment, 0, 1280
 Segment = Segment - 80
NEXT

CLOSE #F

FOR C = 0 TO 255
 B = ASC(MID$(Pal$, C * 4 + 1, 1)) \ 4
 G = ASC(MID$(Pal$, C * 4 + 2, 1)) \ 4
 R = ASC(MID$(Pal$, C * 4 + 3, 1)) \ 4
 OUT &H3C8, C
 OUT &H3C9, R: OUT &H3C9, G: OUT &H3C9, B
NEXT
END SUB

