[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scrolling HGR Screen Up 8 Lines



Jon Bettencourt <jonINTERNETrelayCHAT@napaVALLEYnet.CLARInet> wrote:

> Does anybody have an assembly language routine for such a thing?

Not handy, but I should be able to construct one from first principles.

> Apperently, just moving memory won't work. 2000<2028.3FFFM in the
> System Monitor got close, but not close enough.

It isn't that simple.  You would have to do the move in lots of pieces.

Here is the address pattern for each line on the Hi-Res screen.
(Digging into memory from 1983...)

Starting at line zero (or any line which is a multiple of eight), each
subsequent line in the group of eight is $0400 (1024) bytes after the
previous one, i.e. the first eight lines are:

$2000, $2400, $2800, $2C00, $3000, $3400, $3800, $3C00

Each subsequent group of eight lines is $0080 (128) bytes after the
previous group.  This repeats eight times.

Thus lines 8 through 15 are:

$2080, $2480, $2880, $2C80, $3080, $3480, $3880, $3C80

and lines 16 through 23 are:

$2100, $2500, $2900, $2D00, $3100, $3500, $3900, $3D00

This gets you up to 64 lines.  The next 64 lines repeat the pattern,
adding $0028 (40).

Thus lines 64 through 71 are:

$2028, $2428, $2828, $2C28, $3028, $3428, $3828, $3C28

The last 64 lines repeat the pattern again, adding a further $0028, so
lines 128 through 135 are:

$2050, $2450, $2850, $2C50, $3050, $3450, $3850, $3C50

There are eight unused bytes at the end of each group of 128 (only the
first 120 bytes are visible).

If you look at the memory locations in ascending order, the pattern goes
like this:

$2000   line 0
$2028   line 64
$2050   line 128
$2078   eight unused bytes
$2080   line 8
$20A8   line 72
$20D0   line 136
$20F8   eight unused bytes
$2100   line 16
...
$23D0   line 184
$23F8   eight unused bytes
$2400   line 1
...
$27D0   line 185
$27F8   eight unused bytes
$2800   line 2
...
$2BD0   line 186
$2BF8   eight unused bytes
$2C00   line 3
...
$2FD0   line 187
$2FF8   eight unused bytes
$3000   line 4
...
$33D0   line 188
$33F8   eight unused bytes
$3400   line 5
...
$37D0   line 189
$37F8   eight unused bytes
$3800   line 6
...
$3BD0   line 190
$3BF8   eight unused bytes
$3C00   line 7
...
$3FD0   line 191
$3FF8   eight unused bytes

So lets look at what is needed to move each line up eight.

Lines 0 through 7 will be overwritten, so we can ignore them.
Line 8 ($2080) needs to move to line 0 ($2000).
Line 9 ($2480) needs to move to line 1 ($2400).
...
Line 63 ($3F80) needs to move to line 55 ($3F00).

So far, a simple move back in memory by $0080 will work.

The tricky part is the next eight lines.  Line 64 ($2028) needs to move
to line 56 ($2380).  Line 65 ($2428) needs to move to line 57 ($2780),
etc.  Once you reach line 72, everything is simple again until you hit
line 128, where the same problem occurs.

You have a total of sixteen lines (40 bytes each, or eight groups of 80
adjacent bytes), which have to be moved elsewhere.  You can then move
all of the screen memory back by 128 bytes, and copy the extracted lines
back to the correct places.

This is rather messy.  It will also look strange, with striped effects
during the move.

Another way of doing this (which will look a lot better) would be to
make use of the HBASCALC routine in Applesoft to calculate the address
of each line (or use a lookup table, or calculate the addresses
directly), and move the rows in order.  This will give a rippling
scroll, rather than a striped one.

In this case you would be doing 184 moves, each of which would move 40
bytes.

Here is a self-contained assembly language routine I've just whipped up
which will do this.  I've tested it, and (after a few minor corrections)
it appears to work correctly.

It fits in $0300-$03CF.  Note the use of internal JSRs in three places,
so the destinations would need to be modified if you want to relocate
this code to run elsewhere.  The zero page locations used are monitor
scratch variables, so there should be no side effects.

I'd strongly suggest saving any Applesoft program (or other data) before
testing your transcription of this routine, in case of typos.  It does a
lot of fiddly calculations, and a minor error could easily destroy
memory contents.

MOVEUP8
; Move hi-res page one up by eight lines, clearing the last eight.
0300: A9 00     LDA #$00
0302: 85 42     STA $42        ; Dest address, low byte
0304: A9 80     LDA #$80
0306: 85 3C     STA $3C        ; Source address, low byte
0308: A9 20     LDA #$20
030A: 85 43     STA $43        ; Dest address, high byte
030C: 85 3D     STA $3D        ; Source address, high byte
030E: A9 03     LDA #$03       ; Number of groups of 64 lines to copy
0310: 85 3F     STA $3F
COPYLP
0312: 20 69 03  JSR COPY56     ; Do the simple group of lines
0315: C6 3F     DEC $3F
0317: F0 31     BEQ LAST8      ; Stop if we are up to the last 8 lines
; Adjust the source and destination addresses for the eight
; lines which don't follow the simple pattern.  At this point,
; the source address is equal to the address of the last line,
; which is $1F80 after the start of this third of the screen,
; and the destination address is $0080 bytes earlier.
; The new source line is $0028 after the start of the current
; third, so we need to subtract ($1F80-$0028=$1F58) from the source
; address.
; The new destination line is ($1C00-$0080=$1B80) earlier.
0319: A5 3C     LDA $3C
031B: 38        SEC
031C: E9 58     SBC #$58
031E: 85 3C     STA $3C
0320: A5 3D     LDA $3D
0322: E9 1F     SBC #$1F
0324: 85 3D     STA $3D
0326: A5 42     LDA $42
0328: 38        SEC
0329: E9 80     SBC #$80
032B: 85 42     STA $42
032D: A5 43     LDA $43
032F: E9 1B     SBC #$1B
0331: 85 43     STA $43
; Now copy the eight oddball lines
0333: 20 90 03  JSR COPY8
; Adjust the addresses for the next group of 56 lines.
; The destination address is the source address minus $1C00.
; The new source address is the modified destination address
; plus $0080 (which will never carry).
0336: A5 3C     LDA $3C
0338: 85 42     STA $42
033A: 18        CLC
033B: 69 80     ADC #$80
033D: 85 3C     STA $3C
033F: A5 3D     LDA $3D
0341: 38        SEC
0342: E9 1C     SBC #$1C
0344: 85 3D     STA $3D
0346: 85 43     STA $43
0348: D0 C8     BNE COPYLP     ; Branch always taken

LAST8 
; Do something appropriate with the last eight lines here.
; For the purposes of this example code, I'll fill them with
; black.
034A: A9 D0     LDA #$D0
034C: 85 42     STA $42
034E: A9 23     LDA #$23
0350: 85 43     STA $43
0352: A2 08     LDX #$08
FILLLINE
0354: A0 00     LDY #$00
0356: 98        TYA
FILLLP
0357: 91 42     STA ($42),Y
0359: C8        INY
035A: C0 28     CPY #$28
035C: 90 F9     BCC FILLLP
035E: A5 43     LDA $43
0360: 18        CLC
0361: 69 04     ADC #$04
0363: 85 43     STA $43
0365: CA        DEX
0366: D0 EC     BNE FILLLINE
ANYRTS
0368: 60        RTS            ; All done!

COPY56
; Subroutine to copy 56 lines.
; On exit, the source and destination address will have
; been incremented by $1F00.
0369: A9 07     LDA #$07       ; Number of groups of eight lines to copy
036B: 85 3E     STA $3E
C56LOOP
036D: 20 90 03  JSR COPY8      ; Copy eight lines
0370: C6 3E     DEC $3E
0372: F0 F4     BEQ ANYRTS     ; Stop once we've done 56.
; Adjust the addresses for the next group of eight lines
; by adding $0080.  We need to allow for the $1C00 that
; was added by COPY8, so in effect, we want to subtract $1B80.
0374: A5 3C     LDA $3C
0376: 38        SEC
0377: E9 80     SBC #$80
0379: 85 3C     STA $3C
037B: A5 3D     LDA $3D
037D: E9 1B     SBC #$1B
037F: 85 3D     STA $3D
0381: A5 42     LDA $42
0383: 38        SEC
0384: E9 80     SBC #$80
0386: 85 42     STA $42
0388: A5 43     LDA $43
038A: E9 1B     SBC #$1B
038C: 85 43     STA $43
038E: D0 DD     BNE C56LOOP    ; Always taken

COPY8
; Subroutine to copy 8 lines.
; On exit, the source and destination addresses will have
; been incremented by $1C00.
0390: A2 08     LDX #$08       ; Number of lines to copy
C8LOOP
0392: A0 00     LDY #$00
LINELOOP
0394: B1 3C     LDA ($3C),Y
0396: 91 42     STA ($42),Y
0398: C8        INY
0399: C0 28     CPY #$28
039B: 90 F7     BCC LINELOOP   ; Repeat until we've copied 40 bytes
039D: CA        DEX            ; Count off a line
039E: F0 C8     BEQ ANYRTS
; Adjust the source and destination address by adding $0400
03A0: A5 3D     LDA $3D
03A2: 18        CLC
03A3: 69 04     ADC #$04
03A5: 85 3D     STA $3D
03A7: A5 43     LDA $43
03A9: 18        CLC
03AA: 69 04     ADC #$04
03AC: 85 43     STA $43
03AE: D0 E2     BNE C8LOOP     ; Always taken

-- 
David Empson
dempson@actrix.gen.nz
Snail mail: P O Box 27-103, Wellington, New Zealand