10 Home
Michael edited this page 2016-01-15 17:38:08 -08:00

Welcome to the AppleWin wiki!

HGR

= HGR Y to Address =

Given:

y = abcd efgh   (Range 0 .. 191 = $00 .. $BF)

Address of the scanline is calculated via:

    ---- ---- abcd efgh   INPUT: Y
    ---- ---- ---- -fgh   &7
    ---- -fgh ---- ----   * 0x100
+   ---f gh-- ---- ----   * 4

    ---- ---- abcd efgh   INPUT: Y
    ---- ---- ---a bcde   y/8
    ---- ---- ---- -cde   & 7
    ---- ---- -cde ----   * 0x10
+   ---- --cd e--- ----   * 8

    ---- ---- abcd efgh   INPUT: Y (64 = 2^6)
    ---- ---- ---- --ab   y/64
    ---- ---- --ab ----   * 0x10
    ---- ---- -ab- ----   * 2
    ---- ---- ---a b---   y/64 * 8
+   ---- ---- -aba b---   y/64*0x28   See Note for alt. * 0x28

    0PP- ---- 0000 0000   Graphics page, $20 or $40

=   0PPf ghcd eaba b000   Address

C code:

        int HGR_y_to_address( int y ) {
            return 0x2000 + (y&7)*0x400 + ((y/8)&7)*0x80 + (y/64)*0x28;
        }

6502 code variation 1 (Original Applesoft)

                     GBASL    EQU   $26
                     GBASH    EQU   $27
                     HPAG     EQU   $E6        ; Used by Applesoft, 20 HGR1, 40 HGR2

                              ORG   $F417
                     ; Algorithm Y to HGR address
                     ; INPUT: A = row (0 .. 191)
                     ; The normal entry point is HPOSN $F411, A=row, Y,X=col
                     ; F411:  STA $E2
                     ; F413:  STX $E3
                     ; F415:  STY $E1
F417:                Y2HGRAddr
F417: 48                      PHA              ; Y = abcdefgh
F418: 29 C0                   AND #$C0         ; A = ab000000
F41A: 85 26                   STA GBASL        ;
F41C: 4A                      LSR              ; A = 0ab00000
F41D: 4A                      LSR              ; A = 00ab0000
F41E: 05 26                   ORA GBASL        ;   = abab0000
F420: 85 26                   STA GBASL
F422: 68                      PLA              ; C  A         GBASH    GBASL
F423: 85 27                   STA GBASH        ; ?  abcdefgh  abcdefgh abab0000
F425: 0A                      ASL              ; a  bcdefgh0  abcdefgh abab0000
F426: 0A                      ASL              ; b  cdefgh00  abcdefgh abab0000
F427: 0A                      ASL              ; c  defgh000  abcdefgh abab0000
F428: 26 27                   ROL GBASH        ; a  defgh000  bcdefghc abab0000
F42A: 0A                      ASL              ; d  efgh0000  bcdefghc abab0000
F42B: 26 27                   ROL GBASH        ; b  efgh0000  cdefghcd abab0000
F42D: 0A                      ASL              ; e  fgh00000  cdefghcd abab0000
F42E: 66 26                   ROR GBASL        ; 0  fgh00000  cdefghcd eabab000
F430: A5 27                   LDA GBASH        ; 0  cdefghcd  cdefghcd eabab000
F432: 29 1F                   AND #$1F         ; 0  000fghcd  cdefghcd eabab000
F434: 05 E6                   ORA HPAG         ; 0  pppfghcd  cdefghcd eabab000
F436: 85 27                   STA GBASH        ; 0  pppfghcd  pppfghcd eabab000
                              RTS

