Page 1 of 2

BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Thu Jan 14, 2021 10:52 pm
by rje

There are two tricks to demonstrate with this code:

(1) the use of VERA's auto-increment when loading sprite data

(2) the use of runlength-encoded data for the X16 logo in 64x64 to save RAM.

 

Here's my code in a nutshell.

175 REM SET UP THE VERA DATA PORT FOR AUTO-INCREMENT AT $04000
180 POKE $9F20,$00
185 POKE $9F21,$40
190 POKE $9F22,16 :REM AUTO-INCREMENT TO 1, HIGH ADDR BIT 0





$9f20 and $9f21 and bit 0 in $9f22 point to the destination address in VERA: in this case, it's $04000.

$9f22 also holds the auto-increment value.  A "16" sets the increment to +1.

 

*** EDIT: The suggestion from the crowd is that it's safer to do all that with a VPOKE %10000, $4000, 0 to set up the target address and the auto-increment.

 

195 REM READ-LOOP
200 READ X, RL :IF X<0 GOTO 750
205 FOR Y=1 TO RL
210 POKE $9F23, X
215 NEXT
220 GOTO 200

The read loop takes advantage of the address setup code, so the inner loop only needs a POKE.

No VPOKE.  No counter to increment.  This doubles the load time, approximately.

The data has the value first, and then the number of cells with this value.  So the read loop has an inner loop that does the actual data assignment.

The runlength count was VERY useful for this data.  Sometimes though, with very colorful icons, it's useless.  Take care.

