Jon Bettencourt 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