Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
poking binary data to screen mode 11
#1
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 ...
Reply
#2
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
Reply
#3
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.
Reply
#4
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
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#5
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.
Reply
#6
80& means to make the equation into a LONG instead of INTEGER.

! = single
# = double
% = integer
& = long
am an asshole. Get used to it.
Reply
#7
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.
Reply
#8
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.
Reply
#9
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&
Reply
#10
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?
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)