225 REM
230 REM  X16 LOGO DATA.  FORMAT: VALUE, RUNLENGTH COUNT, ...
235 REM
240 DATA $00,1,$12,1,$AE,1,$91,57,$14,1,$16,1,$14,1,$00,1
245 DATA $12,1,$C9,61,$AE,1,$14,2,$C9,62,$17,1,$C9,5,$16,1
250 DATA $CA,1,$C9,50,$CB,1,$14,1,$91,1,$14,1,$C9,2,$AF,1
255 DATA $C9,5,$CA,1,$E9,1,$16,1,$C9,48,$E7,1,$E9,1,$C9,5
260 DATA $AF,1,$C9,6,$E8,1,$E9,1,$CB,1,$C9,46,$E8,1,$E9,1
265 DATA $E7,1,$C9,5,$AF,1,$C9,6,$E7,1,$E9,2,$E7,1,$C9,43
270 DATA $B5,1,$E8,1,$E9,2,$CA,1,$C9,5,$AF,1,$C9,6,$CA,1
275 DATA $CD,3,$CC,1,$91,1,$C9,40,$CA,1,$CD,4,$C9,6,$AF,1
280 DATA $C9,7,$CC,1,$CD,3,$B0,1,$B5,1,$C9,38,$CA,1,$CC,1
285 DATA $CD,3,$CB,1,$C9,6,$AF,1,$C9,7,$AF,1,$B1,4,$B0,1
290 DATA $AE,1,$C9,36,$B6,1,$B0,1,$B1,4,$AE,1,$C9,6,$AF,1
295 DATA $C9,7,$AE,1,$B8,6,$B6,1,$C9,34,$AF,1,$B8,6,$91,1
300 DATA $C9,6,$AF,1,$C9,8,$B8,7,$B6,1,$C9,31,$91,1,$B7,1
305 DATA $B8,6,$B7,1,$C9,7,$AF,1,$C9,8,$B7,1,$B8,7,$B7,1
310 DATA $C9,29,$B5,1,$B7,1,$B8,7,$B6,1,$C9,7,$AF,1,$C9,8
315 DATA $B6,1,$A2,8,$A1,1,$B5,1,$C9,26,$B5,1,$A2,9,$B5,1
320 DATA $C9,7,$AF,1,$C9,8,$B5,1,$B8,10,$B5,1,$C9,24,$B6,1
325 DATA $B8,10,$C9,8,$AF,1,$C9,9,$B8,11,$AE,1,$C9,22,$B7,1
330 DATA $B8,10,$B7,1,$C9,8,$AF,1,$C9,9,$B7,1,$B9,11,$B6,1
335 DATA $C9,20,$B8,1,$B9,11,$AE,1,$C9,8,$AF,1,$C9,9,$AE,1
340 DATA $9C,12,$9B,1,$C9,17,$B5,1,$B8,1,$9C,12,$C9,9,$AF,1
345 DATA $C9,10,$9C,1,$95,12,$B8,1,$91,1,$C9,14,$AE,1,$9C,1
350 DATA $95,12,$B8,1,$C9,9,$AF,1,$C9,10,$B8,1,$9D,13,$9C,1
355 DATA $B5,1,$C9,12,$B6,1,$95,1,$9D,13,$AF,1,$C9,9,$AF,1
360 DATA $C9,10,$AF,1,$9D,14,$95,1,$AE,1,$C9,10,$93,1,$9D,15
365 DATA $B5,1,$C9,9,$AF,1,$C9,10,$B5,1,$9D,1,$03,14,$9D,1
370 DATA $AF,1,$C9,8,$9B,1,$03,15,$9C,1,$C9,10,$AF,1,$C9,11
375 DATA $9C,1,$03,16,$93,1,$C9,5,$91,1,$9C,1,$03,16,$93,1
380 DATA $C9,10,$AF,1,$C9,11,$AE,1,$9B,1,$95,1,$9D,15,$9A,1
385 DATA $C9,4,$94,1,$9D,15,$9C,1,$9B,1,$B5,1,$C9,10,$AF,1
390 DATA $C9,14,$AE,1,$9A,1,$9B,1,$9C,1,$95,11,$9A,1,$C9,4
395 DATA $9C,1,$95,11,$9C,1,$9B,1,$9A,1,$B5,1,$C9,13,$AF,1
400 DATA $C9,17,$91,1,$92,1,$9B,1,$9C,9,$9A,1,$C9,4,$9B,1
405 DATA $9C,8,$9B,1,$9A,1,$AE,1,$C9,17,$AF,1,$C9,21,$B5,1
410 DATA $9A,1,$9B,1,$9C,5,$9A,1,$C9,4,$9B,1,$9C,5,$9B,1
415 DATA $92,1,$91,1,$C9,20,$AF,1,$C9,24,$99,1,$A3,4,$9A,1
420 DATA $C9,4,$9B,1,$A3,3,$9B,1,$91,1,$C9,23,$AF,1,$C9,24
425 DATA $99,1,$80,4,$99,1,$C9,4,$9A,1,$80,4,$C9,24,$AF,1
430 DATA $C9,24,$99,1,$80,4,$99,1,$C9,4,$7F,1,$80,4,$C9,24
435 DATA $AF,1,$C9,24,$76,1,$7F,4,$7E,1,$C9,4,$7F,5,$C9,24
440 DATA $AF,1,$C9,24,$7E,1,$80,4,$7E,1,$C9,4,$7F,1,$80,3
445 DATA $7F,1,$91,1,$C9,23,$AF,1,$C9,21,$14,1,$62,1,$63,1
450 DATA $64,5,$7E,1,$C9,4,$63,1,$64,5,$7F,1,$5A,1,$91,1
455 DATA $C9,20,$AF,1,$C9,18,$14,1,$62,1,$63,1,$64,8,$62,1
460 DATA $C9,4,$63,1,$64,8,$63,1,$3E,1,$91,1,$C9,17,$AF,1
465 DATA $C9,15,$14,1,$62,1,$64,12,$62,1,$C9,4,$63,1,$64,11
470 DATA $63,1,$3E,1,$14,1,$C9,14,$AF,1,$C9,13,$15,1,$47,1
475 DATA $48,14,$5A,1,$C9,4,$63,1,$48,14,$63,1,$91,1,$C9,12
480 DATA $AF,1,$C9,13,$3F,1,$48,14,$3E,1,$C9,6,$3F,1,$48,14
485 DATA $5A,1,$C9,12,$AF,1,$C9,13,$47,1,$07,12,$48,1,$15,1
490 DATA $C9,8,$46,1,$48,1,$07,12,$46,1,$C9,12,$AF,1,$C9,13
495 DATA $49,12,$48,1,$14,1,$C9,10,$3E,1,$49,12,$47,1,$C9,12
500 DATA $AF,1,$C9,12,$15,1,$49,11,$48,1,$14,1,$C9,12,$15,1
505 DATA $49,11,$48,1,$C9,12,$AF,1,$C9,12,$46,1,$49,10,$47,1
510 DATA $91,1,$C9,14,$14,1,$48,1,$49,10,$14,1,$C9,11,$AF,1
515 DATA $C9,12,$47,1,$49,9,$47,1,$C9,17,$14,1,$48,1,$49,9
520 DATA $3E,1,$C9,11,$AF,1,$C9,12,$08,1,$49,8,$46,1,$C9,20
525 DATA $47,1,$49,8,$46,1,$C9,11,$AF,1,$C9,12,$08,8,$3E,1
530 DATA $C9,22,$46,1,$08,8,$C9,11,$AF,1,$C9,11,$22,1,$2D,6
535 DATA $08,1,$22,1,$C9,24,$2A,1,$08,1,$2D,5,$08,1,$C9,11
540 DATA $AF,1,$C9,11,$2A,1,$2D,5,$08,1,$14,1,$C9,26,$22,1
545 DATA $08,1,$2D,5,$14,1,$C9,10,$AF,1,$C9,11,$2B,1,$2D,4
550 DATA $2C,1,$E5,1,$C9,28,$22,1,$08,1,$2D,4,$22,1,$C9,10
555 DATA $AF,1,$C9,11,$2C,1,$2D,3,$2B,1,$C9,31,$14,1,$2C,1
560 DATA $2D,3,$2B,1,$C9,10,$AF,1,$C9,11,$34,1,$2D,2,$2B,1
565 DATA $C9,33,$E5,1,$2C,1,$2D,2,$2C,1,$C9,10,$AF,1,$C9,10
570 DATA $22,1,$34,2,$2A,1,$C9,36,$2B,1,$34,2,$C9,10,$AF,1
575 DATA $C9,10,$2A,1,$34,1,$22,1,$C9,38,$2B,1,$34,1,$E5,1
580 DATA $C9,9,$AF,1,$C9,10,$2B,1,$22,1,$C9,40,$2A,1,$22,1
585 DATA $C9,9,$AF,1,$C9,63,$AF,1,$C9,63,$AF,1,$C9,63,$AF,1
590 DATA $C9,46,$AE,1,$91,1,$C9,3,$91,1,$AE,1,$C9,10,$AF,1
595 DATA $C9,6,$18,1,$1A,2,$AE,1,$18,1,$1A,1,$19,1,$16,1
600 DATA $17,1,$18,1,$C9,1,$14,1,$19,1,$AE,1,$19,1,$AE,1
605 DATA $C9,1,$17,1,$18,1,$C9,1,$AE,1,$B0,1,$C9,1,$14,1
610 DATA $19,1,$AE,1,$C9,1,$17,2,$1A,2,$17,1,$91,1,$19,1
615 DATA $1A,1,$19,1,$AF,1,$1A,2,$19,1,$AE,1,$1D,1,$AE,1
620 DATA $C9,1,$AE,1,$1D,1,$16,1,$19,1,$14,1,$19,1,$1A,1
625 DATA $19,1,$C9,5,$AF,1,$C9,5,$AE,1,$1B,1,$AE,2,$AF,1
630 DATA $1A,1,$AE,2,$1C,3,$B5,1,$19,1,$1D,1,$18,1,$1D,1
635 DATA $1A,1,$91,1,$1C,2,$C9,1,$1C,1,$1A,1,$17,1,$AE,1
640 DATA $1C,2,$91,1,$1B,2,$16,1,$AE,1,$1C,1,$19,1,$1A,1
645 DATA $17,2,$19,1,$18,1,$AE,1,$1B,1,$AE,1,$1C,1,$1E,1
650 DATA $16,1,$1E,1,$1B,1,$C9,1,$1C,1,$19,1,$1A,1,$AF,1
655 DATA $16,1,$C9,5,$AF,1,$C9,5,$AE,1,$1A,1,$C9,2,$AF,1
660 DATA $19,1,$C9,1,$91,1,$1C,1,$1B,1,$17,1,$19,1,$1C,1
665 DATA $19,1,$18,1,$1A,1,$1C,1,$19,1,$18,1,$1B,1,$AF,1
670 DATA $1D,1,$19,1,$1D,1,$16,1,$1A,1,$18,1,$1A,1,$1B,2
675 DATA $B5,1,$C9,1,$1C,1,$19,1,$1B,1,$18,2,$19,1,$1C,1
680 DATA $1B,1,$1D,1,$91,1,$B5,1,$1A,1,$19,1,$1A,1,$91,1
685 DATA $C9,1,$1B,1,$19,1,$1A,1,$17,1,$1C,1,$91,1,$C9,4
690 DATA $AF,1,$C9,5,$91,1,$1B,3,$16,1,$1B,3,$18,1,$19,1
695 DATA $C9,1,$1A,1,$17,2,$AF,1,$18,1,$AF,1,$1B,1,$91,1
700 DATA $19,1,$1A,1,$AE,1,$B5,1,$18,1,$17,1,$18,1,$C9,1
705 DATA $19,3,$1B,2,$19,1,$AE,1,$1B,3,$18,1,$AE,1,$C9,1
710 DATA $1A,1,$14,1,$1C,1,$1B,1,$91,1,$1B,2,$C9,1,$19,1
715 DATA $AE,1,$1B,3,$C9,5,$AF,1,$C9,47,$18,1,$C9,3,$18,1
720 DATA $C9,11,$17,1,$AE,1,$C9,62,$17,1,$13,1,$14,1,$C9,60
725 DATA $16,1,$14,1,$00,1,$14,1,$16,58,$AF,1,$17,1,$14,1
730 DATA -1,-1 :REM TRIGGERS READ-LOOP END