6502 code variation 2 (Woz's new version)

Woz Re-Codes Hi-Res Address Calculations Bob Sander-Cederlof In the October or November issue of the Washington Apple Pi newsletter, Rick Chapman wrote a review of various methods of calculating the hi-res base addresses. Steve Wozniak liked the article, and responded with a long "letter to the editor" in the December issue. Steve also presented a new version of the hi-res address calculator which is both shorter and faster. In fact, as far as I am aware, it is the fastest method ever, except for table-lookups.

In the September 1983 issue of Apple Assembly Line, I presented both the original Woz code and a shorter-faster version by Harry Cheung of Nigeria. Here are the specs:

   Applesoft ROM version:  33 bytes, 61 cycles
    Harry Cheung version:  25 bytes, 46 cycles
     New Wozniak version:  26 bytes, 36 or 37 cycles

The byte counts do not include an RTS at the end of the code, nor do the times include a JSR-RTS. After all, if you are really working for speed you will put the code in its place, not make it a subroutine.

Woz's new version takes either 36 or 37 cycles, depending on the values for the first two bits of the line number. Remember that the line number can be any value from 0 to 191, or $00...$BF. That means the first two bits are either 00, 01, or 10. If you look at lines 1090-1120 below, you will see that the shortest path is for 00, taking both branches, giving a running time for the whole calculation of 36 cycles. If the first two bits are 01 or 10, one branch will be taken and the other not, making the total time 37 cycles. In Woz's letter he shortchanged himself, thinking possibly both branches might not be taken, giving a total running time of 38 cycles; this cannot happen with legal line numbers.

Line 1180 adds in either $10 or $20, depending on which hi-res page you are using. The Applesoft code here adds in a value of either $20 or $40, so if this version were to be inserted into Applesoft the generation of HPAG2 would have to be changed. No problem, and not likely anyway. By the way, if you are only using one specific hi-res page, you can change line 1180 to an immediate mode form, saving yet another cycle.

Here is Woz's new version, reformatted for the S-C Assembler and with some changes in comments:

  1000 *SAVE S.NEW.WOZ.HIRES.CALC
  1010 *--------------------------------
  1020 GBASL  .EQ $26
  1030 GBASH  .EQ $27
  1040 HPAG2  .EQ $E6     Applesoft puts it here anyway.
  1050 *--------------------------------
  1060 CALC   ASL          A--BCDEFGH0
  1070        TAX          TAX...TXA could be TAY...TYA
  1080        AND #$F0     A--BCDE0000
  1090        BPL .1       B=0
  1100        ORA #$05     A--BCDE0B0B
  1110 .1     BCC .2       A-0
  1120        ORA #$0A     A--BCDEABAB
  1130 .2     ASL          B--CDEABAB0
  1140        ASL          C--DEABAB00
  1150        STA GBASL
  1160        TXA          C--BCDEFGH0
  1170        AND #$0E     C--0000FGH0
  1180        ADC HPAG2    O--OOxxFGH0
  1190 *   HPAG2 = $10 for base $2000, $20 for base $4000
  1200        ASL GBASL    D--00xxFGHC  GBASL=EABAB000
  1210        ROL          0--0xxFGHCD
  1220        STA GBASH
  1230        RTS
  1240 *--------------------------------

6502 code variation 3 (lookup table)

Of course the table/array lookup is the fastest. Classic Space vs Speed trade-off.

                     y2hgrL   EQU   $1000
                     y2hgrH   EQU   $1100

                              ORG   $0900
                     ; Table Y to HGR address
                     ; INPUT: Y = row (0 .. 191)
0900: B9 00 10       Y2HGRADR LDA   y2hgrL, Y
0903: 85 26                   STA   GBASL
0905: B9 00 11                LDA   y2hgrH, Y
0908: 44 E6                   ORA   HPAG       ; #$20 for HGR1, #$40 for HGR2
090A: 85 27                   STA   GBASH
090C: 60                      RTS

                              ORG   $1000
1000: 00 00 00 00 00 00 00 00
1008: 80 80 80 80 80 80 80 80
1010: 00 00 00 00 00 00 00 00
1018: 80 80 80 80 80 80 80 80
1020: 00 00 00 00 00 00 00 00
1028: 80 80 80 80 80 80 80 80
1030: 00 00 00 00 00 00 00 00
1038: 80 80 80 80 80 80 80 80
1040: 28 28 28 28 28 28 28 28
1048: A8 A8 A8 A8 A8 A8 A8 A8
1050: 28 28 28 28 28 28 28 28
1058: A8 A8 A8 A8 A8 A8 A8 A8
1060: 28 28 28 28 28 28 28 28
1068: A8 A8 A8 A8 A8 A8 A8 A8
1070: 28 28 28 28 28 28 28 28
1078: A8 A8 A8 A8 A8 A8 A8 A8
1080: 50 50 50 50 50 50 50 50
1088: D0 D0 D0 D0 D0 D0 D0 D0
1090: 50 50 50 50 50 50 50 50
1098: D0 D0 D0 D0 D0 D0 D0 D0
10A0: 50 50 50 50 50 50 50 50
10A8: D0 D0 D0 D0 D0 D0 D0 D0
10B0: 50 50 50 50 50 50 50 50
10B8: D0 D0 D0 D0 D0 D0 D0 D0

                              ORG   $1100
1100: 00 04 08 0C 10 14 18 1C
1108: 00 04 08 0C 10 14 18 1C
1110: 01 05 09 0D 11 15 19 1D
1118: 01 05 09 0D 11 15 19 1D
1120: 02 06 0A 0E 12 16 1A 1E
1128: 02 06 0A 0E 12 16 1A 1E
1130: 03 07 0B 0F 13 17 1B 1F
1138: 03 07 0B 0F 13 17 1B 1F
1140: 00 04 08 0C 10 14 18 1C
1148: 00 04 08 0C 10 14 18 1C
1150: 01 05 09 0D 11 15 19 1D
1158: 01 05 09 0D 11 15 19 1D
1160: 02 06 0A 0E 12 16 1A 1E
1168: 02 06 0A 0E 12 16 1A 1E
1170: 03 07 0B 0F 13 17 1B 1F
1178: 03 07 0B 0F 13 17 1B 1F
1180: 00 04 08 0C 10 14 18 1C
1188: 00 04 08 0C 10 14 18 1C
1190: 01 05 09 0D 11 15 19 1D
1198: 01 05 09 0D 11 15 19 1D
11A0: 02 06 0A 0E 12 16 1A 1E
11A8: 02 06 0A 0E 12 16 1A 1E
11B0: 03 07 0B 0F 13 17 1B 1F
11B8: 03 07 0B 0F 13 17 1B 1F

= HGR Address to Y =

0PPfghcdeabab000 ab
PPfghcdeabab0000 << 1
        11000000 & 0xC0

0PPfghcdeabab000 cde
    0PPfghcdeaba >> 4
         0111000 & 0x38

0PPfghcdeabab000 fgh
          0PPfgh >> 10
            0111 & 7 

C code:

   y = ((address & 0x18) << 3) | ((address & 0x1c00) >> 10) | ((address & 0x380) >> 4);

int HGR_address_to_y( int address ) { 
    return ((address <<  1) & 0xC0) // ab 
         | ((address >>  4) & 0x38) // cde 
         | ((address >> 10) & 0x07);// fgh 
}

TEXT

Text Row to Address

Given:

y = 000a bcde   (Range 0 .. 23 = $00 .. $17)

    ---- ---- 000a bcde   INPUT: Y
    000a bcde ---- ----   * 256
    000a bcd0 ---- ----   & 0xFE
    0000 abcd ---- ----   / 2
    0000 00cd ---- ----   & 3
+   0000 01cd ---- ----   | 4

    ---- ---- 000a bcde   INPUT: Y
    ---- ---- 000a b000   & 0x18
    ---- ---- e00a b000   = temp
    ---- ---- 000a b000   & 18
    ---- ---0 00ab 0000   * 2
    ---- --00 0ab0 0000   * 2
+   ---- --00 eaba b000   | temp

=   0000 01cd eaba b000   Address
                     ; Algorithm Y to TXT address
                     ; INPUT: A = row

                     BASL     EQU   $28
                     BASH     EQU   $29

                              ORG   $FBC1
FBC1: 48        577  BASCALC  PHA              ;CALC BASE ADR IN BASL,H
FBC2: 4A        578           LSR              ;  FOR GIVEN LINE NO
FBC3: 29 03     579           AND   #$03       ;  0<=LINE NO.<=$17
FBC5: 09 04     580           ORA   #$04       ;ARG=000ABCDE, GENERATE
FBC7: 85 29     581           STA   BASH       ;  BASH=000001CD
FBC9: 68        582           PLA              ;  AND
FBCA: 29 18     583           AND   #$18       ;  BASL=EABAB000
FBCC: 90 02     584           BCC   BSCLC2
FBCE: 69 7F     585           ADC   #$7F
FBD0: 85 28     586  BSCLC2   STA   BASL
FBD2: 0A        587           ASL
FBD3: 0A        588           ASL
FBD4: 05 28     589           ORA   BASL
FBD6: 85 28     590           STA   BASL
FBD8: 60        591           RTS

                     ; Table Y to TXT address
                     ; INPUT: Y = row

                     y2txtL   EQU   $1280
                     y2txtH   EQU   $1298

                              ORG   $1200
1200: B9 80 12       Y2TXTADR LDA   y2txtL, Y
1203: 85 28                   STA   BASL
1205: B9 98 12                LDA   y2txtH, Y
1208: 85 29                   STA   BASH
120A: 60                      RTS

                              ORG   $1280
1280: 00 80 00 80 00 80 00 80                  ; Rows  0 .. 7 ($00 .. $07)
1288: 28 A8 28 A8 28 A8 28 A8                  ; Rows  8 ..15 ($08 .. $10)
1290: 50 D0 50 D0 50 D0 50 D0                  ; Rows 16 ..23 ($10 .. $17)

1298: 04 04 05 05 06 06 07 07                  ; Rows  0 .. 7 ($00 .. $07)
1298: 04 04 05 05 06 06 07 07                  ; Rows  8 ..15 ($08 .. $10)
1298: 04 04 05 05 06 06 07 07                  ; Rows 16 ..23 ($10 .. $17)

Text Address to Row

TODO!