Useful BASIC and KERNAL extensions for the X16

Chat about anything CX16 related that doesn't fit elsewhere
Post Reply
rje
Posts: 1263
Joined: Mon Apr 27, 2020 10:00 pm
Location: Dallas Area

Useful BASIC and KERNAL extensions for the X16

Post by rje »


IF


  • Typical development is cross-development on the emulator.


  • The focus is on games and experimenting with the expansion slots.


THEN


  • What BASIC extensions would be useful?


  • What KERNAL extensions would be useful?


 

I think ways to LOCATE the cursor on the screen might be useful in this context.

 

SlithyMatt
Posts: 913
Joined: Tue Apr 28, 2020 2:45 am

Useful BASIC and KERNAL extensions for the X16

Post by SlithyMatt »


You can already do this with the kernal. The PLOT subroutine sets or gets the position based on the Carry bit.

kelli217
Posts: 535
Joined: Sun Jul 05, 2020 11:27 pm

Useful BASIC and KERNAL extensions for the X16

Post by kelli217 »


And it's fairly easy to use, with the minor exception that it uses X for Y and vice versa.

rje
Posts: 1263
Joined: Mon Apr 27, 2020 10:00 pm
Location: Dallas Area

Useful BASIC and KERNAL extensions for the X16

Post by rje »


Yes.  How about a BASIC LOCATE, then?

More controversially, there could be VERA BASIC commands for sprite and PSG handling.

 

SPRITE

Sprite registers are bitfield-packed.  BASIC commands could make the data easier to handle by taking separate parameters.  Commands could be simple or APIs with multiple fields.

 

SOUND

And it would be mighty nice to have BASIC commands that could allow me to trigger a BANG or PING sound.  It would be trickier than sprites, because pseudo-envelopes would probably run on an interrupt as shown elsewhere in this forum.  So that means the BASIC command would set up and call a ML API to said interrupt ML.

BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

Useful BASIC and KERNAL extensions for the X16

Post by BruceMcF »



On 3/2/2021 at 11:48 PM, SlithyMatt said:




You can already do this with the kernal. The PLOT subroutine sets or gets the position based on the Carry bit.



Quite. That would be the keyword: parse the parameters, call PLOT.

SPRITE and SOUND are V7 Basic keywords that would have to have the parameters redefined to fit the CX16 context. Trickiest is that IIRC, V7 Basic allows setting the ADSR envelope, but only the FM chip has hardware ADSR, so if following the V7 approach more closely, it would be a SOUND command for the FM, when a SOUND command for the PSG would seem to be more useful for simple applications in Basic.

rje
Posts: 1263
Joined: Mon Apr 27, 2020 10:00 pm
Location: Dallas Area

Useful BASIC and KERNAL extensions for the X16

Post by rje »


Here's something I've wanted at least three times now: a "BASIC blitter" or something, that can print strings stored in banked RAM.

I'm doing this a lot:

for x = a to a+15 :n$=n$+chr$(peek(x)) :next x

My inner garbage collector dies a little every time I do this.

Maybe I can set the accumulator from BASIC and then call CHROUT in that loop? e.g.

 

for x = a to a+15 :poke 780, peek(x) :sys $FFD2 :next x

 

OKAY, I'VE ANSWERED MY OWN QUESTION: yes, it works.

It's still clunky, but at least it doesn't offend my inner gc.

 

TomXP411
Posts: 1785
Joined: Tue May 19, 2020 8:49 pm

Useful BASIC and KERNAL extensions for the X16

Post by TomXP411 »



1 hour ago, rje said:




Here's something I've wanted at least three times now: a "BASIC blitter" or something, that can print strings stored in banked RAM.



I'm doing this a lot:




for x = a to a+15 :n$=n$+chr$(peek(x)) :next x



My inner garbage collector dies a little every time I do this.



Maybe I can set the accumulator from BASIC and then call CHROUT in that loop? e.g.

 




for x = a to a+15 :poke 780, peek(x) :sys $FFD2 :next x



 



OKAY, I'VE ANSWERED MY OWN QUESTION: yes, it works.



It's still clunky, but at least it doesn't offend my inner gc.

 



There is already a feature request on the ROM Github page. 

While there's been some discussion about the actual implementation, the basic idea has definitely been put forward to the team. Short version, is I proposed PEEK and POKE for all of the basic data types, along with a BANK statement to make it simpler to access banked memory with all of the BASIC memory commands. 

So let's skip to how to do it NOW....

Cheat and hack the variable table. The VARTAB variable lives at $03E2 on the CX16. (Look at the "basic.sym" file included with the emulator.)

Start by creating a string that you don't intend to use. I'll use B$ in my example.

image.png.3849f858e8eec91c74879c11f53757d0.png

Looking at $3E2, we see the table is actually at $0811

so lets look at $0811, we get:

42 80 - B$ (B is ASCII 42, and 80 is the internal flag for $). 

04 - the string is 4 bytes long

09 08 - data is stored at $0809 in memory. Let's confirm this:

image.png.7c25bb4a40b35594d330f2333e725730.png

There it is! ABCD

and this is actually pretty smart... if we examine memory from the start of our program ($801), we see that $809 is actually the location of the string literal itself. Check it out:

image.png.7c7e9953a2c6564c94730cb34111abe5.png

So the interpreter actually just pointed the string pointer directly inside the program.

So we can hack this by pointing to a different place in memory and reading our string from there. Let's write the numerals 1-8 to $400 

image.png.7d6e2521d858add68618a565b9c43b6c.png

Now modify the variable table

image.png.50d343503c30b4a08e6db63d67d05aa0.png

By changing the address to $00 04, we point the start of the string to $400

And by changing the 04 to 08, we can make the string 8 bytes long. 

This results in:

image.png.42428f9d43468d2da631fb6159ef2023.png

It's a little more complex to put this into BASIC, but we can do it:

This program writes all of the PETSCII characters to the $400 space, then changes B$ to point to the @ sign. It makes B$ 32 bytes long, so we should see the whole alphabet, plus a few extra characters:

image.thumb.png.d8eef78b5d0bc9dee6127d1826520b71.png

Note the test for B$ on line 30. The variable table sets bit 7 of the second letter high on a string variable. So B$ is actually "B" followed by $80. 

Line 40 advances to the next variable in the table, and contains a sanity check to make sure we don't read past the end of BASIC memory. 

Finally, line 50 errors out if we made a mistake. 

So using that technique, you should be able to point to any place in memory, including banked RAM. Just be careful to always set your bank register to the right location before trying to print or read B$.

 

 

 


image.png
image.png
Post Reply