Help loading GR, HGR, DGR AND DHGR image files in the Apple II

Genjoke

Tinkerer
Oct 31, 2021
67
40
18
Brazil - Rio de Janeiro - Flamengo
Hi folks.

Programs to encode modern images into Apple II-savvy formats are not new.

Digarok released a nifty utility to do so: Buckshot. I recently came to know about it in a YouTube video by @Javmast3r .

The application lets you convert images into 4 modes:
  • Low Resolution
  • Double Low Resolution
  • High Resolution
  • Double High Resolution
I was able to load the high-resolution ones.

High resolution:

Code:
 ? CHR$(4);"BLOADARCHIVE,A$2000 (or 4000 depending on the page)

Screenshot 2024-04-27 at 11.36.18.jpg
Screenshot 2024-04-27 at 11.33.02.jpg



For double high resolution it's a little bit trickier, but I managed to dig the net for the solution:

Code:
PR#3

POKE 49232,0: REM GRAPHICS
POKE 49234,0: REM FULL GRAPHICS
POKE 49236,0: REM PAGE ONE
POKE 49239,0: REM HI-RES ON
POKE 49246,0: REM DOUBLE HI-RES ON

POKE 49237,0: PRINT CHR$(4);"BLOADARCHIVE,A$2000,L$2000
POKE 49236,0: PRINT CHR$(4);"BLOADARCHIVE,A$2000,L$2000,B$2000


Screenshot 2024-04-27 at 11.40.20.jpg
Screenshot 2024-04-27 at 12.01.19.jpg



The problem begins when I try to load low-resolution images! Looking at the memory allocation map for the Apple II, it says that low-res graphics are allocated in the same place as text: 0400.

I tried BLOADARCHIVE,A$400 but I got nothing… I didn't even try to tap into Double Low Resolution!!!

Does anyone know the answer to this??

As always, Thank You!!!!
 
Last edited:
  • Love
Reactions: Javmast3r

joevt

Tinkerer
Mar 5, 2023
41
26
18
There's some info at https://en.wikipedia.org/wiki/Apple_II_graphics

Basically, the graphics pages have screen holes between some rows. The screen holes for HGR aren't used for anything so you can overwrite them without issue with a BLOAD.

The screen holes for GR are used by various things including the disk driver so you should not try to BLOAD there. Instead, BLOAD to some free memory space (maybe HGR space) then copy the bytes to GR space but skip the screen holes.

Below is some notes for translating line numbers in HGR or GR or TEXT to addresses. Basically, it uses some bit shifting or multiplying of parts of the line number to get the address.
Code:
Line addresses:                       reference COMPUTE! August 1983 pp. 172-177

Brief explanation of line number (eg 0-191) to line start address conversion
(eg $2000-$4000):

For text mode, the display is divided in 3 and each third is split in 8 rows. A row is a
character's vertical position. For HR and DHR, these are split into 8 character lines (the
height of a character is 8 pixels or hi-res lines).

                          vv-third (00,01,10)
text line # bits (0..23): ABCDE
                            ^^^-row in third 000..111

  LR line # bits (0..47): ABCDEF
                               ^-even/odd row in lo/hi nibble of byte

  HR line # bits (0.191): ABCDEFGH
                               ^^^-character line (0..7)

                                    111111 000 0000 000
                              bit#: 543210 987 6543 210
text or LR line start address bits: 0000pp CDE ABAB 000
        HR line start address bits: 0ppFGH CDE ABAB 000

pp = 01 for page 1, 10 for page 2.


For LR, if F is 0 then top even line of row, low nibble $0x for byte, else bottom odd line
of row, high nibble $x0 for byte.

The pattern ABAB 000 means each third is multiplied by 101000 = 40 which is the exact
number of bytes per row. It also means there are screen holes for the unused third (where
AB=11). The screen holes have addresses with pattern 0ppxxxxxx1111xxx for HR and
0000ppxxx1111xxx for LR. That's 512 bytes for HR and 64 for LR.

  1010000 last third (%10) start
+  100111 last byte of character line (39,$27)
= 1110111 last byte of last third (%10)
+       1
  1111000 first byte of unused third (%11)
+  100111 last byte of character line (39,$27)
=10011111 overflows into other address lines
- 1111111 max allowed in unused third (%11)
=  100000 amount of overflow (32)
          The unused third only has 40-32=8 bytes. Each third has 8 rows of characters.
          For HR, each character row has 8 character lines.
          8*8=64 unused bytes for text and LR. 8*8*8=512 unused bytes for HR.
