In this article, which is pretty much aimed at newbies, I'll tell you how to plot points on the screen, which you need if you're going to do stuff like plotters (obviously), vector graphics etc. I won't discuss going into effects very much here, though.
First of all you have to decide what kind of area you want to plot into. The most common seems to be an area of 16x16 chars, which is probably because plotting into a charset is very easy and fast (this gives you and area of 128x128 pixels). In some situations you might want to plot into a hires bitmap, which is a bit slower, or sprites, which can be handy if you want to move the plotting area around, or if you want to be able to expand it.
Please notice that the example code is written from the top of my head, so it might not work, but I hope it does. :) It's not there to be copied, but to give you an impression of what it should look like.
I'll go through routines for all of these 3 alternatives in this article, and I'll start with the simplest one: the 16x16 chars area.
PLOTTING INTO A CHARSET
For this one to be fast, you need the chars laid out in the correct way. If you think about it a bit, you'll realize that you want to line up the chars vertically (in the upper left corner you have char 0, below it char 1, below that one char 2 and so on, and to the right of char 0 you'll have char 16 ($10), below that one char 17 ($11) and so on). With this layout, the bytes to plot into will be indexable by the y coordinate, as you'll see in the example code below.
To plot a point in this charset, you need to know 2 things: which address you should plot into, and what you should put there. The information you have is the x and the y coordinate. So what you have to do is to use these to find out which byte to plot into, and what to plot into it. For this you need 3 tables: the x low table, the x high table and the table which tells you what to plot. You don't need any y table, because the y coordinate will just be used as an index, based on the address you put together from the x tables.
Let's say your charset is located at $2000. If you're going to plot a point at (0,0) (x coordinate 0, y coordinate 0), you want to put the value $80 (bit 7) into address $2000. For (4,4) you want to put the value $08 (bit 3) into address $2004. So what should the tables look like?
The x high table holds the high byte of the address that corresponds to a certain x coordinate, with the y coordinate being 0. So it'll start with $20, $20, $20, $20 (16 of those, as the first 32 chars are used for the first two columns of chars), then $21, $21, $21 (16 of those too) and so on. The x low table holds the corresponding low byte of the address, and starts with $0, $0, $0 (8 of those), then $80, $80, $80 (8 of those too) and then it starts over with 8 instances of $0, 8 of $80 etc.
let's take an example: let's say you want to plot a point into x coordinate 42 ($2a). On index $2a in the x high table you'd find $22, and in the x low table you'd find $80, and putting them together gives you the address $2280. Just add the index for the y coordinate to that address, and you have the address to plot into.
The only thing that remains to explain is how to find out what to plot. That's very simple as well: the three low bits of the x coordinate have this information. So you just use those as an index into the table $80, $40, $20, $10, $08, $04, $02, $01. Repeat that sequence throughout a whole page (so that you don't have to and out the other bits of the x coordinate) and you're done.
The code will look something like this (assuming we have the x coordinate in the x register and the y coordinate in the y register):
lda xlo,x
sta $fe
lda xhi,x
sta $ff
lda plottab,x
ora ($fe),y
sta ($fe),y
Pretty simple, huh? Sure it is! The only thing not explained above is why we're using ora and then sta, not just sta. Well, if you've already plotted a point into a byte, and then you plot another one into the same byte, you don't want the first plot to get erased, right?
PLOTTING INTO A HIRES BITMAP
If you've understood the previous section, you should be able to figure this one out yourself, but I'll give you some hints anyway. The plottab is exactly the same here, of course, you still use the three low bits. Finding the address to plot is a bit more complex, though.
One technique to use is this one: use the y coordinate to find the start of the line to plot into, then add the high part of the x coordinate, multiplied by 8. For this to work, you need a high and low y table. The addresses to the leftmost bytes of a hires bitmap (at $2000) are $2000, $2001, $2002, $2003, $2004, $2005, $2006, $2007, $2140, $2141, $2142 etc. So, first there are 8 consecutive addresses, then you add $0140 to the first address and keep going.
So the y high table will start with $20, $20, $20, $20 (8 of those), then 8 instances of $21, 8 instances of $22, 8 of $23, 8 of $25 (no, that's not a typo) etc. The y low table will start with $00, $01, $02, $03, $04, $05, $06, $07, $40, $41, $42, $43, $44, $45, $46, $47, $80, $81, etc.
Now, the x address will need to use 2 bytes, because the coordinates range from $00 to $140 (as a hires bitmap is 320 bytes wide). These 2 bytes can be used in different ways, of course. The most appropriate might be to have the 3 low bits in one byte and the 6 high bits in another byte, but we'll go for the general solution here, and assume that the x coordinate consist of one byte with the low 8 bits, and another one with the high bit (so only 1 bit is used here).
Then the code would look something like this (with the x in xlo and xhi and the y coordinate in the y register, of
course):
lda xlo
and #$f8
clc
adc ylo,y
sta $fe
lda xhi
adc yhi,y
sta $ff
ldx xlo
lda plottab,x
ldy #$00
ora ($fe),y
sta ($fe),y
As you can see, this one will be a bit slower than the simple charset plotter above, which is why that one is more common.
PLOTTING INTO SPRITES
You should have grasped the basic concepts of plotting by now: use tables to find the byte to plot into and use the 3 low bits of the x coordinate to find out what to plot into the byte. So I won't go into plotting into sprites in detail, but just give you some hints and then leave it as an exercise to figure out the details.
Indexing into a bunch of sprites is a bit more complicated than a hires bitmap. But let's say you want to plot into 4x4 sprites. The first row of sprites will be $00, $01, $02 and $03, the second one $04 and so on. So the offsets for the x coordinates will be 0 for x coordinate 0-7, 1 for 8-15, 2 for 16-23, 64 for 24-31, etc. Then you need to add 3 to this address for each y coordinate step (i.e. 0 for y coordinate 0, 3 for y coordinate 1, 6 for y coordinate 2, etc.).
That doesn't work for y coordinates 21 and above, though, so you need another table for the additional addition there. This will be a direct addition to the high byte of the address you got for the x coordinate. You'll just add 1 to it for each multiple of 21 in the y coordinate.
You can probably figure out the rest on your own...
CLEARING
I should say something about clearing too, as you might want to clear the bitmap each frame too to get rid of the old plots and start over with an empty bitmap each frame. The brute-force way of doing it is to simply sta 0 into each address in the bitmap. This will take 8000 cycles for a charset, assuming you've unrolled the code, so that it looks something like this:
lda #$00
sta $2000
sta $2001
sta $2002
sta $2003
[...]
sta $27fe
sta $27ff
But it may take less time to use a table which you create while plotting. For each point you plot, you store the address in the table (or directly into speedcode). Then you only have to clear the bytes that you've actually plotted into. I think that's enough for now...
PUTERMAN/CIVITAS |