Jump to content
  • 0
mobluse

How to detect Commander x16 BASIC vs e.g. Commodore

Question

Posted (edited)

How can I detect that it is Commander X16 BASIC that my BASIC program runs in and not a Commodore BASIC? Preferably an official way that doesn't change with ROM releases. If there are more models of Commander with different capabilities they should also be possible to detect.

In Commodore BASIC this is done using PEEK(65534) which gives 72 for C64, 23 for C128, 253/255 for C+4 and C16, and 114 for VIC20. In X16 this was 35 when I tested, but I don't know if that can change.

I try to write BASIC programs that work on X16, C64, C128, and VIC20 (and perhaps GW-BASIC on IBM PC, MMBasic on Maximite, Applesoft BASIC on Apple II etc.). I want to set character width to between 20 and 40 (SCREEN 0) and similar colors, but have to do it in different ways depending on computer, but to have one version for each computer is a maintenance problem. The type of calculation program I'm writing doesn't demand much of the hardware.

10 IF NOT MODEL$="X16" THEN GOTO 30
20 SCREEN 0
30 IF NOT MODEL$="C128" THEN GOTO 50
40 GRAPHIC 0
50 REM REST OF PROGRAM...

Edited by mobluse

Share this post


Link to post
Share on other sites

23 answers to this question

Recommended Posts

  • 0
18 minutes ago, mobluse said:

In Commodore BASIC this is done using PEEK(65534)

I'm not sure whether this is officially documented anywhere, or is just a trick that is commonly used to identify Commodore systems in software. Regardless, that location is not specifically dedicated to system identification on any computer. The actual purpose of this location is the 6502 interrupt vector, which just happens to be different on every Commodore system. If the ROM is updated and the location of the interrupt routine changes, this value will change as well.

Share this post


Link to post
Share on other sites
  • 0

After doing a bit more research on Commodore BASIC, I am concerned that a program like this:

54 minutes ago, mobluse said:

10 IF NOT MODEL$="X16" THEN GOTO 30
20 SCREEN 0
30 IF NOT MODEL$="C128" THEN GOTO 50
40 GRAPHIC 0
50 REM REST OF PROGRAM...

will not work. The reason is that Commodore BASIC tokenizes keywords as they are typed in, converting a string such as "PRINT" into a single byte. The strings of characters that make up keywords are meaningless to BASIC when injected directly into memory, therefore bypassing the tokenizer; doing so will cause a syntax error. Due to the space saved when a program is tokenized, programs are saved and loaded in this form. As a result, BASIC does not scan for keywords while loading a program. The issue is that the GRAPHIC keyword would not be recognized by the tokenizer of the X16, and would be preserved as a string of characters when the program is saved. When loaded on a C128, there would be a syntax error on line 40. To make this approach work, you would either need to re-tokenize the program before running it, or use a custom tokenizer that understands the keywords of all Commodore systems.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0

Well, there is a "signature" starting at $FFF6 in bank 0, that's set to "MIST", after Michael Steil's online handle (mist64).  On a C64 this is set to "RRBY", which is apparently the initials of two of the main engineers that worked on the C64.  Looking in VICE, on a C128, this is just set to $FF,$FF,$24,$E2.

  • Like 2

Share this post


Link to post
Share on other sites
  • 0

This difference on $FFF6=65526 could be used, but I stick to 65534 so far.

Initially I was thinking about type-in programs or programs imported from text, but this could work for tokenized programs if SCREEN and GRAPHIC had the same token.

10 IF NOT PEEK(65534)=35 THEN GOTO 30
20 SCREEN 0
30 IF NOT PEEK(65534)=23 THEN GOTO 50
40 GRAPHIC 0
50 REM REST OF PROGRAM...

A worse matter is that I have not succeeded to load a tokenized C128 program into x16emu even if it only contains PRINT instead of SCREEN/GRAPHIC. If I do, it's only an empty program. Tokenized BASIC programs should be portable between Commodore type computers such as Commander X16, I think, provided they use the same tokens. I can load a tokenized C64 program into x16emu. I include programs generated by petcat in Linux that is included with VICE 3.4 (in my case).
p=x16c128 ; cat $p.bas | awk '{print tolower($0)}' | petcat -w2 -o $p.prg
cp x16c128.prg X16C128W2.PRG
p=x16c128 ; cat $p.bas | awk '{print tolower($0)}' | petcat -w70 -o $p.prg
cp x16c128.prg X16C128W70.PRG

Both programs can be loaded and run in xvic, x64, x128, and x128 -80col (from VICE), but only X16C128W2.PRG loads in x16emu.

