Posts: 358
Threads: 15
Joined: May 2003
While doing the bit-shifts, it occured to me that if I could poke bits into video memory for a binary screen mode (eg 11) then each integer could control 16 pixels and screen control should be really fast, compared to using 2 integers / pixel (eg pset(x,y). Is this the case? If so, how would one go about finding the memory coordinates for the pixels in a particular screen mode?
If this question is too broad, or naive, just say so, and I'll learn more before asking ...
Posts: 2,020
Threads: 24
Joined: Jun 2002
such is the case with screen 11, as there's only 1 plane. In 16 color modes, you need to switch planes (there are 4) and each bit controls 1 pixel in that plane.
EDIT: yeah, glenn actually read your message properly. The vga buffer is stored in address &HA000, and is 256k, but for one screen the data will never exceed 64k (chained mode 13h uses 4 bytes per pixel to rid itself of planes, which is why there is only one page). Just a little bit on peek/poke:
you use def seg to set an address, and you use peek and poke to write one byte to an offset from that address. Glenn has some more specifics on using the AND operator to change one bit in a byte.
i]"I know what you're thinking. Did he fire six shots or only five? Well, to tell you the truth, in all this excitement, I've kinda lost track myself. But being as this is a .44 Magnum ... you've got to ask yourself one question: 'Do I feel lucky?' Well, do ya punk?"[/i] - Dirty Harry
Posts: 704
Threads: 0
Joined: Dec 2002
but I don't have time to deal with it before leaving for work soon. (And by the time I get to it, somebody will probably have beaten me to it and have a better answer anyway.) This one's easier, so I have time.
In mode 11, each pixel is a bit. 8 of them are stored in video memory together to make a byte (at least, you can think of it that way). So if you do,
DEF SEG = &HA000
BYTE = PEEK(0)
BYTE will contain the data for the first 8 pixels at the top left of your screen. PEEK(1) will be the next 8 pixels on the top row, and so on. After 640 bits (80 bytes) are read, you move to the next row. So, the pixel value (attribute--a 0 or 1 value) in each value of BYTE will be
ATTRIBUTE = (BYTE AND 2^N)/2^N
where N = 0, 1, 2, 3, ..., 7 is the pixel position relative to the rightmost bit position in the byte. For the value of BYTE obtained above,
(BYTE AND 128) / 128
would be the attribute of the pixel at the upper lefthand corner (0, 0) of your screen.
BYTE AND 1
would be the attribute of the pixel at (7, 0).
ravelling Curmudgeon
(geocities sites require copying and pasting URLs.)
I liked spam better when it was something that came in a can.
Windows should be defenestrated.
Posts: 6,419
Threads: 74
Joined: Mar 2002
Well, here is some code I've written a while ago. This is just to plot single pixels in SCREEN 11.
Code: DECLARE SUB MyPsetInScr11 (x%, y%, Bit%)
CONST Set = 1
CONST Clr = 0
DIM SHARED Pwrs2%(7)
FOR i% = 0 TO 7: Pwrs2%(i%) = 2 ^ i%: NEXT i%
SCREEN 11
FOR x% = 240 TO 500
FOR y% = 140 TO 300
MyPsetInScr11 x%, y%, Set
NEXT y%
NEXT x%
FOR x% = 280 TO 460
FOR y% = 180 TO 260
MyPsetInScr11 x%, y%, Clr
NEXT y%
NEXT x%
SUB MyPsetInScr11 (x%, y%, Bit%)
xr% = x% \ 8
xo% = x% AND 7
postn& = 80& * y% + xr%
DEF SEG = &HA000
myByte% = PEEK(postn&)
IF Bit% = Clr THEN
p% = (NOT (Pwrs2%(7 - xo%))) AND &HFF
POKE postn&, myByte% AND p%
ELSE
p% = Pwrs2%(7 - xo%)
POKE postn&, myByte% OR p%
END IF
END SUB
But if you wanna do 1-bit sprites you can always use some technique I used with my ol' programs (when I used Qbasic 1.0 and memory/speed didn't allow me to have tons of sprites). If you check QB help for the LINE command, you'll notice that there is a parameter called "pattern". It is just a 16 bits number. The line will be drawn following that pattern, in 16 pixels bits, so if a bit is 1 then a pixel will be drawn and if a bit is 0 the pixel won't.
I figured out that having 16 different designs in 16 pixels wide horizontal lines one in the top of another, I could draw simple sprites.
The code goes as follows. I think it is self-explicative. The good thing with it is that sprites are blit very fast and that they only take 32 bytes:
Code: DECLARE SUB Put1BitSprite (x%, y%, Spr%())
DIM MySprite%(15) ' A sprite takes 32 bytes.
SCREEN 11
' Read and convert sprite:
' This is done 'cause my sprite is in binary format in the DATAs. It would
' be better to convert them to integer numbers (you just have to have a
' proggie like this and print out the values, and then use them directly).
RESTORE mySpriteInBin:
FOR i% = 0 TO 15
' Better pre-calt the two bytes, then use CVI:
byte1% = 0
FOR j% = 0 TO 7
READ a%
byte1% = byte1% + a% * 2 ^ (7 - j%)
NEXT j%
byte2% = 0
FOR j% = 0 TO 7
READ a%
byte2% = byte2% + a% * 2 ^ (7 - j%)
NEXT j%
MySprite%(i%) = CVI(CHR$(byte2%) + CHR$(byte1%))
NEXT i%
LOCATE 1, 20: PRINT "1 PLANE SPRITES"
' Let's draw some of them
FOR x% = 0 TO 400 STEP 20
Put1BitSprite x%, x%, MySprite%()
NEXT x%
' Sprite in binary data
' (It would be better to pre-calculate this, but...)
mySpriteInBin:
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0
DATA 0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0
DATA 0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0
DATA 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0
DATA 0,0,1,1,0,0,1,0,0,0,1,0,0,1,1,0
DATA 0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0
DATA 0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0
DATA 0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0
DATA 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0
DATA 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0
DATA 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0
DATA 0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0
DATA 0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0
SUB Put1BitSprite (x%, y%, Spr%())
' This technique relies on LINE's pattern drawing capability.
' As patterns are described by 16 bits integers, drawing 16 pixels
' in horizontal lines using our Spr% data as patterns will draw
' our tiny 1 bit sprite.
'
' This can be used in any screen mode. Just replace the '1' by a
' colour% number (add a parameter).
FOR i% = 0 TO 15
LINE (x%, i% + y%)-(15 + x%, i% + y%), 1, , Spr%(i%)
NEXT i%
END SUB
Posts: 358
Threads: 15
Joined: May 2003
Quote:Well, here is some code I've written a while ago. This is just to plot single pixels in SCREEN 11.
Code: DECLARE SUB MyPsetInScr11 (x%, y%, Bit%)
CONST Set = 1
CONST Clr = 0
DIM SHARED Pwrs2%(7)
FOR i% = 0 TO 7: Pwrs2%(i%) = 2 ^ i%: NEXT i%
SCREEN 11
FOR x% = 240 TO 500
FOR y% = 140 TO 300
MyPsetInScr11 x%, y%, Set
NEXT y%
NEXT x%
FOR x% = 280 TO 460
FOR y% = 180 TO 260
MyPsetInScr11 x%, y%, Clr
NEXT y%
NEXT x%
SUB MyPsetInScr11 (x%, y%, Bit%)
xr% = x% \ 8
xo% = x% AND 7
postn& = 80& * y% + xr%
DEF SEG = &HA000
myByte% = PEEK(postn&)
IF Bit% = Clr THEN
p% = (NOT (Pwrs2%(7 - xo%))) AND &HFF
POKE postn&, myByte% AND p%
ELSE
p% = Pwrs2%(7 - xo%)
POKE postn&, myByte% OR p%
END IF
END SUB
Thanks Nathan. I wrote code yesterday to accept x&y input then plot the point...I was tickled pink with myself...before seeing how others did it.
The sub works well. I have a question about this line:
postn& = 80& * y% + xr%
What does 80& mean? I'm not used to seeing numbers appended with symbols except for # on long digit sequences.
Posts: 1,166
Threads: 62
Joined: Apr 2003
80& means to make the equation into a LONG instead of INTEGER.
! = single
# = double
% = integer
& = long
am an asshole. Get used to it.
Posts: 358
Threads: 15
Joined: May 2003
Quote:80& means to make the equation into a LONG instead of INTEGER.
! = single
# = double
% = integer
& = long
of course....however, I raised the question because in the line of code, postn& was already tagged as a long...the question is...then, does it serve any purpose to 'tag' a numer with a data-type tag when the number is used in an expression that evaluates to assign value to a 'tagged' variable?
Just trying to learn, as I was unfamiliar with the 80& construct, so I was wondering why you used it. Thanks.
Posts: 1,166
Threads: 62
Joined: Apr 2003
Code: postn& =80& * y% + xr%
The r-value would be evaluated as an integer if 80 didn't have the & on it. Regardless of the l-value.
am an asshole. Get used to it.
Posts: 358
Threads: 15
Joined: May 2003
Quote:Code: postn& =80& * y% + xr%
The r-value would be evaluated as an integer if 80 didn't have the & on it. Regardless of the l-value.
Thanks for the info...I didn't know this.
The following illustrates for anyone who doesn't know about this.
Code: CLS
x% = 30000
y% = 32000
g& = 1& * x% * y% 'works fine
PRINT x%, y%, g&
g& = x% * y% 'returns an overflow error
PRINT x%, y%, g&
Posts: 6,419
Threads: 74
Joined: Mar 2002
80& * y% makes the result to be a LONG, otherwise it will cause an overflow, 'cause y% is an Integer.
The same with the ol' VGA mode 13h equation:
Code: add& = 320& * y% + x%
'cause it is better to use integers for speed. Have you checked out the 1-bit sprite blitter?
|