Jaymzroo's
Lesson 1: 86 Find Pixel routine
Please email me with any mistakes!
Anyone who has programmed the Ti-85 or Ti-86 calculators in Assembly, most
likely know about the VIDEO_MEM ($fc00 in both cases, 85 or 86). If you have
used it you know it can be hard to find just one pixel since 8 pixels are
stored in one byte, each pixel getting a corresponding bit in the byte.
Well, on the 85 one needs only to type "CALL_(FIND_PIXEL)", however on the
ti-86, there is no ROM routine to find the right byte for you (as far as I
know). For the 85 authors that want to know how that command works, and for
the 86 authors who would like to know, and have a routine at hand, I will try
to explain it in "normal-people-english".
First of all you need to know the basic concept of how it works. Since there
are 16 bytes across the screen in each row, and 8 pixels stored in each byte,
it is simple to find a pixel, though it may look wierd. You just multiply the
y axis coordinate by 16 (because there are 16 bytes in each horizontal row),
and divide the x axis coordinate by 8, since there are eight pixels in one
Byte, then add the results together to find what byte to change. If you
dont understand you better think about it hard, cause its the basis for the
entire routine.
To begin, you must know how to divide and multiply in binary. Since 16 and 8
are powers of 2, it makes it extremely simple. To multiply by a power of 2,
just add together your operand, for example:
< 5 * 64 = 320 > so... || < 4 * 16 = 64 >
ld hl,5 || ld a,4
add hl,hl | 5*2 = 10 || add a,a
add hl,hl | 10*2 = 20 || add a,a
add hl,hl | 20*2 = 40 || add a,a
add hl,hl | 40*2 = 80 || add a,a
add hl,hl | 80*2 = 160 || a = 64
add hl,hl | 160*2 = 320 ||
ok that is pretty obvious and simple. Now lets divide by powers of 2, not
that much harder. Just use the SRL command. It inserts a 0 in the bit 7
and shifts everything to the right, dividing by 2. If you understand this you
can go to the example. Otherwise, think of the number 100 in decimals. If you
shift it to the right one place, it is dividing by 10. 100->10. Because
decimals are based on 10. Binary, based on 1's and 0's, when rotated acts the
same as dividing by 2.
For example...
< 16 \ 4 = 4 >
ld a,16 16=%00010000
srl a 8=%00001000
srl a 4=%00000100
a = 4
heres one that doesnt come out perfectly
< 50 / 8 = 6 remainder 2 >
ld a,50 %00110010 =50
srl a /2 %00011001 =25
srl a /4 %00001100 =12
srl a /8 %00000110 =6
a now equals 6
Youre probably thinking, "8 times 6 doesn't equal 50??". True, where is the
remainder? In the bits that were rotated out the LSB (least significant bit)
side of the bite. Hmm... The first time, from 50 to 25 a "0" came out, a "1"
the second time and a "0" the third. Well, if you mask out the last 3 bits
from the operand before you even start, you know the remainder! so,
ld a,50 ;50 = %00110010
and %00000111 ;cause you know youre dividing by 8 before you start.
ld e,a ;now E holds the remainder, in this case 2 (%010)
Now, If you dont understand the part before this you better test it out on
your own. Try it for yourself, its the best way to learn.
If you did understand this, then go down to to routine and see if you get it
yet.
The routine takes the Y coordinate ("C") and multiplies that by 16, since
every row down you jump is equal to 16 bytes. Then it takes the X coordinate
("B") and divides it by eight since there are eight pixels stored in each
byte. Then it adds the two results, which is The byte that contains your
desired pixel in its eight bits. Then it takes the remainder of dividing the
X axis number and finds the corresponding power of two, so that if it is the
first pixel in the byte, A will look like %10000000, if its bit 0 that has
the corresponding pixel it will look like %00000001, and so on. If you dont
quite understand this, look over the routine and/or go back and read it again.
<---------------------------------------------------------------------------->
THE ROUTINE by James Rubingh
<---------------------------------------------------------------------------->
Fpixel: ;calculate the byte, and A as a power of 2
ld a,b
and 7
ld e,a ;there exist a simulated 16 bit addition used in
ld d,0 ;the EBLE YOPP findpixel routine, its a few clock
ld hl,offsets ;clock cylcles faster, but not as easy to understand
add hl,de ;It is far superior though
ld a,(hl)
ld l,c ;There is another way to do this that uses the
ld h,0 ;RLD command. That command will Multiply the
add hl,hl ;byte at hl by 16 and add A to the result
add hl,hl ;all by itself. (eble yopp findpixel routine)
add hl,hl
add hl,hl
srl b
srl b
srl b
ld e,b
ld d,0
add hl,de
ret
offsets: .db $80,$40,$20,16,%00001000,%00000100,%00000010,%00000001
/\
||
||
All different powers of 2
I would also like to point out that this code above will only find the offset
To the correct bit FROM 0. This means that if you want to find a bit in the
Graph memory, you would need to add $fc00 to the offset given by this routine.
To find an offset to the bit in the GRAPH_MEM, then you would just add
GRAPH_MEM to the offset to find a pixel in the Graph_mem. If you dont
understand this, then i dont think that you understand how the FIND_PIXEL
routine works. You can find simple examles of this in almost any game. One
thing to look for is that the author may use 'ld a,h \ or $FC \ ld h,a'
instead of loading $fc00 into DE and adding that to hl, it does the same thing.
You can see a prime example of this in the EBLE-YOPP routine.
+--------------------------------------------+
| Jaymzroo@juno.com |
| http://members.tripod.com/~jaymzroo |
+--------------------------------------------+