# Improving transfer time to VERA in BASIC

## Recommended Posts

Today I opened up the old "Rogue Forest" game I wrote a year ago, and I thought that this snippet could be sped up:

if y>8 and y<40 then ff=int(rnd(1)*3)
vpoke 1,P,fo(ff) :rem character index
vpoke 1,P+1,cl   :rem bg/fg color nybbles

if y>8 and y<40 then ff=int(rnd(1)*3)
vpoke 1,P+2,fo(ff)
vpoke 1,P+3,cl

if y>8 and y<40 then ff=int(rnd(1)*3)
vpoke 1,P+4,fo(ff)
vpoke 1,P+5,cl

if y>8 and y<40 then ff=int(rnd(1)*3)
vpoke 1,P+6,fo(ff)
vpoke 1,P+7,cl

P, P+1, P+2, P+3... P+7.  I mean, that sounds like a shoo-in for using the auto-increment with Port 0, for example.

Anyone think that sounds reasonable?  I THINK I should be able to do something like this:

vpoke %10000, P, 0 :rem set up autoincrement

if y>8 and y<40 then ff=int(rnd(1)*3)
poke \$9f23, fo(ff) :rem character index
poke \$9f23,cl   :rem bg/fg color nybbles

if y>8 and y<40 then ff=int(rnd(1)*3)
poke \$9f23, fo(ff)
poke \$9f23, cl

if y>8 and y<40 then ff=int(rnd(1)*3)
poke \$9f23, fo(ff)
poke \$9f23, cl

if y>8 and y<40 then ff=int(rnd(1)*3)
poke \$9f23, fo(ff)
poke \$9f23, cl

Edited by rje
##### Share on other sites

I haven't looked at reference material to ensure all the numbers are exactly correct, but that seems reasonable in theory.

##### Share on other sites

Thanks.  It's not exactly correct, so I have to hunt around for the right way.

In particular, the initial VPOKE has something wrong with it.

Edited by rje
##### Share on other sites

Given a base address P I think what you want to replace the VPOKE with:

POKE \$9F25, PEEK(\$9F25) AND 254 : REM SELECT ADDR 0
POKE \$9F22, %00010000 OR INT(P / 65536) : REM INCR 1 AND VRAM ADDR BIT 16
POKE \$9F21, INT(P / 256) AND 255 : REM VRAM ADDR BITS 15:8
POKE \$9F20, P AND 255 : REM VRAM ADDR BITS 7:0
REM NOW THE ADDR IS SETUP SO DO EVERYTHING AFTER VPOKE LINE...

##### Share on other sites

With the solution above, I am assuming P is the complete VRAM address from \$00000 to \$1FFFF. The second line doesn't have to do the "OR INT(P/65536)" part if the address will always be \$FFFF or smaller.

##### Share on other sites

On 10/11/2021 at 10:14 PM, Scott Robison said:

With the solution above, I am assuming P is the complete VRAM address from \$00000 to \$1FFFF. The second line doesn't have to do the "OR INT(P/65536)" part if the address will always be \$FFFF or smaller.

Thanks for that.  Managing the bitfields (and understanding what they do) is the full problem.  It looks to me like I was POKEing above \$10000, so the OR is probably needed.

##### Share on other sites

you can always poke a short assembly routine into ram somewhere and SYS to it to do the tight loop, if you want to speed up things?

##### Share on other sites

You're right.

For now, though, I'm seeing what it can do when I stay in BASIC, to serve as a demo of what you can do with BASIC.

Ah, but I am currently using that tiny interrupt-driven sound library by Dusan.  Even as simple as it is, it's adding a great bit of "color" to the game!

##### Share on other sites

