Jump to content
IGNORED

Atari Basic graphics handling routines


gtkakega

Recommended Posts

Anyone have the source code for Atari Basic graphics handling routines for graphics mode 8? I'm curious how the plot and drawto statements are implemented for a graphics mode 8 screen (i.e., manipulation of screen bytes considering 320x192 pixels is actually 40x192 bytes). There must be an algorithm for manipulating screen bytes when using plot and drawto statements.

Link to comment
Share on other sites

Anyone have the source code for Atari Basic graphics handling routines for graphics mode 8? I'm curious how the plot and drawto statements are implemented for a graphics mode 8 screen (i.e., manipulation of screen bytes considering 320x192 pixels is actually 40x192 bytes). There must be an algorithm for manipulating screen bytes when using plot and drawto statements.

 

Actually, the graphics routines are in the OS, not BASIC. You can get the OS source listing here:

 

http://homepage.ntlworld.com/kryten_droid/...0050912.lst.zip

 

...or buy the "Atari 800 Technical Reference Notes" from B&C Computervisions, http://www.myatari.com (part number BKA046).

 

Either way, the actual drawing code is near the end of the listing (search for the string "BASKETBALL", or look on page 120 of the listing).

 

Actually, if you know the Atari fairly well and can read 6502 code, I'd recommend reading the whole listing, start to finish. It'll take a while, but you'll end up understanding a lot of things that were mysterious before.

Link to comment
Share on other sites

Here's the C source to a plot routine I wrote for gr.8 screens as part of a very early cc65 atari graphics library:

 

/* PLOT2CLK.C  - Plot 2 color lookup tables
*
* Atari Graphics Library
* Shawn Jefferson
*
* September 8, 2003
*/

const unsigned char plot2cmask[8]  = {128,64,32,16,8,4,2,1};


/* PLOT2CLN.C  -  Plot function, 2 color mode, no clipping
*
* Atari Graphics Library
* Shawn Jefferson
*
* December 11, 2002
*/

#include <atari.h>
#include "atarigfx.h"



/* plot_2colmode_nc
*
* Plots a point on the bitmap using the passed in color register.  This
* function does no clipping, so you have to watch the parameters you pass
* in.
*/
void __fastcall__ plot_2colmode_nc(BITMAP *bmp, unsigned int x, unsigned int y, unsigned char creg)
{
 unsigned char bit;
 unsigned char data;
 unsigned int index;


 bit  = (x % 8);
 index = (bmp->bpl * y) + (x / 8);

 data = bmp->dat[index];

 if (creg == BAKCOL(bmp->mode)) {			  // background color?
data &= ~plot2cmask[bit];				   // clear pixel instead
 }
 else
data |= plot2cmask[bit];					// set pixel

 bmp->dat[index] = data;
 return;
}

 

First thing I did was calculate the bit we were interested in and the index into the bitmap (the library passed small structs around with a pointer to a bitmap that was drawn onto.) bmp->bpl was a value that corresponded to Bytes Per Line and is usually 40 for a regular size Gr.8 screen. Then I determined whether we are setting or clearing the pixel and then either ORed it or ANDed it with the reverse of the bitmask. Then write the byte back to the bitmap. I imagine the OS is doing something very similiar.

 

Certainly not an optimized fast drawing routine, but it's in C code so it's readable enough.

Edited by Shawn Jefferson
Link to comment
Share on other sites

The OS routines are pretty slow, mainly because (a) they have to be space efficient, (b) they have to serve for every graphics mode, © all the CIO overhead.

 

Imagine, for OS GR. mode 8:

Probably one of the most efficient ways of doing a PLOT for a given graphics mode is to have a table for every value of Y, which contains an entry for the screen address corresponding to (0,Y).

The table is best stored with all the low bytes followed by all the high bytes.

 

Then to PLOT X,Y you just fetch the table value and store it into a pointer.

Then use X DIV 8 to get the address offset into the line for the pixel we want. 3 LSR instructions give DIV 8.

 

Use X AND 7 to work out which pixel within the byte is to be manipulated. Have 2 tables containing mask and OR values to set a pixel.

 

Mask table would contain $7F, $BF ... $FD,$FE.

OR value table contains $80,$40 ... $02,$01.

 

Then to set a pixel, just get AND the existing data with the mask data then OR with the second tables entry. To reset a pixel, just skip the second step.

To toggle a pixel, just use EOR instead of the OR operation.

 

Writing assembler code to perform a PLOT or DRAWTO is fairly straightforward - the OS manual has an excellent pseudo-code explanation of DRAWTO. A well written routine would be at least 3 times as fast as the built in ones.

 

But you're looking at an overhead of probably around 800 bytes for your own routine (of which nearly half would be tables).

Edited by Rybags
Link to comment
Share on other sites

 index = (bmp->bpl * y) + (x / 8);

 

Wouldn't it be faster to have

 

 index = (bmp->bpl * y) + (x >> 3);

 

