3

The BASIC 7.0 of the C128 provides commands for copying a block of bytes between an REU (RAM expansion unit) and memory in Bank 0 or 1. For those who do not own an REU, is there a function for copying a block of data between two memory areas across banks 0 and 1? From reading the BASIC 7.0 documentation I did not find an appropriate BASIC command for this, but is there a machine language routine in the ROM that can be called from BASIC and does the job?

The alternative of using a FOR-loop in BASIC 7.0: FOR I=source TO I+length-1:BANK 0:A=PEEK(I):BANK 1:POKE target-source+I,A:NEXT is really slow.

1 Answer 1

5

No there is no equivalent BASIC command. In fact, even REU commands (FETCH/STASH/SWAP) can not copy between the C128's two banks, but only between whatever bank has been selected (*1) ant the REU.

As a result copying a block from one bank into the other needs to go thru the REU. First transferred to the REU and then to the other Bank. For example to move 256 bytes fron $1000 in Bank 1 to $2000 in Bank 0 one needs to:

10 BANK 1 : SWAP 256, 1024, 0, 0  : REM Move from bank 1 to REU and save REU content
20 BANK 0 : FETCH 256, 2048, 0, 0 : REM Move from REU to Bank 0
30 BANK 1 : SWAP 256, 1024, 0, 0  : REM Restore REU content

Given, it will be comparably fast, still not really elegant.

The same process can of course be done using an external drive, like a floppy.

10 BSAVE "MOVEFILE", B1, P (1024) TO P (1024+256)
20 BLOAD "MOVEFILE", B0, P (2048)
30 SCRATCH "MOVEFILE"

Works, but might not be the fastest way. For short amounts the mentioned BASIC loop might be faster (*2,3).

Of course if a machine language routine is fine, that would speed it up a lot. The C128 Kernal offers a set of new calls to access a byte in any bank as described on p.405 of the C128 Programmer's Reference Guide:

16. $FF74 JMP INDFET ;LDA (fetvec),Y from any bank
17. $FF77 JMP INDSTA ;STA (stavec),Y to any bank
18. $FF7A JMP INDCMP ;CMP (cmpvec),Y to any bank

Using these a copy routine can be set up that should work acceptable fast while still being fairly hardware independent (*3,4).


*1 - By setting via BANK n or POKE 981,n

*2 - Maybe without that potential error and a tiny bit optimized:

last=length-1
FOR I=0 TO last:BANK 0:A=PEEK(start+I):BANK 1:POKE target+I,A:NEXT

*3 - Another idea could be using the common RAM area as intermediate buffer - not sure how well that might work from BASIC

*4 - I'm not sure, but it might be worth to take a look at using the 8563 RAM as buffer intermediate buffer.

10
  • "Maybe without that error" - which error?
    – Peter B.
    Commented Sep 27, 2022 at 20:35
  • @PeterB. FOR I=source TO I+length-1 is a rather dubios construct, isn't it?
    – Raffzahn
    Commented Sep 27, 2022 at 20:44
  • The end address of the for loop is calculated once and put onto the stack, Thus, the first value of I counts for the calculation and the expression is only evaluated once. Would not count that as error.
    – Peter B.
    Commented Sep 27, 2022 at 20:48
  • 1
    I tested with a 4K area and got 16 seconds vs 65 seconds. For 256 bytes it is around 5 seconds for both, so not worth bothering the disk. 256 bytes means writing and reading 2 blocks, which is a bit unfortunate for the floppy team. With 506 bytes it is still 2 blocks on disk and the floppy solution wins with 6 vs 9 seconds.
    – Peter B.
    Commented Sep 27, 2022 at 21:48
  • 1
    @PeterB. Would you want to try that with STEP 2? (FOR I=0 TO last STEP 2 :BANK 0:A=PEEK(start+I):B=PEEK(start+I+1):BANK 1:POKE target+I,A:POKE target+I+1,A:NEXT) Just out of curiosity :))
    – Raffzahn
    Commented Sep 27, 2022 at 22:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .