Commodore BASIC as a Scripting Language for UNIX and Windows – now Open Source

Update: The source is available at github.com/mist64/cbmbasic

Attention Slashdot crowd, here is a little background:

This application is a recompiled version of the original Commodore 64 binary – it is not a reimplementation, so while it runs at pretty much the maximum possible speed, it is still 100% compatible. The huge C file in the archive has been produced by feeding the original 6502 code into my static recompiler and optimizing it with LLVM. The original operating system interface (character I/O, LOAD, SAVE etc.) has been reimplemented in native C, so Commodore BASIC interfaces nicely with OS X/Windows/Unix – you can use pipe I/O, and you can pass the filename of a BASIC program on the command line.

Yes, you could also just run a standard C64 emulator, but it wouldn’t be nearly this speed, and everything would run inside a sandbox; and there would be no way to interface this to your OS.

A while back, I released Apple I BASIC and Commodore BASIC as a scripting language for Mac OS X 10.5 on Intel. It did not work on any other OS or on a different CPU type.

Today, we are releasing Commodore BASIC as a Scripting Language – it works on Linux, Windows, Mac OS X 10.4/10.5 (Intel and PowerPC), and you even get the source, so you can adapt it to other operating systems and CPUs.

Download it here: cbmbasic.zip

The archive comes with binaries for Mac OS X and Windows. The source compiles on Linux, Windows and Mac OS X. All code is BSD-licensed. Main work by Michael Steil, speed optimizations, Linux and Windows fixes by James Abbatiello.

The core of the BASIC interpreter is in the file cbmbasic.c, which is platform, endianness and bitness independent. For all I/O, it calls out into runtime.c, do it should be able to adapt this project for any OS by just changing runtime.c.

All function calls that the core interpreter can’t handle end up in kernal_dispatch() in runtime.c, where a switch statement dispatches these to C functions. For Commodore BASIC, runtime.c has to support several Commodore KERNAL library routines. Some of them are very important (CHRIN, CHROUT) and some are only used for certain BASIC statements (LOAD, SAVE, OPEN, SETTIM). runtime.c does not implement all functions yet.

Feel free to port cbmbasic to your system and architecture of choice, and extend runtime.c to support more functions. If you like, send your changes back to us (mist64<at>mac<dot>com, abbeyj<at>gmail<dot>com), so we can update the main project and give your changes to everyone. We’re also interested how fast you can get it with different compilers and settings.

See my old article for more info as well as some insights on how it is done.

See also:

99 thoughts on “Commodore BASIC as a Scripting Language for UNIX and Windows – now Open Source”

  1. I like the effort but the code is indeed completely unreadable. cbmbasic.c is a whopping 1.2Mb, which is really insane.

    Reply
  2. @DusK, bart: The code is statically recompiled 6502 code – there is no way to make it more readable. 🙂

    Also, this is a very nice test for compilers. Intel’s C Compiler for example refuses to optimize it, because the function is too big.

    Reply
  3. i’m not involved in the develop of cbmbasic, so i just try to guest.
    i think the cbmbasic.c file is generated by llvm (low level virtual machine) so to modify it you need to change the source llvm file (mist64 and abbeyj mike think you share it?) or the llvm back-end (not an easy task).

    Reply
  4. @lorenzo: Correct, LLVM is used to do a first pass of optimization and create C code that works with many C compilers. The input to LLVM is (simplified) the original 6502 code of Commodore BASIC. I’m sorry, but nothing more readable exists.

    Reply
  5. Why can’t I run the scripts/games that you have linked to in the other article? It just keeps giving “STRING TOO LONG” error.

    Running linux here btw.

    Reply
  6. Port TI-Extended Basic with Speech Synthesizer support so we can recall the wonderful days of gosub/return call char, call hchar, call vchar, call sprite, call coinc and call sound…

    Reply
  7. This is really useful! Are you going to support redirection of a stdin pipe where “INPUT” doesn’t print the “?” like in apple1basic? Also, it would be nice if it weren’t so strict with inputs being in caps, but there’s probably a reason for it being that way that I don’t understand. Oh, and I noticed the Windows port likes to put #’s after printing out variables or the input. When I fullscreen, it’s shown as a garbage character.

    The .bas file referenced below just prints the input after “YOU SAID “:

    C:cbmbasic>echo test | cbmbasic.exe test.bas
    ?#
    YOU SAID test

    C:cbmbasic>

    Reply
  8. @hiroshi: You might be seeing the PETSCII 0x1D characters (CSR RIGHT) – when the screen is the current output device, it replaces some SPACE characters with this. You can support this in CHROUT. Patches are welcome. 🙂

    Reply
  9. @Keptwench: I’m actually working on getting Amiga programs working in my recompiler, yes. And James recently got some DOS programs working.

    Reply
  10. Does this mean we could see AmigaDOS and other programs running natively, without having to use such things as UAE?

    Reply
  11. @Ghostwolf: The idea is to run Amiga applications that only use exec.library and dos.library calls and don’t do UI or access hardware directly, natively on modern systems.

    Reply
  12. For those who are interested in running AmigaOS applications natively, please see the AROS project: http://aros.sourceforge.net/

    This project recreates the Amiga’s entire API in a portable manner, including but not limited to graphics.library and intuition.library. It runs under Windows, Linux, and even on bare metal. In essence, it is the closest thing you can get to an open source edition of AmigaOS Classic.

    No emulator needed.

    Reply
  13. I just left a comment, but it didn’t appear. No indication that it was awaiting moderation either. Just . . . nothing.

    Reply
  14. Trying again:

    For those who are interested in running Amiga applications under your OS of choice, without the use of an emulator, please see the AROS project at http colon slash slash aros dot sf dot net. (Sorry for the URL munging, but it looks like this commenting system pukes on URLs). No emulation involved; the only requirement is to recompile the Amiga application to your host environment. AROS is the closest thing to an open source AmigaOS Classic you’ll ever find.

    Reply
  15. It seems like this is CASE SENSITIVE and all BASIC commands have to be in CAPS! Is there an easy way to change this?

    thanks!

    Reply
  16. @Bob: You could change CHRIN() in runtime.c to make all input uppercase, but then you would lose the possibility to use lowercase in strings. Another idea would be to swap upper case and lower case on both CHRIN() and CHROUT() – so keywords would have to be lower case, but BASIC would preserve the case.

    Commodore BASIC had hooks for external extensions in the tokenizer, detokenizer and interpreter; I’m thinking about providing these hooks to runtime.c. 🙂

    Reply
  17. Is there a possibility that we could see a version of amiga basic also? But This is wonderful; just to run old C-64 programs.

    Reply
  18. Now if you can figure out how to read my old 5.25″ floppies that failed to read because my floppy reader was “out of alignment” you’d be my hero!

    Long live C-64!

    Reply
  19. Michael: your “recompiler” and your words about your work related to Amiga programs really impresses me! I would like to know more about it. Precisely I would like to know in what extend it could be ported to AROS which could provide almost all native functions as it reimplements original libraries from scratch (and that means it’s not limited to dos and exec). And what about recompiling third-party #?.library #?.device and so on? What do you think? Am I only dreaming?

    Reply
  20. Is there a way to quit infinite loops and go back to the interpreter? I’m afraid my PC’s keyboard lacks RUN/STOP.

    Reply
  21. my standard test of a BASIC is to run a for/next loop and then print the counter number. on this Basic I get a strange printed thingy after each print. try it

    10 FOR N = 1 TO 10
    20 PRINT N
    30 NEXT N

    Reply
  22. Wow, what a great idea!, but do i have to do a lot of “poke” and “peek” to get high resolution graphics and sound?:)

    Reply
  23. Where did you get the idea to use CBM basic for scripting on a modern OS? The first computer I ever had was a C64, when I was about 8 years old in 1990. I started learning to program, but never really got the knack for it until I discovered GFA Basic for my next computer, an Atari ST, a couple of years later.
    I quickly came to feel that C64 basic sucked horribly, was inexpressive, hard-to-use and unfriendly – at least compared to GFA (not having line numbers was another nice thing :)).

    Reply
  24. I’m able to run cbmbasic scripts but can anyone tell me how to run code in direct mode?
    All I get is syntax errors.

    Reply
  25. You are aware that the Commodore 64 used the Motorola 6510 processor, correct? It was the Vic-20 that used the 6502. Can you be sure that this is 100% compatible with the Commodore 64’s version of basic?

    Reply
  26. Either way the 6510 is 100% compatible with the 6502, as it uses the same CPU die. The only difference is the added 6-bit I/O register and tristate logic.

    Reply
  27. Pingback: StooBlog v0.1
  28. The 6510 processor was NOT by Motorola! You’re thinking of the 65000 which was used in Macintoshes and the Amiga.

    The 6510 was from MOS semiconductor, who Commodore bought and owned. Ironically, the Apple II and the Atari 2600 used the 6502 processor and had to buy them from Commodore.

    Reply
  29. Versions of GWBASIC for Windows and Linux would be great too. I havnt got a clue how to do that myself. I love the simplicity of the old languages – makes them quicker to learn and use for the occassional programmer. A dBase language would be another contender for this treatment, since I’ve been searching for something I can use to create simple databases without success. Thanks very much for making this available.

    Reply
  30. This is so hot. My SGI Irix machine now is able to run legacy CBM BASIC much faster than in VICE. Now, how do I peek and poke the CRiMe graphics on my O2 ?

    Reply
  31. I think the Versions of GW BASIC for Windows and Linux would be great to,
    The old languages are makes them quicker to learn, Anyone using more static languages, such as C and C++, will be used to attaching debuggers to running programs.

    Reply
  32. Pingback: AIMP Standalone
  33. Hi!

    Hmm, cbmbasic.c looks as if it was generated.

    I’m writing a C64 emulator (http://svn.nomike.com/playground/trunk/emu/C64/ ), so do you still have the original source and generator of cbmbasic.c somewhere? If so, could I read it? I could use that in order to help me learn to use LLVM properly and/or debug the emu 🙂

    Since you have experience with LLVM, do you know how to use LLVM JIT for dynamic languages?

    The LLVM builder seems to be strangely datatype insistent.

    Reply
  34. It’s awesome to go to see this website and reading the views of all colleagues regarding this article, while I am also eager of getting know-how.

    Reply
  35. I will immediately clutch your rss as I can not to
    find your email subscription hyperlink or e-newsletter
    service. Do you’ve any? Please let me understand so that I could subscribe. Thanks.

    Reply
  36. Basic 3.5 from 264 series would be cool too. Since it is a much better basic to program in.

    Reply
  37. Hi Mick, thanks for this litte jam!
    I tried to compile under linux, and ther’s a small error here:

    33c33
    // unsigned char RAM[65536];

    In runtime.c just declare RAM as extern, as it’s already defined in cbmbasic.c

    Reply

Leave a Comment