x16emu -prg X16C128W2.PRG
x128 -80col -basicload -autoload X16C128W2.PRG
In the case with C128 and 80 columns one has to enter VICE configuration and switch screen.

X16C128W2.PRG X16C128W70.PRG x16c128.bas

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

Ultimately, no detection system is as simple and uses as little space as just adding 

SYSTEM=1 :REM C64=1, 128=2, X16=3 

As the first line of your program.  So I don’t bother trying to detect a system when writing code that targets generic BASIC 2. I just set the configuration at the start of the program. 
 

and it’s possible the reason tokenized files are failing to load is the start address. I don’t remember if the 128 uses the same start address as the 64,  but if it is not $801, then the program may get loaded to the wrong place in memory. 

Edited by TomXP411
  • Like 1

Share this post


Link to post
Share on other sites
  • 0

X16C128W70.PRG can be loaded if you load it from within the emulator, with SD card support turned off. When you do this, the program works fine. I believe that using the other load methods, the file is loaded at the location specified in the header, rather than the beginning of BASIC memory.

Share this post


Link to post
Share on other sites
  • 0
12 minutes ago, TomXP411 said:

And, it’s possible that the reason entokenned files are failing to load is the start address. I don’t remember if the 128 uses the same start address as the 64, but if it is not $801, then the program may get loaded to the wrong place in memory.

C128 BASIC programs load at $1C01.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0

It seems the load address of BASIC programs in X16 is the same as in C64 i.e. $0801, because I saved a program from x16emu and used hexdump in Linux.

I can LOAD "X16C128W70.PRG" inside x16emu, but when I use
x16emu -prg X16C128W70.PRG,0801
it only loads the first line. Strange! xvic, x64, xplus4 in VICE doesn't have this problem. It is possible to load the C128 program in xpet if I hack the start address to $0401 using hexcurse in Linux:
xpet -autoload X16C128W70PET.PRG

There is a new video about loading in Commodore type computers: LOAD"*",8 vs. LOAD"*",8,1 on the Commodore 64 from 8-Bit Show And Tell.

 

Share this post


Link to post
Share on other sites
  • 0
1 hour ago, mobluse said:

I can LOAD "X16C128W70.PRG" inside x16emu, but when I use
x16emu -prg X16C128W70.PRG,0801
it only loads the first line. Strange!

In memory, each line of BASIC contains a pointer to the address of the next line. Loading from within the emulator changes these pointers, while loading using the -prg option doesn't.

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

Edit: THIS IS WRONG, BECAUSE WHEN I TEST IT NOW IT DOESN'T WORK.

But it works in xpet and x64 if I change the two start bytes in the C128 file (X16C128W70.PRG) to the correct address for the computers, respectively, and load as machine code with e.g.:
x64 -autoload X16C128W7064.PRG
That uses:
load "X16C128W7064.PRG",8,1

It also works if I load using:
LOAD "X16C128W7064.PRG",8,1
in x16emu.

That would mean that if you load with ',1' it also changes the pointers, but that would make it difficult to load machine code in C64, since LOAD would change the two bytes after a 0, but I've never heard that is a problem. Does the LOAD"*",8,1 detect if it is a BASIC or machine code program, and try not to modify pointers if it is machine code?

Also if people write machine code assuming -prg doesn't change the code, then they might not be able to run the program from within x16emu or the real computer.

Edited by mobluse
I must have mixed the programs.

Share this post


Link to post
Share on other sites
  • 0

I do not believe BASIC can tell the difference between an assembly program or a BASIC program. However, most assembly programs begin with a header written in BASIC that jumps to the actual code. When changing addresses, the system stops at the end of this header, leaving the code intact. As for programs that do not include a BASIC header, BASIC considers a pointer to $0000 to be the end of a program. Programs that do not use a BASIC header likely just include two zero bytes at the beginning.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
On 3/22/2021 at 4:16 AM, mobluse said:

But it works in xpet and x64 if I change the two start bytes in the C128 file (X16C128W70.PRG) to the correct address for the computers, respectively, and load as machine code with e.g.:
x64 -autoload X16C128W7064.PRG
That uses:
load "X16C128W7064.PRG",8,1

It also works if I load using:
LOAD "X16C128W7064.PRG",8,1
in x16emu.

That would mean that if you load with ',1' it also changes the pointers, but that would make it difficult to load machine code in C64, since LOAD would change the two bytes after a 0, but I've never heard that is a problem. Does the LOAD"*",8,1 detect if it is a BASIC or machine code program, and try not to modify pointers if it is machine code?

Also if people write machine code assuming -prg doesn't change the code, then they might not be able to run the program from within x16emu or the real computer.

