Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mrspeaker/ebas2bas

Convert "ebas" files to standard C64 BASIC
https://github.com/mrspeaker/ebas2bas

basic basic-programming c64 commodore-64

Last synced: about 1 month ago
JSON representation

Convert "ebas" files to standard C64 BASIC

Awesome Lists containing this project

README

        

* EBAS2BAS
C64 BASIC, with some lil' conveniences: no line numbers required, and some other helpful transformations. This tool converts /.ebas/ files to standard C64 BASIC as a /.bas/ file.

What is an /.ebas/ file? It's a thing I made up, 'cause I am making a game which requires me to write /a lot/ of C64 BASIC, and I got annoyed at re-numbering things. Then I got carried away adding more features. *Unless you are me, you likely will have no use for this script*.

[[https://user-images.githubusercontent.com/129330/136657907-99987639-f516-42a7-b2aa-4905a4704705.gif]]

Here's an example of some "eBASIC":

#+BEGIN_SRC basic
# Position sprites
for n=4 to 9:
poke v+n,n*0x14:
next

# Print some text
print "{clear}"
~top
poke 0x286,n:
n=n+1
print "coding is basic ... ";
goto ~top
#+END_SRC

Running ebas2bas generates BASIC:
#+BEGIN_SRC basic
10 for n=4 to 9:poke v+n, n*20:next
20 print "{clear}"
30 poke 646,n:n=n+1
40 print "coding is basic ... ";
50 goto 30
#+END_SRC

** Usage

#+BEGIN_SRC bash
node ebas2bas.js
#+END_SRC

You can omit the ~.ebas~ extension. The output will be the the same name, but with a ~.bas~ extension.

** Transformations

*** Line numbers & labels
#+BEGIN_SRC basic
~top
print "i am the best ";
goto ~top
#+END_SRC

compiles to:

#+BEGIN_SRC basic
10 print "i am the best ";
20 goto 10
#+END_SRC

*** Support for hex and binary numbers

Converts hex and binary numbers to decimal

#+BEGIN_SRC
0x1f -> 31
0b111 -> 7
0b1000_0001 -> 129
#+END_SRC

*** Comments

Comments with "#" are removed from the source code (You can still use REM comments if you want them to stay).

#+BEGIN_SRC
poke 0xD020,1 # Make border white -> poke 53280,1
#+END_SRC

*** Multi line source

Most BASIC programs jam many statements onto a single line. To keep the source readable, you can use multiple lines - then any ending with ":" will be concatenated.

#+BEGIN_SRC basic
for n=0 to 62 :
read q :
poke 0x340+n,q :
next
#+END_SRC

compiles to:

#+BEGIN_SRC basic
10 for n=0 to 62 :read q :poke 832+n,q :next
#+END_SRC

*** Include files
External files can be included into the current source with ~{{ "./path/to/file" }}~. The contents of the file will be dumped in the first pass, so all further transformations (hex, macros, etc) will be applied to the included contents. Include files can also contain other includes (with no circular dependency testing, so becareful!).

As the include file is dumped directly, it can also be assembly code, or macros. If it's assembly, remember to wrap the include tag in an inline-assembler tag (see section ~inline assembler~) if needed. Eg: ~{{! {{ "./test.asm" }} !}}~.

*** Macros
Macros are javascript functions that return BASIC source code that is injected in the final listing. If the return value is an array, multiple lines will be injected. To define a macro, wrap a javascript function in ~{!~ and ~!}~ tags:
#+BEGIN_SRC js
{! rainbow = (str) => {
const cols = COLS.slice(1); // COLS = Magic array of color tokens
return str
.split("")
.map((ch,i) => "{" + cols[i % cols.length] + "}" + ch)
.join("");
} !}
#+END_SRC
This defines a macro called ~rainbow~ that splits an input string into characters, then changes the color of each character using the standard basic color codes (eg ~{wht},{red}~). To call a macro, wrap a function call in ~{{~ and ~}}~ tags:
#+BEGIN_SRC basic
print "hello, {{ rainbow("world") }}!"
REM compiles to:
10 print "hello, {wht}w{red}o{cyn}r{pur}l{grn}d!"
#+END_SRC
*** Inline assembler
Inline assembler can be compiled with [[http://www.theweb.dk/KickAssembler/Main.html][KickAssembler]], and the bytes are then injected into the BASIC listing via POKES and run with a SYS call.

#+BEGIN_SRC asm
{{!"set screen colors via asm"
*=$c000
lda #0
sta $d020
sta $d021
rts
!}}
#+END_SRC

Compiles to:
#+BEGIN_SRC basic
10 rem set screen colors via asm
20 for za = 0 to 8:read zb:poke 49152+za,zb:next za
30 sys 49152
40 data 169,0,141,32,208,141,33,208,96
#+END_SRC

The title string is optional, and will be included in a REM statement if present. If you don't specify a base memory location (with the KickAssembler definition (eg, ~*=$c000~) it will use the default (I think it's ~$801~? Which is not good for BASIC!). But if you specify the base in your first inline asm block, subsequent blocks can continue on from the last address by putting a ~*~ after the opening tag.

For example, the above asm is located from ~$c000~ to ~$c008~ (49152-49160 decimal). If you start the next asm block with ~{{!*~, it will POKE the bytes into location ~$c009~ (49161 decimal).

** Options
Sorry, no CLI options yet. Settings are defined in [[https://github.com/mrspeaker/ebas2bas/blob/main/ebas_config.json][ebas_config.json]]:

#+BEGIN_SRC json
{
"LINE_SPACING": 10,
"OUTFILE_PATH": "./",
"KICKASSEMBLER_PATH": "/usr/lib/KickAssembler/",
}
#+END_SRC

- *LINE_SPACING* is how to sequentially number your source code. Default is 10, but you might just want 1 (or 5, or whatever).
- *OUTFILE_PATH* indicates where to dump the output file. Default is in the current directory.
- *KICKASSEMBLER_PATH* is the path to the KickAssembler compiler jar file if you want to do inline assembler.

** Running .bas files on a C64
My use case is to convert the .ebas file to plain C64 BASIC, then compile /that/ into an optimised C64 ~.prg~ file with Egon Olsen's fantastic [[https://github.com/EgonOlsen71/basicv2][BASICv2]] ~mospeed~ java command line tool:

#+BEGIN_SRC bash
./mospeed.sh -target=test.prg test.bas
#+END_SRC

The ~.prg~ file can then be loaded into Vice or another emulator (or, you know, run on a real Commodore 64!).