If you're using the initial VPOKE just to set up the address, that won't work since it will increment on that write as well, and it will end up starting at P+1 on the next line.  You need to start at P-1 (assuming that it's ok to put a 0 there), or somehow VPOKE only on the first actual data write that you do.

##### Share on other sites

On 10/12/2021 at 6:57 PM, Ender said:

If you're using the initial VPOKE just to set up the address, that won't work since it will increment on that write as well, and it will end up starting at P+1 on the next line.  You need to start at P-1 (assuming that it's ok to put a 0 there), or somehow VPOKE only on the first actual data write that you do.

VPOKE will set an address (I don't think it's documented as to whether it will set addr 0 or 1), but I don't think it sets the increment. Regardless, VPOKE will always reset the address every time it is used. By avoiding VPOKE completely you can set the address, pick whether it is 0 or 1, and target the port. Whether it is a net improvement will depend on how much overhead is involved in the multiple POKE statements and how many bytes you write with auto incrementing addresses. I feel confident that my solution is technically correct (though I didn't try running it), but it might not be more efficient than a series of VPOKE statements. That would probably be a good test. Run the 8 VPOKE based version 1000 or so times and time it, then run the 12 POKE only version 1000 or so times and time it and see if one is definitively better than the other.

Now I'm curious. Testing.

##### Share on other sites

It's not (noticeably) slower or faster, and technically it's a demonstration of the autoincrement, so I'm keeping it.

Edited by rje
##### Share on other sites

On 10/12/2021 at 9:55 PM, Scott Robison said:

VPOKE will set an address (I don't think it's documented as to whether it will set addr 0 or 1), but I don't think it sets the increment. Regardless, VPOKE will always reset the address every time it is used. By avoiding VPOKE completely you can set the address, pick whether it is 0 or 1, and target the port. Whether it is a net improvement will depend on how much overhead is involved in the multiple POKE statements and how many bytes you write with auto incrementing addresses. I feel confident that my solution is technically correct (though I didn't try running it), but it might not be more efficient than a series of VPOKE statements. That would probably be a good test. Run the 8 VPOKE based version 1000 or so times and time it, then run the 12 POKE only version 1000 or so times and time it and see if one is definitively better than the other.

Now I'm curious. Testing.

If you look at the source code of VPOKE, all it does is put the first argument in to \$9f22, the second argument into \$9f20 and \$9f21, and the third argument in to \$9f23.  So yes, you can use VPOKE to set the increment, and arguably it's faster than doing three POKEs to set up the address, since you're parsing and executing two less BASIC commands.

##### Share on other sites

On 10/12/2021 at 8:02 PM, Ender said:

If you look at the source code of VPOKE, all it does is put the first argument in to \$9f22, the second argument into \$9f20 and \$9f21, and the third argument in to \$9f23.  So yes, you can use VPOKE to set the increment, and arguably it's faster than doing three POKEs to set up the address, since you're parsing and executing two less BASIC commands.

Ah, good to know, thanks. In my testing just now, my version is definitely slower because the extra pokes do math on P that isn't necessary in the VPOKE version, so don't use it even though it is "technically correct" but "slow".  And I realized that if P is greater than 32767 AND is going to fail with it and AND only works with valid signed integers.

Edited: removed screen shot in favor of next message.

There is the test code, and the numbers under RUN are the number of jiffies to execute the pure VPOKE and the number of jiffies to execute the pure POKE.

Edited by Scott Robison
##### Share on other sites

Here is a better test case that is more apples to apples based on Ender's comment.

So 322 jiffies to use pure VPOKE, 590 jiffies to use pure POKE, 218 to use hybrid approach that should autoincrement. Replace %10001 with a variable to make it even faster, probably.

Edit: Oh, I put one too many POKE commands in the final loop. That is just a typo. Remove one of them to get the exact 8 VRAM pokes you wanted. That gets the time down to only 199 jiffies.

Edited by Scott Robison
##### Share on other sites

So by using VPOKE 8 times in a loop, each statement will average 0.67 ms per VPOKE (plus extra time for any calculations since I'm just poking values of 0).

By using one VPOKE and 7 POKE statements in a loop, the average time is only 0.42 ms per VPOKE/POKE. 37% speed increase.

##### Share on other sites

Yep, replace P+0 with P and replace %10001 with a variable defined earlier and I got the third loop down to 170 jiffies, or 0.36 ms per VPOKE/POKE. 46% speed increase.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.