The question is rather whether the x16emu is doing the ",1" option correctly. ",0" is "ignore the two leading bytes, load to the default Basic address", ",1" is "load to the address indicated by the two leading bytes". The two leading bytes are in any event never loaded, so there is nothing to "edit".

For purely Vic-20, C64 and X16 Basic, I think you can call the Kernel function SCREEN at $FFED that gives the screen dimensions, columns in X, rows in Y, and then the answer will both make it redundant to find out which one it is, and will also let you know which one it is.

The VIC-20 was the first CBM KERNAL that had the SCREEN call, so that doesn't work for PET 4000/8000's.

 

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

There are pointers to the next line in the BASIC lines, but the computer doesn't know what it is loading and updates the pointers anyway, but one can probably fix that by having the machine code after the last line of the program.

I think I can solve the original problem anyway by using SYS to set screen with to 40 characters in X16 and C128:
POKE 780,0:SYS 65375

screen_set_mode/$FF5F
https://github.com/commanderx16/x16-docs/blob/master/Commander X16 Programmer's Reference Guide.md#function-name-screen_set_mode

I could use screen/$FFED to get the rows and columns, but that doesn't seem to work on C128 - tested in x128 and x128 -80col:
SYS 65517:R=PEEK(782):C=PEEK(781)

BTW screen_set_mode in C128 is slightly different than in X16 since in C128 it switches between two different physical screens with different screen dimensions AFAIK. In the x128 emulator you have to switch screen manually in the configuration menu.

Edited by mobluse

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
8 minutes ago, mobluse said:

There are pointers to the next line in the BASIC lines, but the computer doesn't know what it is loading and updates the pointers anyway, but one can probably fix that by having the machine code after the last line of the program.

 

On 3/21/2021 at 2:16 PM, Elektron72 said:

I do not believe BASIC can tell the difference between an assembly program or a BASIC program.

The ,1 at the end means "this is a machine language program" (the Commodore does not know what to do with assembly code.)

I believe that if you load a program without the ,1 at the end, then BASIC will re-link the lines as you load the program. If you load it with the ,1 at the end, the re-linking should not happen. 

It's easy enough to test... create a 3 line program and set the link in the first line to skip the second line. Then load it with ,8 and ,8,1 and see what the results are. 

 

Edited by TomXP411

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

What do you mean would happen with the three line program where one line is skipped by linking in the cases ,8 and ,8,1 and x16emu -prg?

I have two programs 3LINES.PRG and 3LINES2.PRG. The last is the hacked version where line 1 links to line 3.

x16emu -prg 3LINES2.PRG
and LIST gives two lines, but LOAD with ,8 and ,8,1 gives three lines in both x16emu and x64 from VICE.

It seems that the program is repaired with both ,8 and ,8,1.

3LINES.PRG 3LINES2.PRG

Edited by mobluse

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

 

11 hours ago, TomXP411 said:

I believe that if you load a program without the ,1 at the end, then BASIC will re-link the lines as you load the program. If you load it with the ,1 at the end, the re-linking should not happen. 

This may be the intended behavior; if it is, then the emulator/ROM has a bug. I modified one of the test programs from above by changing the header so that it always loads at $0801. Here is a hex dump of the file prior to loading:

Quote

