[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Hires calculations
[Note crosspost and followups to comp.sys.apple2.programmer]
<bobryan9@my-dejanews.com> wrote:
> How do I calculate the MEMORY LOCATION of a byte on the LEFT SIDE of the
> Hires screen, given the Y location?
With a rather complex calculation. I wrote one as part of a hi-res
graphics drawing program I wrote back in high school.
There is probably a CALL you could make into Applesoft BASIC to access
the internal routine, but here is the brute force and ignorance method.
The hi-res screen is divided into three bands, each of which has eight
sub-bands, each of which is eight lines.
The memory addresses start at 8192 ($2000), advance across the line,
then jump down to the middle third ($2028), advance across the line,
then jump down the bottom third ($2050), advance across the line, then
run off the screen for eight bytes ($2078 to $207F).
The next 128 bytes start eight lines below the first 128. This pattern
repeats eight times.
You are now $0400 bytes after the start of the screen, and the entire
pattern repeates one line below the previous pass. Repeat the whole
thing eight times and you reach the end of the screen.
In total, there are 192 lines. If you write out the line number in
binary, you can divide it into three fields:
Bits 7 and 6 select between thirds of the screen (a value of 3 is
illegal).
Bits 5, 4 and 3 select between blocks of eight lines.
Bits 2, 1 and 0 select between individual lines.
Call these fields C, B and A.
The formula for the start address of a designated line, relative to the
base address of the screen, is:
C * 40 + B * 128 + A * 1024
The tricky part is breaking the line number up into the three fields.
It is very easy in machine code, using shift and AND operations, but
BASIC can't do this efficiently.
The following code would work:
1000 REM Convert line number in Y into address in ADDR
1010 C = INT(Y / 64): TMP = Y - C * 64
1020 B = INT(TMP / 8): A = TMP - B * 8
1030 ADDR = C * 40 + B * 128 + A * 1024 + 8192
1040 RETURN
The assembly language version would go something like this (off the
cuff, and reasonably well optimised hence suitably cryptic, but
untested):
HBASCALC:
*
* Input:
* A register contains line number
* Zero page location HADDR contain high byte of start address of screen
*
* Output:
* Zero page locations HBASL and HBASH contain address of line.
tax ; Save line in X register
and #$C0 ; Extract bits 7 and 6
sta HBASL ; Save top bits multiplied by 64
lsr
lsr
ora HBASL ; Now have (bits 7-6 shift right 6) * 80
sta HBASL
txa ; Get the line back
and #$38 ; Extract bits 5, 4 and 3
lsr
lsr
lsr
lsr
sta HBASH ; Store (bits 5-4 shift right 4) * 128
ror HBASL ; Fix low byte, include bit 7
txa ; Get the line back again
and #$07 ; Extract bits 2, 1 and 0
asl
asl ; Now have (bits 2-0) * 1024
ora HADDR ; Set appropriate high order bits ($20 or $40)
ora HBASH ; and appropriate low order bits
sta HBASH ; Done!
rts
--
David Empson
dempson@actrix.gen.nz
Snail mail: P.O. Box 27-103, Wellington, New Zealand