Jump to content
IGNORED

Using bitmaps


phoney

Recommended Posts

Okay, here's another question. (For FastBasic.)

 

I have taken some graphics from my PC and turned them into binary bitmaps I am trying to reproduce on the Atari.

 

So right now I have something like

(start a location X, Y)

DATA 0,1,1,0,0,0,1,1,1,1,1,1,0,255

(read from the data)

(if value is 1, PLOT a point, in any case increment X, if it's 255 increment Y ... eventually the value could be from 0 to 3 based on color)

 

It works, but this seems very inefficient as the DATA statements become very long to cover every pixel of a 160-pixel wide screen.

 

I understand I can encode 8 pixels in a byte, but I don't understand how to decode them so I can use the PLOT command with them. Like, if I turn 01110010 into 114, how do I turn it back into 01110010 (I guess as an eight digit array) so I can tell where to PLOT? Or can I somehow figure out how to PLOT eight pixels in a row using that number 114. But also how would I then encode the color data ...

 

I see a lot of people using what appear to be bitmapped objects encoded as a few bytes, but I can't figure out how to get from 'there' to 'here' in terms of plotting the object on the screen, especially with color data.

 

I feel like this has been covered in articles but I can't quite figure out how to turn my question into what they are answering. They all seem to assume I've memorized a lot of things about the memory map and honestly I want to use PLOT because every time I try to address screen locations with POKE I get them slightly wrong, and speed doesn't matter.

 

Also FastBasic doesn't seem to be able to address anything higher than 32767 as a variable??? Which makes it hard to address a lot of screen locations.

Link to comment
Share on other sites

If it's a significant amount of graphics, like over a few hundred bytes then you're probably better off keeping them in a file.

Using PLOT is also pretty slow, adding decoding packed graphics could see it take an hour to load a single screen.

An entire screen dumped as a 4 or 8K file would take a while to load using GET/POKE (like over a minute) but still be way quicker than PLOT.

 

Link to comment
Share on other sites

So, like, put all the data to a file as a string of 0s and 1s, (or 0-1-2-3s) and GET that data byte by byte? I feel like all the I/O would make it even slower compared to keeping it in the program, no?

 

I'm 'printing' a 160x8 header and four 32x32 objects (from a library of about 16). The objects change.

Link to comment
Share on other sites

No - for a file I mean having the data as it's raw, native value.

 

Atari bitmap like many old computer uses packed (chunky) pixels.

So a byte might have bits set like:

0 0 0 1 1 0 1 1

Example there would be 4 pixels with colours 0, 1, 2, 3.

Storing the raw data is the most efficient way aside from compression (ignoring procedural generation techniques)

 

Link to comment
Share on other sites

So, what I don't understand is how to take a byte like that and, in FastBasic, extract the bits so I can plot them in the right colors.

 

That number you gave me (four pixels) is 27. But I don't know what to do with that 27. I know I can read a bunch of 0s and 1s from a DATA, COLOR Z and PLOT X,Y. But I don't know how to get the "27" there into a form I can use and how to use it.

Link to comment
Share on other sites

What is your display list currently? I'm assuming it's set to a Graphics mode? If so then it has a pointer to memory that is ready for data to be interpreted as pixels.

 

Just load your data into that area of RAM and it will be displayed. The bits that are set will choose which color register to display (depending on the graphics mode).

Link to comment
Share on other sites

4 hours ago, phoney said:

Because whenever I try that the location is wrong.

The screen memory is PEEK(88)+PEEK(89)*256 (sorry, don't use FB, so don't know if it does a DPEEK)

 

each line in GR.7 is 40 bytes, so to calculate a pixel you need to PEEK the location, mask out the pixel you

want to insert, then OR in your new pixel with the colour you want.

 

So for a given X,Y coordinate, you multiply the Y by 40 then add the X/4 to get the screen byte.

 

pixels are as follows in a byte, bits 7&8 are pixel 0 6&5 are pixel 1 4&3 pixel 2 and 1&0 are pixel 3, this is for all bytes.

Link to comment
Share on other sites

Now if I have like 16 of these objects, and they're 1K each, can I even encode them in my program, or do I need to write a bunch of 1K files to disk and read them in as needed?

 

I also have a weird Axlon board in my computer but the idea of bankswitching memory is making my head explode.

Link to comment
Share on other sites

1 hour ago, phoney said:

OK. So, do you think I should be putting a bunch of long DATA statements in here, or creating some 1K files on the disk and reading them byte by byte when I need the graphic?

You could always store your data in strings, again if you have the space, that way each character only uses 1 byte where as each

DATA statement uses 6 bytes for the first element and a further 3 or 4 bytes for each extra item on the line.

 

I've used that method in a fruit machine game I wrote that needed a custom character set and stored the new set in several strings

and extracted the data from the strings at run time.

Link to comment
Share on other sites

Hi!

10 hours ago, phoney said:

OK. So, do you think I should be putting a bunch of long DATA statements in here, or creating some 1K files on the disk and reading them byte by byte when I need the graphic?

 

There are advantages and disadvantages to each option:

- If you put the data inside your program, you can generate a single binary file that will load and run, this is easier to program and easier to distribute.

- If you put the data as files in a disk, you can have a lot more data, as only the objects that you need would be in RAM. This will allow for more content/levels/objects, but not all at the same time.

 

This is an example of fast drawing your image using inline DATA and MOVE (much faster than copying individual bytes):

 

' Image Drawing Example
' ---------------------

' Image Data, 32 * 28 pixels, 4 pixels per byte, 224 bytes total:
DATA Image() Byte = 0,0,23,255,255,245,0,0,0,1,109,85,85,94,80,0,
DATA Byte = 0,26,171,85,85,122,164,0,0,106,170,213,85,234,169,0,
DATA Byte = 0,170,175,255,255,250,170,0,1,170,191,255,255,254,170,64,
DATA Byte = 2,170,255,255,255,255,170,128,6,171,255,255,255,255,234,144,
DATA Byte = 6,167,255,255,255,255,218,144,10,171,255,255,255,255,234,160,
DATA Byte = 26,167,255,255,255,255,218,164,26,167,255,255,255,255,218,164,
DATA Byte = 26,167,255,255,255,255,218,164,21,87,255,255,255,255,213,84,
DATA Byte = 0,7,255,255,255,255,208,0,0,7,255,255,255,255,208,0,
DATA Byte = 0,7,255,255,255,255,208,0,0,7,255,255,255,255,208,0,
DATA Byte = 0,7,255,255,255,255,208,0,0,7,255,255,255,255,208,0,
DATA Byte = 0,7,255,255,255,255,208,0,0,7,255,255,255,255,208,0,
DATA Byte = 0,7,255,255,255,255,208,0,0,7,255,255,255,255,208,0,
DATA Byte = 0,7,255,255,255,255,208,0,0,7,255,255,255,255,208,0,
DATA Byte = 0,7,255,255,255,255,208,0,0,5,85,85,85,85,80,0

' Set Graphics mode 7+16 (160x96)
GR. 7+16

' Loop forever:
DO
  ' Generate a new random position:
  PosX = RAND(160-32)
  PosY = RAND(80-28)

  ' Draw the image
  @Draw PosX, PosY
  ' Wait half a second
  PAUSE 30
  ' Erase the image
  @Erase PosX, PosY
LOOP

' Draws the image at X,Y coordinates:
PROC Draw Draw_X Draw_Y
Draw_Src = &Image
  Draw_Dst = DPeek(88) + Draw_Y * 40 + Draw_X / 4
  FOR I=0 TO 27
    MOVE Draw_Src, Draw_Dst, 8
    Draw_Src = Draw_Src + 8
    Draw_Dst = Draw_Dst + 40
  NEXT
ENDPROC

' Erase the region at X,Y coordinates:
PROC Erase Draw_X Draw_Y
  Draw_Dst = DPeek(88) + Draw_Y * 40 + Draw_X / 4
  FOR I=0 TO 27
    MSET Draw_Dst, 8, 0
    Draw_Dst = Draw_Dst + 40
  NEXT
ENDPROC

 

9 hours ago, TGB1718 said:

You could always store your data in strings, again if you have the space, that way each character only uses 1 byte where as each

DATA statement uses 6 bytes for the first element and a further 3 or 4 bytes for each extra item on the line.

On FastBasic, DATA statements don't use space for the text representation, only for each actual byte of data - this means that they will use less memory than a string.

 

And if using the cross-compiler, the DATA can be included from a file instead of typed into the program.

 

Have Fun!

 

sample.xex sample.fb

Edited by dmsc
Attach program.
  • Like 2
Link to comment
Share on other sites

It's been a long time, but I used machine language routine that hooked into the DOS file input/output routines and loaded or saved from disk to/from computer memory at full disk access speed.  The routine was only 39 bytes long and I stored it in a string variable called IO$.  I used it in my program "Space Station Multiplication" featured in Antic magazine.  It loaded an 8kb picture and some animation frames into memory.  I had a second routine that moved the animation frames from high memory into the visible screen area.  Those routines sound like they might be just what you're looking for.  As to Fast Basic only supporting integers with values between -32768 to 32767, you do have a full 64k of values, just half of them are negative, internally one bit of the number is just used to interpret the number as positive or negative, so you should be able to just use negative numbers to represent the high values above 32k through 64k, they would have the same binary value internally.

Linked below you can find my original program if you wanted to take a look at it. I'd have no problem if you wanted to use the routines, but I don't have the docs on them anymore so it might take a little work to figure out the parameters used, it's been a long time but I might be able to help a little. 

 

http://www.atarimagazines.com/v9n2/spacestation.html

Link to comment
Share on other sites

17 hours ago, dmsc said:

Hi!

 

There are advantages and disadvantages to each option:

- If you put the data inside your program, you can generate a single binary file that will load and run, this is easier to program and easier to distribute.

- If you put the data as files in a disk, you can have a lot more data, as only the objects that you need would be in RAM. This will allow for more content/levels/objects, but not all at the same time.

 

This is an example of fast drawing your image using inline DATA and MOVE (much faster than copying individual bytes):

 

' Image Drawing Example
' ---------------------

Thank you! I will use MOVE!

How much room do I have on a 48K machine for actual program text, though? If I have, say, 16x256 byte items, do the DATA statements alone use up so much space that I'll run out of RAM for my program logic when using the IDE?  At the moment I'm taking the 'write it to a file, read the object I need from the appropriate file" approach. Although I could just read ALL the objects in from one big 4K file at boot ... can an array have 4096 elements?

I am writing this on the 800 because I can't get the Fujinet emulator working on my other computers. Also, I just want the 'real' 800 experience. By the way, 48K 800 + LiteDos + N: driver + FB.COM works just fine.

 

 

17 hours ago, dmsc said:

 

Link to comment
Share on other sites

Hi!

On 12/20/2023 at 5:35 PM, phoney said:

How much room do I have on a 48K machine for actual program text, though?

About 31KB with the integer IDE - enough for a really big program. And about 32KB with the command line compiler (FBC.COM)

 

On 12/20/2023 at 5:35 PM, phoney said:

If I have, say, 16x256 byte items, do the DATA statements alone use up so much space that I'll run out of RAM for my program logic when using the IDE?

No. 16x256 = 4KB of data in the executable, the DATA statements will be 16KB of text, this will fit in RAM.

 

IMHO, start using DATA and switch to other methods when/if your program gets too big. Perhaps at that point I will have implemented the support for including DATA from disk in the IDE :) .

 

On 12/20/2023 at 5:35 PM, phoney said:

  At the moment I'm taking the 'write it to a file, read the object I need from the appropriate file" approach. Although I could just read ALL the objects in from one big 4K file at boot ... can an array have 4096 elements?

Yes, a byte array can use up all memory.

On 12/20/2023 at 5:35 PM, phoney said:

I am writing this on the 800 because I can't get the Fujinet emulator working on my other computers. Also, I just want the 'real' 800 experience. By the way, 48K 800 + LiteDos + N: driver + FB.COM works just fine.

Great!

 

Have Fun!

Link to comment
Share on other sites

Hi!

27 minutes ago, phoney said:

Okay, so why isn't this working? It's putting stuff to the screen but not the same stuff in the same order as I see in the array.

 

Because you are using a WORD array, not a BYTE array, so each array member takes two bytes.

 

Also, it is way faster to read the data with BGET:

 

DIM CLTHIMG(2816) BYTE
OPEN #1, 4, 0, "D:SWEATER.DAT"
BGET #1, &CLTHIMG, 8*32
CLOSE #1

GR.7
COLOR 1

 

Have Fun!

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...