That's it.


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Thu Jan 14, 2021 11:07 pm
by Lorin Millsap
You should be using VPOKE.


Sent from my iPhone using Tapatalk

BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Thu Jan 14, 2021 11:21 pm
by rje


40 minutes ago, Lorin Millsap said:




You should be using VPOKE.



Yeah, fiddling with the registers directly isn't perfectly safe.

But how does VPOKE handle auto-increment?  (Because it doesn't out of the box...) I didn't see documentation on VPOKE DOES AUTO-INC.  Only the VERA doc talks about auto-increment, while only the "Programmer's Reference" talks about VPOKE.  We need some bridging documentation...


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 3:25 am
by Ender


4 hours ago, rje said:




Yeah, fiddling with the registers directly isn't perfectly safe.



But how does VPOKE handle auto-increment?  (Because it doesn't out of the box...) I didn't see documentation on VPOKE DOES AUTO-INC.  Only the VERA doc talks about auto-increment, while only the "Programmer's Reference" talks about VPOKE.  We need some bridging documentation...



Actually, I don't think you could use VPOKE in this instance.  Under the hood, VPOKE simply sets the address at $9f20-$9f22 and pokes the value into $9f23. Theoretically, you could set the first argument, the bank, to 16 to set the increment bit, since it's just poking that value to $9f22. However, the incrementing wouldn't work with calling VPOKE continuously since it's explicitly setting the address each time.  I just tried it with an experiment and it didn't seem to increment. You could probably use VPOKE for the first piece of data though, to set the address, and just poke to $9f23 after that. It should in theory be a tiny bit faster since the setting up of the address is being done in assembly instead of BASIC. Less lines of code too.


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 3:44 am
by rje

Thanks Ender - I might try that.  Perhaps the VPOKE's first argument sets ALL of $9f22?  So I could VPOKE $16, $4000, data?  Sounds dangerous...

 

(Sorry: I meant VPOKE $10, $4000, data)


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 3:50 am
by Ender


1 minute ago, rje said:




Thanks Ender - I might try that.  Perhaps the VPOKE's first argument sets ALL of $9f22?  So I could VPOKE $16, $4000, data?  Sounds dangerous...



Yup, it just takes the value of the first argument and stores it into $9f22.  (Though I think it would be decimal 16, not hex). Actually, taking a closer look at your code, it might not be less lines of code, given the way you're doing runlength.


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 4:04 am
by rje

D'oh, yes, but you got my drift.  I was getting excited.

 

I can replace three of those set-up lines with a single:

VPOKE %10000, $4000, 0

 

And yeah, that works!  Thanks!


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 9:21 am
by Guybrush

Your RLE format is somewhat hungry for memory space ?.

I'd use a [RunLength], [Value] format where RunLength's MSB indicates whether it's followed by a single byte value that is repeated N times, or by N bytes that are only used once.

So, a data stream that looks like ABCDDDDDDDEFGHIJJJJJJ would be stored as 3,A,B,C,135,D,5,E,F,G,H,I,134,J for a total of 14 values, while your format would be A,1,B,1,C,1,D,7,E,1,F,1,G,1,H,1,I,1,J,6 for a total of 20 values. The difference would be even greater if there are many non-repeated values.

Of course, this could be extended to indicate, for instance, that what follows is a pattern of M values that should be repeated N times, by using a few bits of the RunLength byte.


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 5:56 pm
by StephenHorn


8 hours ago, Guybrush said:




Your RLE format is somewhat hungry for memory space ?.



I'd use a [RunLength], [Value] format where RunLength's MSB indicates whether it's followed by a single byte value that is repeated N times, or by N bytes that are only used once.



So, a data stream that looks like ABCDDDDDDDEFGHIJJJJJJ would be stored as 3,A,B,C,135,D,5,E,F,G,H,I,134,J for a total of 14 values, while your format would be A,1,B,1,C,1,D,7,E,1,F,1,G,1,H,1,I,1,J,6 for a total of 20 values. The difference would be even greater if there are many non-repeated values.



Of course, this could be extended to indicate, for instance, that what follows is a pattern of M values that should be repeated N times, by using a few bits of the RunLength byte.



That's a useful tip. I did my own RLE expander in assembly, and while I didn't think to do that, I'm totally going to add it.


BASIC: Load Runlength-encoded Sprite data into VERA RAM

Posted: Fri Jan 15, 2021 6:55 pm
by Guybrush


51 minutes ago, StephenHorn said:




That's a useful tip. I did my own RLE expander in assembly, and while I didn't think to do that, I'm totally going to add it.



Yeah, it's really much better suited for assembly since you can simply test the MSB with BPL or BMI after loading.