Yes, if you compile with -Osir you get optimizations, and this is one of them. Here's an exerpt from a small test using the command-line

cl65 -t atari -Osir --listing -T test.c

 

00000Cr 1			 ; x = (x / 8);
00000Cr 1			 ;
00000Cr 1  4A		   	lsr	 a
00000Dr 1  4A		   	lsr	 a
00000Er 1  4A		   	lsr	 a
00000Fr 1  91 rr			sta	 (sp),y

Edited by Shawn Jefferson
Link to comment
Share on other sites

you can use the USR command in basic to start a ML routine.

 

but you should remember that you have to pull the parameters from the stack.

 

f.e. if you have a plot routine A=usr($0600,xp,yp)

 

x,y are saved on the stack as well...

 

so... you have to do in your ML subroutine

 

PLA ;to get the amount of parameters OS put on stack

PLA ;hi byte of YP

PLA ;lo byte of YP

STA YP

PLA ;hi byte of XP

STA XP+1

PLA ;lo byte of XP

STA XP

...

 

i hope you get it.

Link to comment
Share on other sites

Yes, inline assembler is easy to use with CC65. Check out the ASM keyword. Of course, with cc65 you wouldn't be using basic at all, so the USR() discussion doesn't apply.

 

So, it has to look like this:

 

asm("

PLA ;to get the amount of parameters OS put on stack

PLA ;hi byte of YP

STA YP+1 ;(you forgot :-) )

PLA ;lo byte of YP

STA YP

PLA ;hi byte of XP

STA XP+1

PLA ;lo byte of XP

STA XP

");

 

? But how does the assembler know, that the YP = &YP in C?

Edited by atarixle
Link to comment
Share on other sites

You need to have asm("") around every keyword. For the variable, there are options to the asm() keyword that will let you match a C variable with the assembler symbol..or you can just use the name of your variable prepended with a "_'. So

 

int x;

 

int foo( void )

{

asm("inc _x");

return x;

}

 

Wouls work. Note that the variable must not be a local variable, it must be a file level global.

Link to comment
Share on other sites

  • 2 weeks later...

You need to have asm("") around every keyword. For the variable, there are options to the asm() keyword that will let you match a C variable with the assembler symbol..or you can just use the name of your variable prepended with a "_'. So

 

int x;

 

int foo( void )

{

asm("inc _x");

return x;

}

 

Wouls work. Note that the variable must not be a local variable, it must be a file level global.

 

With a local variable you use "%o", which gives you the offset from the current C stack pointer.

 

 int x;

 asm("ldy #%o", x);
 asm("sta (sp),y);

Link to comment
Share on other sites

Anyone have the source code for Atari Basic graphics handling routines for graphics mode 8? I'm curious how the plot and drawto statements are implemented for a graphics mode 8 screen (i.e., manipulation of screen bytes considering 320x192 pixels is actually 40x192 bytes). There must be an algorithm for manipulating screen bytes when using plot and drawto statements.

 

I have a book that has the basic source code included.

Link to comment
Share on other sites

  • 8 months later...

Interesting stuff here. I am looking for a faster way to draw lines in assembly. I tried the CIO calls from assembly language and quickly discovered I cannot make things go not much faster than Basic. One of the reasons why I avoided doing bitmap type screen games for so long is because if it requires a lot of line drawing, it takes will not be much faster than Basic. I have to examine that Really Unreal line drawing source. Another limitation the OS had is the graphic routines cannot adapt for overscan (48 bytes wide) or a taller displaylist (200 or more lines).

 

What graphics mode does that above source work with anyway? I am looking for something that works with a graphics 15 screen. I cannot figure out what mode it works with.

Edited by peteym5
Link to comment
Share on other sites

I guess we are all doing things pretty similarly. Here's the code for the pixel plotting routine in Rasteroids:

 

bitmask		.byte 128,64,32,16,8,4,2,1	 


 ldx pixel_y
 lda scrnOffLo,x	  
 sta 205
 lda scrnOffHi,x
 sta 206				 

 lda pixel_x
 and #7
 tax
 lda pixel_x+1		  ; divide x position by 8 to get dest byte offset 
 lsr
 lda pixel_x			 
 ror				 
 lsr				 
 lsr 
 tay
  
 lda bitmask,x
 eor (205),y
 sta (205),y			;store altered screen byte

 

Pretty much exactly as Rybags described. There is actually a little bit of code before this to check to make sure the x, y values are within screen bounds but I only added this recently to support the "pulse bomb" powerup. If anyone sees any possible optimizations (and I'm sure you will) please let me know.

 

tjb

Link to comment
Share on other sites

actually I am looking more for a drawto or a direct way to draw a line between 2 sets of coordinates in 4 color mode. thanks anyway. I might later adapt the line drawing routine to work with a graphics 15 screen or figure out another way of duplicating the OS drawto routine. Maybe I can find the original inside the OS somewhere and see how that was put together.

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...