00000000: 0108 1c1c 0a00 8b20 a820 c228 3635 3533  ....... . .(6553
00000010: 3429 b233 3520 a720 8920 3330 0024 1c14  4).35 . . 30.$..
00000020: 0099 2030 003f 1c1e 008b 20a8 20c2 2836  .. 0.?.... . .(6
00000030: 3535 3334 29b2 3233 20a7 2089 2035 3000  5534).23 . . 50.
00000040: 471c 2800 9920 3000 621c 3200 9920 2252  G.(.. 0.b.2.. "R
00000050: 4553 5420 4f46 2050 524f 4752 414d 2e2e  EST OF PROGRAM..
00000060: 2e22 0000 00

Regardless of whether the ",1" is used or whether an SD card image is used, the emulator debugger shows this:

952391655_Screenshotfrom2021-03-2311-05-41.png.9146af95e2a779a761b0484be9c2d06c.png

The pointers have been changed. If these are not supposed to change when ",1" is used, the emulator and ROM need to be fixed.

X16C128W71.PRG

Edited by Elektron72

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

BASIC doesn't care about the second address; it merely passes that address to Kernal.

When you use the LOAD command -- at the "READY." prompt -- BASIC always does two things:

  1. Sets its end-of-program pointer to the value returned by Kernal.
  2. Tries to relink the line pointers, starting at the beginning of BASIC RAM.

Those actions can cause trouble.  For example, if you type in a program, then LOAD the VTUI library into "Golden RAM", then RUN your program, it will fail!  BASIC will put the program's variables at addresses immediately above VTUI instead of above the program.  (You must edit your program, again, so that BASIC will set that pointer back to the end of your program.)

Edited by Greg King

Share this post


Link to post
Share on other sites
  • 0
6 hours ago, Greg King said:

BASIC doesn't care about the second address; it merely passes that address to Kernal.

When you use the LOAD command -- at the "READY." prompt -- BASIC always does two things:

  1. Sets its end-of-program pointer to the value returned by Kernal.
  2. Tries to relink the line pointers, starting at the beginning of BASIC RAM.

Those actions can cause trouble.  For example, if you type in a program, then LOAD the VTUI library into "Golden RAM", then RUN your program, it will fail!  BASIC will put the program's variables at addresses immediately above VTUI instead of above the program.  (You must edit your program, again, so that BASIC will set that pointer back to the end of your program.)

Hrm... that seems problematic, especially for machine language programs. If BASIC tries to relink an ML program, it's going to alter and destroy the program. Does the relinking process start at $0801 or at the address the program was loaded to? 

Maybe the reason I have never seen this happen to programs loaded into $400 (or the 4K upper memory block on the 64) is that BASIC only relinks at the start of BASIC, not at the load address. (and breaks my above hypothesis.)

 

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
On 3/20/2021 at 10:17 PM, mobluse said:

A worse matter is that I have not succeeded to load a tokenized C128 program into x16emu

It appears the LOAD behavior is broken, and LOADing with or without the ,1 will result in the program being incorrectly loaded to $1C01. This violates the LOAD syntax rules. I just reported this as a bug on the Github page.

In the meantime, you can fix this by using a hex editor and updating the load address to $0801 if you are loading in programs written on the Commodore 128. Or you can load it into 64 mode without the ,1 then save it again. This should reset the load address to $801.

 image.png.be46dca49f118649a587a8e6284459e5.png

 

Edited by TomXP411

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

I could load the C128 program X16C128W70.PRG (above) in x16emu from the host file system using LOAD"X16C128W70.PRG" and LOAD"X16C128W70.PRG",8 but not using LOAD"X16C128W70.PRG",8,1. I've not tried to LOAD from SD card.

Also I do not get the text "SEARCHING...
LOADING FROM $..." but only "READY."

Maybe you have a different release than 38 or this is how it looks when you load from an SD card.

Anyway, I think loading should work in Commander X16 as in Commodore computers, because that is what most people expect and know how to handle.

Edited by mobluse

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
1 hour ago, mobluse said:

I could load the C128 program X16C128W70.PRG (above) in x16emu from the file system using LOAD"X16C128W70.PRG" and LOAD"X16C128W70.PRG",8 but not using LOAD"X16C128W70.PRG",8,1. I've not tried to LOAD from SD card.

Also I do not get the text "SEARCHING...
LOADING FROM $..." but only "READY."

Maybe you have a different release than 38 or this is how it looks when you load from an SD card.

Anyway, I think loading should work in Commander X16 as in Commodore computers, because that is what most people expect and know how to handle.

This is how it looks when loading from SD. 

What you see above is the actual CX16 ROM code loading a file. From what others have said, when LOADing from the host file system (ie: without an SD image mounted), the emulator traps the call to the LOAD command and injects the data into the virtual machine's memory. So that's not at an accurate simulation of how the real computer will work. 

Also, disk commands and the OPEN command only work on SD. They do not work when attempting to access files on the host file system.

 

Edited by TomXP411

Share this post


Link to post
Share on other sites
  • 0
5 hours ago, mobluse said:

...Maybe you have a different release than 38 or this is how it looks when you load from an SD card.

AFAIR, at present it's loading from an SD card/image that uses the current Kernel routines ... loading from the filesystem hosting the emulator is getting the file directly and putting it where it thinks it should go.

Share this post


Link to post
Share on other sites
  • 0

Good news... the new KERNAL fixes the load bug. 

Programs loaded with ,8 now properly start at $0801, no matter what address is at the beginning of the file, and programs loaded with ,8,1 properly load to the original address in the beginning of the file. 

I have confirmed it with a program saved from the Commodore 128, which has a different start of BASIC address.

This is in the new Proto 2 KERNAL that Michael announced on Friday, here: 

 

Someone also added BIN$ and HEX$ functions, to print binary and hexadecimal values: super convenient. 

 

 

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

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

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Please review our Terms of Use