Bitmaps in MCGA
Moderators:Administrator, Global Moderator
Putting aside my general lack of knowledge, can someone please tell me where I can get a program to display 256 color bitmaps in screen mode 13. I can't seem to find one that works; they all seem to distort the pic in some way or another. That, or a lot of them use some screwy palette thing (see general lack of knowledge) so that when I modify the program to try and save the picture as a gfx, it screws up the colors and deletes about 4 pixels from the bottom right corner. Please, someone help! I didn't spend 10 hours designing tiles on Paint so that I can fail at loading them into QBasic. Speed of the program is not an issue. I want the simplest thing possible for 256 colors, 320x200 pixels. Thanks for even taking the time to read this ridiculously long post.
-
- QBasic God
- Posts:166
- Joined:Tue Mar 25, 2003 12:45 am
- Location:U.S.A.
- Contact:
Well, if your image is missing pixels like that, it's usually due to not allocating enough memory to store the image. The standard formula for screen 13 is:
As for a .bmp loader, there are tons of them around. Here's one that uses assembly!
Code: Select all
MemSize% = ((ImageWidth% * ImageHeight%) / 2) + 2
Code: Select all
' Bmpload Version 2 By Doug Barry (PD Computers)
' This is the fastest BMP Loader I have ever seen, and I wrote it !!!!
' God it's fast, anyway it uses assembler to copy a variable to the another
' part of the memory, here I have used it to put the image data into the
' bit of the Physical ram that overlaps the video memory, hence loading
' the picture in one vertical blank space (one 50Hz cycle)
'
' Thanks load to Dan Holmes for finding out the memory copying routine, and
' Andrew Griffin/Jon Sutton for info on the BMP structure.
' Also to the guy/gal that posted ShowBMP9.bas on the net and to the
' guy/gal that wrote CPLASMA.BAS for the "OUT" command for palette setting.
' Enjoy, even though it's uncommented it should be easy to understand,
' being only 65, yes count 'em 65 lines of code (WOW!!!!!!!!).
' My E-Mail is pdcomputers@iname.com
' or s3dougla@doreen.rainhammark.kent.sch.uk if this don't work.
' i will try to reply and help with any of your problems.
DECLARE SUB SetPALETTE (Slot%, R%, G%, B%)
DECLARE SUB memcopy (fromseg%, fromoffset%, toseg%, tooffset%, bytes%)
DIM SHARED Buffer(319, 199) AS STRING * 1
DIM SHARED Pointer AS STRING * 1
DIM SHARED ImageDataSegment(200) AS STRING * 320
DEFINT A-Z
FileName$ = LCASE$(LTRIM$(RTRIM$(COMMAND$)))
'FileName$ = "Test.Bmp"
OPEN FileName$ FOR BINARY AS #1
IF LOF(1) < 2 THEN PRINT "File does not exist": KILL FileName$: SYSTEM
GET #1, 54, Pointer
SCREEN 13
FOR Slot% = 0 TO 255
GET #1, , Pointer
B% = INT(ASC(Pointer) / 4)
GET #1, , Pointer
G% = INT(ASC(Pointer) / 4)
GET #1, , Pointer
R% = INT(ASC(Pointer) / 4)
SetPALETTE Slot%, R%, B%, G%
GET #1, , Pointer
NEXT Slot%
FOR Y = 199 TO 0 STEP -1
GET #1, , ImageDataSegment(Y)
NEXT
CLOSE
memcopy VARSEG(ImageDataSegment(0)), VARPTR(ImageDataSegment(0)), &HA000, 0, &HFA00
SYSTEM
SUB memcopy (fromseg%, fromoffset%, toseg%, tooffset%, bytes%)
asm$ = ""
asm$ = asm$ + CHR$(85)
asm$ = asm$ + CHR$(137) + CHR$(229)
asm$ = asm$ + CHR$(30)
asm$ = asm$ + CHR$(139) + CHR$(70) + CHR$(10)
asm$ = asm$ + CHR$(142) + CHR$(192)
asm$ = asm$ + CHR$(139) + CHR$(70) + CHR$(14)
asm$ = asm$ + CHR$(142) + CHR$(216)
asm$ = asm$ + CHR$(139) + CHR$(118) + CHR$(8)
asm$ = asm$ + CHR$(139) + CHR$(126) + CHR$(12)
asm$ = asm$ + CHR$(139) + CHR$(78) + CHR$(6)
asm$ = asm$ + CHR$(243)
asm$ = asm$ + CHR$(164)
asm$ = asm$ + CHR$(31)
asm$ = asm$ + CHR$(93)
asm$ = asm$ + CHR$(203)
WAIT &H3DA, 8
DEF SEG = VARSEG(asm$)
CALL Absolute(BYVAL fromseg%, BYVAL fromoffset%, BYVAL toseg%, BYVAL tooffset%, BYVAL bytes%, SADD(asm$))
DEF SEG
END SUB
SUB SetPALETTE (Slot, R, G, B)
OUT &H3C8, Slot
OUT &H3C9, R
OUT &H3C9, B
OUT &H3C9, G
END SUB
Come check out [url=http://www.freebasic.net/forum/index.php]FreeBASIC[/url]. The syntax is based on QuickBasic, but it expands to use pointers, operator overloading, etc... The list goes on and on!
-
- QBasic God
- Posts:166
- Joined:Tue Mar 25, 2003 12:45 am
- Location:U.S.A.
- Contact:
CALL ABSOLUTE is the QuickBasic function that calls an assembly language procedure. You need to include QB.BI to use it. Here's a copy of QB.BI in case you don'y have it.
Copy the code from above and paste it into a new .txt file in your QB45 dir and save it. Then, rename the file QB.BI. At the beginning of your program, add this line:
So, the .bmp loading program should look like this:
If you still have problems just post again.
P.S.
If you want to use BLOAD/BSAVE, then you have to save the palette because those functions do not.
Code: Select all
'***
' QB.BI - Assembly Support Include File
'
' Copyright <C> 1987 Microsoft Corporation
'
' Purpose:
' This include file defines the types and gives the DECLARE
' statements for the assembly language routines ABSOLUTE,
' INTERRUPT, INTERRUPTX, INT86OLD, and INT86XOLD.
'
'***************************************************************************
'
' Define the type needed for INTERRUPT
'
TYPE RegType
ax AS INTEGER
bx AS INTEGER
cx AS INTEGER
dx AS INTEGER
bp AS INTEGER
si AS INTEGER
di AS INTEGER
flags AS INTEGER
END TYPE
'
' Define the type needed for INTERUPTX
'
TYPE RegTypeX
ax AS INTEGER
bx AS INTEGER
cx AS INTEGER
dx AS INTEGER
bp AS INTEGER
si AS INTEGER
di AS INTEGER
flags AS INTEGER
ds AS INTEGER
es AS INTEGER
END TYPE
'
' DECLARE statements for the 5 routines
' -------------------------------------
'
' Generate a software interrupt, loading all but the segment registers
'
DECLARE SUB INTERRUPT (intnum AS INTEGER,inreg AS RegType,outreg AS RegType)
'
' Generate a software interrupt, loading all registers
'
DECLARE SUB INTERRUPTX (intnum AS INTEGER,inreg AS RegTypeX, outreg AS RegTypeX)
'
' Call a routine at an absolute address.
' NOTE: If the routine called takes parameters, then they will have to
' be added to this declare statement before the parameter given.
'
DECLARE SUB ABSOLUTE (address AS INTEGER)
'
' Generate a software interrupt, loading all but the segment registers
' (old version)
'
DECLARE SUB INT86OLD (intnum AS INTEGER,_
inarray(1) AS INTEGER,_
outarray(1) AS INTEGER)
'
' Gemerate a software interrupt, loading all the registers
' (old version)
'
DECLARE SUB INT86XOLD (intnum AS INTEGER,_
inarray(1) AS INTEGER,_
outarray(1) AS INTEGER)
'
Copy the code from above and paste it into a new .txt file in your QB45 dir and save it. Then, rename the file QB.BI. At the beginning of your program, add this line:
Code: Select all
'$INCLUDE: 'QB.BI'
Code: Select all
'$INCLUDE: 'QB.BI'
DECLARE SUB SetPALETTE (Slot%, R%, G%, B%)
DECLARE SUB memcopy (fromseg%, fromoffset%, toseg%, tooffset%, bytes%)
DIM SHARED Buffer(319, 199) AS STRING * 1
DIM SHARED Pointer AS STRING * 1
DIM SHARED ImageDataSegment(200) AS STRING * 320
DEFINT A-Z
FileName$ = LCASE$(LTRIM$(RTRIM$(COMMAND$)))
'FileName$ = "Test.Bmp"
OPEN FileName$ FOR BINARY AS #1
IF LOF(1) < 2 THEN PRINT "File does not exist": KILL FileName$: SYSTEM
GET #1, 54, Pointer
SCREEN 13
FOR Slot% = 0 TO 255
GET #1, , Pointer
B% = INT(ASC(Pointer) / 4)
GET #1, , Pointer
G% = INT(ASC(Pointer) / 4)
GET #1, , Pointer
R% = INT(ASC(Pointer) / 4)
SetPALETTE Slot%, R%, B%, G%
GET #1, , Pointer
NEXT Slot%
FOR Y = 199 TO 0 STEP -1
GET #1, , ImageDataSegment(Y)
NEXT
CLOSE
memcopy VARSEG(ImageDataSegment(0)), VARPTR(ImageDataSegment(0)), &HA000, 0, &HFA00
SYSTEM
SUB memcopy (fromseg%, fromoffset%, toseg%, tooffset%, bytes%)
asm$ = ""
asm$ = asm$ + CHR$(85)
asm$ = asm$ + CHR$(137) + CHR$(229)
asm$ = asm$ + CHR$(30)
asm$ = asm$ + CHR$(139) + CHR$(70) + CHR$(10)
asm$ = asm$ + CHR$(142) + CHR$(192)
asm$ = asm$ + CHR$(139) + CHR$(70) + CHR$(14)
asm$ = asm$ + CHR$(142) + CHR$(216)
asm$ = asm$ + CHR$(139) + CHR$(118) + CHR$(8)
asm$ = asm$ + CHR$(139) + CHR$(126) + CHR$(12)
asm$ = asm$ + CHR$(139) + CHR$(78) + CHR$(6)
asm$ = asm$ + CHR$(243)
asm$ = asm$ + CHR$(164)
asm$ = asm$ + CHR$(31)
asm$ = asm$ + CHR$(93)
asm$ = asm$ + CHR$(203)
WAIT &H3DA, 8
DEF SEG = VARSEG(asm$)
CALL Absolute(BYVAL fromseg%, BYVAL fromoffset%, BYVAL toseg%, BYVAL tooffset%, BYVAL bytes%, SADD(asm$))
DEF SEG
END SUB
SUB SetPALETTE (Slot, R, G, B)
OUT &H3C8, Slot
OUT &H3C9, R
OUT &H3C9, B
OUT &H3C9, G
END SUB
If you still have problems just post again.
P.S.
If you want to use BLOAD/BSAVE, then you have to save the palette because those functions do not.
Come check out [url=http://www.freebasic.net/forum/index.php]FreeBASIC[/url]. The syntax is based on QuickBasic, but it expands to use pointers, operator overloading, etc... The list goes on and on!