[code]
 
Last edited:
  • Like
Reactions: Genjoke

joevt

Tinkerer
Mar 5, 2023
41
26
18
If you load the GR image to $2000, then this should be able to copy it to $400 (if my math is correct):
Code:
10 FOR Y = 0 TO 23
20 AB = INT(Y / 8)
30 CDE = Y - AB * 8
40 OFFSET = CDE * 128 + AB * 40
50 FOR X = 0 to 39 : POKE 1024+OFFSET+X,PEEK(8192+OFFSET+X) : NEXT
60 NEXT
But it's really slow because Applesoft BASIC uses floating point numbers and doesn't have integer arithmetic or bitwise operands.

https://www.calormen.com/jsbasic/reference.html
https://www.calormen.com/jsbasic/
https://www.scullinsteel.com/apple2/
 
  • Like
Reactions: Genjoke

joevt

Tinkerer
Mar 5, 2023
41
26
18
The COMPUTE! magazine issue I referenced is at internet archive and contains machine language for calculating HGR line address.
 
  • Like
Reactions: Genjoke

Genjoke

Tinkerer
Oct 31, 2021
67
40
18
Brazil - Rio de Janeiro - Flamengo
I think the problem is the Buckshot output.

I converted that heart image to a low-res image file.

Screenshot 2024-04-28 at 00.19.56.jpg


I then used the load at HGR and then transfering it to GR approach.

Using an assambly routine I got this:

Screenshot 2024-04-28 at 00.19.42.jpg


Using your BASIC program I got this:

Screenshot 2024-04-28 at 00.22.05.jpg


I think your program has some wrong value, but one can notice that both results suggest that the original file is saved in a different "order" as the horizontal lines are not loaded on the correct Y position.
 

joevt

Tinkerer
Mar 5, 2023
41
26
18
Using your BASIC program I got this:

I think your program has some wrong value, but one can notice that both results suggest that the original file is saved in a different "order" as the horizontal lines are not loaded on the correct Y position.

My program is correct. Change line 50 to write the line number as a character between A and X (1 to 24)
Code:
50 FOR X = 0 to 39 : POKE 1024+OFFSET+X,Y+1 : NEXT

What is the size of the binary created by buckshot? If it's 24 * 40 = 960 then it's not including screen holes. It might be saving the file with the lines in order (except with the lores pixels of the odd row numbers 1-39 mixed into the bytes of the even row numbers 0-38). If both are true, then line 50 should maybe be like this:

Code:
50 FOR X = 0 to 39 : POKE 1024+OFFSET+X, PEEK(8192+Y*40+X) : NEXT
 
  • Love
Reactions: Genjoke

Genjoke

Tinkerer
Oct 31, 2021
67
40
18
Brazil - Rio de Janeiro - Flamengo
50 FOR X = 0 to 39 : POKE 1024+OFFSET+X, PEEK(8192+Y*40+X) : NEXT

THIS ONE WORKED!!!!

I will now dig into the theory and try to understand it!

Thanks a lot!

The file created by Bucksot is indeed 960 bytes long.

Now the only one that I have to figure out is the Double Lo-Res! The binary is exactly the double: 1920 bytes.
 
Last edited:

joevt

Tinkerer
Mar 5, 2023
41
26
18
Seems like Buckshot is not saving DLO images correctly. In my source test image, the diagonal line reaches the bottom line. In the DLO result, the diagonal line doesn't reach the bottom line. It seems the image was stretched horizontally so that only 40 of the 80 pixels are represented. It looks like the first 40 bytes are for main memory and the next 40 bytes are for auxiliary memory.

Is the file saved to ProDOS image the same as the file saved as local binary?

Buckshut DLO test.png
 

Genjoke

Tinkerer
Oct 31, 2021
67
40
18
Brazil - Rio de Janeiro - Flamengo
Seems like Buckshot is not saving DLO images correctly. In my source test image, the diagonal line reaches the bottom line. In the DLO result, the diagonal line doesn't reach the bottom line. It seems the image was stretched horizontally so that only 40 of the 80 pixels are represented. It looks like the first 40 bytes are for main memory and the next 40 bytes are for auxiliary memory.

Is the file saved to ProDOS image the same as the file saved as local binary?

View attachment 16372
That explan the odd results I was getting in PRODOS!

indeed I got a stretched image, but both horizontally and vertically. I could only fill the screen with the upper left quadrant of the image.
 
Last edited: