gtkakega Posted February 11, 2007 Share Posted February 11, 2007 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. Quote Link to comment Share on other sites More sharing options...
Urchlay Posted February 11, 2007 Share Posted February 11, 2007 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. Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 11, 2007 Share Posted February 11, 2007 (edited) I would imagine it involves ORing in a bit mask...if you take the pixel x-coord mod 8, that will give you the bit you want to set. Dividing by 8 will give you the byte. You could either have a pre-allocated mask table or you could just lsr a 1 that amount of times. Edited February 11, 2007 by danwinslow Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted February 17, 2007 Share Posted February 17, 2007 (edited) 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 February 17, 2007 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 17, 2007 Share Posted February 17, 2007 (edited) 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 February 17, 2007 by Rybags Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted February 17, 2007 Share Posted February 17, 2007 Rybags. thats how i have done most of my plot routines. and draw routines you can use the good old bresenham algorithm. you can find my source here. its not optimised and straight forward used in my intro "Really Unreal". http://web.archive.org/web/20041109220435/...eally_src2.html Quote Link to comment Share on other sites More sharing options...
atarixle Posted February 17, 2007 Share Posted February 17, 2007 index = (bmp->bpl * y) + (x / 8); Wouldn't it be faster to have index = (bmp->bpl * y) + (x >> 3); or optimizes cc65 this automaticly anyway? Quote Link to comment Share on other sites More sharing options...
gtkakega Posted February 18, 2007 Author Share Posted February 18, 2007 Thanks all! Now I have some resources to work with. I did find an article in the book Atari Graphics and Arcade Game Design (chapter which explains a similar approach to drawing in graphics mode 8. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted February 23, 2007 Share Posted February 23, 2007 (edited) 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 February 23, 2007 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
atarixle Posted February 24, 2007 Share Posted February 24, 2007 (edited) Is it possible to create ML-code to use with ATARI-BASIC? How can I set the start-adresse, if I want to create code for page six? Is there an optimizing-switch to create relocalable code? Edited February 24, 2007 by atarixle Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted February 24, 2007 Share Posted February 24, 2007 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. Quote Link to comment Share on other sites More sharing options...
atarixle Posted February 24, 2007 Share Posted February 24, 2007 but you should remember that you have to pull the parameters from the stack. I think, I did this some years ago (or read about it, I have this nice "ATARI-Assembler" Book). But, how do I do this in cc65? Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted February 24, 2007 Share Posted February 24, 2007 (edited) inline assembler? but i am not a cc65 guru. Edited February 24, 2007 by Heaven/TQA Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 24, 2007 Share Posted February 24, 2007 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. Quote Link to comment Share on other sites More sharing options...
atarixle Posted February 24, 2007 Share Posted February 24, 2007 (edited) 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 February 24, 2007 by atarixle Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 24, 2007 Share Posted February 24, 2007 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. Quote Link to comment Share on other sites More sharing options...
atarixle Posted February 25, 2007 Share Posted February 25, 2007 aha, thank you! Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted March 12, 2007 Share Posted March 12, 2007 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); Quote Link to comment Share on other sites More sharing options...
whitman Posted March 13, 2007 Share Posted March 13, 2007 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. Quote Link to comment Share on other sites More sharing options...
peteym5 Posted December 11, 2007 Share Posted December 11, 2007 (edited) 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 December 11, 2007 by peteym5 Quote Link to comment Share on other sites More sharing options...
tjb Posted December 11, 2007 Share Posted December 11, 2007 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 Quote Link to comment Share on other sites More sharing options...
peteym5 Posted December 11, 2007 Share Posted December 11, 2007 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. Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted December 11, 2007 Share Posted December 11, 2007 With a line drawing routine, the horizontal case and the vertical case can be optimized, otherwise a Bresenham algorithm will work. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.