And yes, to speed things up: retrieving the string’s storage address via @var (and knowing how it’s encoded), then PEEKing into memory… But you don’t want to go down that road. Even if it’s just reading via PEEK (no CALL/POKE), it makes the code CPC-only.
I have read another of your post… As this is not assembly langage but BASIC encoding, here is the direct access to a char in BASIC.
10 A$="Texte"
20 AD=@A$:REM AD = Memory adress of A$
30 L=PEEK(AD): REM L = Size of A$ (same as LEN)
40 AD1 = PEEK (AD+1) : REM AD1 = LSB of "Texte"
50 AD2 = PEEK (AD+2) : REM AD2 = MSB of "Texte"
60 TAD = AD2 * 256 + AD1 : REM TAD = Memory adress of "Texte"
70 FOR I=0 TO L-1:PRINT CHR$(PEEK(TAD+I)):NEXT I : REM Prints all chars one by one
Like always, if you have computed the address yourself, then accessing one letter is easy as a getting a value after an addition.
With MID$, BASIC is doing the same thing over and over again each time, adding some overhead that can be by-passed with this kind of quick access.
Back in the days, when the only scrolling routine I knew was MID$, I noticed that it was slow while traversing a (long) string/message and would speed up towards the end of it. I wonder if this was due to some inefficient sub-string extraction or just because it had less chars to print when there were only 10, 9, 8 … chars of the long string left. Now I assume it was the latter