Heya,
I have been playing for a while with 6502 assembly and namely on Apple ][. Presently I got curious about how vertical position would be calculated in hires. Yes, some uses tables and got one of my own for both hires and text/lores. However hires table is created in basic, and I am more curious about calculating it without using table. Namely calculating with assembly and that horrible 8 bit register. Google didn't give out pure math (read none at all).
Unless somewhere in memory is table used by basic's hires graphics function, in which case that table will be handy. Didn't find anything resembling such table however, but would be memory saver if such thing exist.
If you are curious what I am doing right now, it is actually trying put up two functions. Hires versions of hlin and vlin. Byte accurate versions, not pixel. I am working with something? Well, won't give out details until all required snippets are gathered... nope...
You might want to look at the GBASCALC routine in the Monitor ROM ($F847).
Actually are you sure that one is right address, coz all results seem be pointing to text memory address. Plus only PLOT seem be calling it, not HPLOT. Kinda useless, as basic already has VLINE and HLINE for LORES, but I am working with HIRES and looking to create similar call functions with assembly. HPLOT is both far too slow and don't need pixel accurate function. Just byte accuracy for right results...
As I recall, you could transpose a few bits in the Y coordinate, mulitply by 40, and then you should have it.Except that I think there might be some skip bytes at the end of every so many lines, which complicates things. Can anyone shed some light on this?
Back in 1989-90 I was experimenting with the 160x192x16 mode provided by the A2E AppleColor RGB card (not standard DHR). I didn't know where the ROM calc routines for HIRES lived back then and I wrote some assembly to compute a screen memory value from an X,Y coordinate pair. For the Y values, it's still 0-191, so the algorithm doesn't change. There are (of course) lots of intersting patterns in the memory layout of Hires... Here's the basic gist of how I did it (which probably isn't the *best* way, mathwise, but it worked):
The low byte of the destination screen memory address starts as $00.
First, take the Y coord and divide it by 8. This gives a value of 0-23. If that value is odd, add $80 to the low byte of the destination screen memory address.
If Y/8 is >7, add another $28 to the low byte of the destination address.
If Y/8 is >15, add another $28 to the low byte of the destination address.
The high byte of the destination address starts as $20.
Take Y/8 Modulo 8 (0-7). Divide by two (0-3). Add this to the high byte of the dest address.
Take Y Modulo 8. (0-7). Multiply by 4. Add this to the high byte of the destination address.
You now have the memory address for the start of the row.
The picture of the hi-res memory layout at https://www.xtof.info/hires-graphics-apple-ii.html (which I believe was similar to what was shown in one of the books that came with the RGB card) helps visualize what's going on with the math.
I can provide my source code if you wish, but working through it to reverse engineer the algorithm I see that there are several things that could be improved that I did the hard way (I was 13/14 years old at the time!)... and to be quite honest, a table-based lookup is going to be much, much faster and simpler than trying to do all the math.
REM HOW TO CALCULATE THE HIRES ADDRESSREM GIVEN THE COORDINATE OF A PIXELhttps://mmphosis.netlify.app/hires/
The routine you're looking for is in Applesoft at $F411, called HPOSN.
Screenshot 2026-10-11 at 19.28.33.png
I think the brute-force table lookup of the previous post may be the fastest way to get the HIRES line begin address much quicker than Woz' method, but IMHO the table is waste of memory and the whole scheme is useless for software sprites, because these would be too slow even with the lookup table method, which would need to be run for each line of the sprite while the sprite is being rendered on the screen.
A much faster (and even more memory gobbling) way is to code a 'sprite slide' like this:
LDA (SPNT),Y
ORA LINEAD,X
STA LINEAD,X
INY
.... repeat this code for 192 times. Prior to calling into this slide, set SPNT to the begin of the sprite bit map, X to the byte index (0....39), Y to zero, and calculate the entry and exit address into that slide, depending on the y coordinate. The exit address would be the INY instruction after the last line of the sprite bit map. Use evil self-modifying code to replace this INY with a RTS. Then do a computed JSR to the entry address which is the LDA (SPNT),Y of the first y-coordinate (the scn line number) where to put the first line of the sprite (Y = 0 for this first line).
Of course the actual bit shuffling which is just a "ORA" can be more sophisticated, i.e. using another pointer to a mask, but this costs time and slows the sprite engine down. I think that sprites can be designed and placed such that if the same type of sprite does overlap, it still will have the right colors. So no mask is needed. If you want a mask, the code snippet above must be changed to:
LDA LINEAD,X
AND (MPNT),Y
ORA (SPNT),Y
STA LINEAD,X
INY
where MPNT is the pointer to the sprite mask.
I'm currently into this topic because I code the driver software for my Apple-1 Color Graphics card, and sought the fastest possible software sprite rendering code which still is universal enough. The code for the sprite slide is generated automatically and every block has the right LINEAD which is calculated once during auto code generation and so it does not need any speedup tricks like the table lookup method of the previous post.
Comments invited !
(Oh, and if you know of some open source code to turn a sprite definition into all the slices for all possible x-coordinates, please show me where it is to be found. I could write that stuff myself but why reinvent the wheel ;-)
- Uncle Bernie
Something about the "slide" reminds me of Duff's Device, which of course is just a way to write such a low-level structure in a high-level language.
One interesting reference about all this is at https://github.com/AppleWin/AppleWin/wiki.
There they mention a better routine, not in ROM, produced later by Woz himself.
Sometimes you would like a simple one line formula whether fast or not, in Integer BASIC it can be written
ADDR = 8192*P + YMOD8*1024 + YMOD64/8*128 + Y/64*40
where P is the page, either 1 or 2. Another way to write the third term is Y/8MOD8*128
It can be done similarly in Applesoft but there will be some ugliness with INT to handle lack of MOD and truncate FP division.
If you are just updating 8-row tiles then a hybrid scheme works well where you tabulate only those lines with YMOD8=0. Then the in-between lines are filled in with a simple ADC #$400. This is a compromise that is reasonably fast and doesn't require the full table.
I have tried using self-modifying code to squeeze a little more out of the loops. The idea is that direct beats indirect, so instead of creating a pointer, modify a direct address somewhere during an init phase: maybe you gain something. Of course doing away with the row loop altogether as in UB's post above is even better, if you can spare the memory.