Atari 2600 BASIC compiler is here!

I'm probably going to get a mix of praise and criticism for this. Anyway, I've written a BASIC compiler for the Atari 2600. Yes, you read that right. This is not a joke!

Of course there is no "print" statement, string operations or arrays... But I've managed to abstract some of the harder things to simple BASIC keywords and functions.

Also, it doesn't generate binaries directly, instead it converts them to an assembly file in DASM syntax, then invokes DASM to make a binary. It comes with a canned kernel with two players, two missiles, and asymmetric playfield and a 6-digit score, but it is possible for a somewhat-experienced programmer to make it work with almost any kernel.

It is my hope that folks will use this BASIC as a stepping stone to serious 2600/6502 programming, much like some of us did in the past on our C-64's, Apples or Atari 8-bits. Since it generates meaningful assemblies instead of binaries, I think this is likely, or at least I remain hopeful.

The included kernel uses a bitmapped 32x12 playfield and has easy to use scrolling routines too, which could be used to make a car racing game or something of that sort. Calling the display kernel is not automatic - you must use the drawscreen function.

[technical stuff]Also, the compiler generates pretty efficient code, or at least I think so. As long as you're not using too many of the playfield scrolling routines, I think (I hope) it's unlikely that you will exceed the time alloted for overscan/vblank. The compiler also inserts conditional compilation flags to prevent player graphics from wrapping page boundaries and can also be configured to automatically use branches instead of jumps where the target is near.

Also, I haven't abstracted out all 2600 intricacies - you still have direct access to any TIA register and can include inline assembly. In fact you must use TIA regs for some things, like colors and sound, but you access them just like any other variable.[/technical stuff]

To learn more, read the README file or ask me questions, or tell me I'm crazy or something since I have been critical about this very thing in the past...

This looks like a great idea. I think it will also make a good prototyping tool for experienced developers. It should allow a game idea to be tested before investing a lot of effort on a custom kernel. Unfortunately I can't actually run it as I am a Linux user, but I hope that you are going to release the C source at some point? Are you using LEX/YACC (Flex/Bison) to parse the source files as this should solve the spacing issues? You are probably not looking for suggestions yet, but I think that presenting the registers as 2D arrays would make some things easier to express, e.g. if CXM0P(7)=1 then ... I will be interested to watch how this develops.

This looks like a great idea. I think it will also make a good prototyping tool for experienced developers. It should allow a game idea to be tested before investing a lot of effort on a custom kernel. Unfortunately I can't actually run it as I am a Linux user, but I hope that you are going to release the C source at some point? Are you using LEX/YACC (Flex/Bison) to parse the source files as this should solve the spacing issues? You are probably not looking for suggestions yet, but I think that presenting the registers as 2D arrays would make some things easier to express, e.g. if CXM0P(7)=1 then ... I will be interested to watch how this develops.

Chris

I welcome any/all suggestions! My parser is written by me, and this is why it is so picky. I'll look into LEX and/or YACC to see how they can help, as the spacing issue is a little annoying.

Also, allowing TIA regs as arrays should be simple enough to implement.

I'll go ahead and post the source so others can compile it. Also, I am open to suggestions on how to improve the source too, if anyone notices anything funny.

EDIT: Bug found when compiled under Linux - has been fixed. If you are having problems, download the updated source below.

Thanks for the suggestions - I want to improve the kernel definitely since I want to free up enough cycles to display the ball. I've only got one byte of RAM to spare - so this equates to 1 cycle here. I tried using switchdraw at some point but I went back to skipdraw, but I can't remember why - I think it might have used up an extra byte of RAM or something. I'll look into this again and see if I can get it working with switchdraw. I also need to VDEL P1 at some point.

Thanks for the suggestions - I want to improve the kernel definitely since I want to free up enough cycles to display the ball. I've only got one byte of RAM to spare - so this equates to 1 cycle here. I tried using switchdraw at some point but I went back to skipdraw, but I can't remember why - I think it might have used up an extra byte of RAM or something. I'll look into this again and see if I can get it working with switchdraw. I also need to VDEL P1 at some point.

Yeah, SwitchDraw uses two bytes of RAM for every object. Might be worth scaring up some RAM for the extra cycles, though. Use SwitchDraw for both players and the code I posted for the three single-bit objects and you save 7 cycles altogether.

Maybe if you don't allow calls to DisplayScreen inside a subroutine? Kind of restrictive, but then you can use the 6 stack bytes for the temp variables you'll need.

Thanks for the suggestions - I want to improve the kernel definitely since I want to free up enough cycles to display the ball. I've only got one byte of RAM to spare - so this equates to 1 cycle here. I tried using switchdraw at some point but I went back to skipdraw, but I can't remember why - I think it might have used up an extra byte of RAM or something. I'll look into this again and see if I can get it working with switchdraw. I also need to VDEL P1 at some point.

Yeah, SwitchDraw uses two bytes of RAM for every object. Might be worth scaring up some RAM for the extra cycles, though. Use SwitchDraw for both players and the code I posted for the three single-bit objects and you save 7 cycles altogether.

Maybe if you don't allow calls to DisplayScreen inside a subroutine? Kind of restrictive, but then you can use the 6 stack bytes for the temp variables you'll need.

That should work. The compiler isn't smart enough to know if it's in a subroutine when displayscreen is called, so I'd either have to figure out how to do this and issue a warning, or just mention this restriction in the documentation. It should be worth it if I can get the ball on the screen.

I welcome any/all suggestions! My parser is written by me, and this is why it is so picky. I'll look into LEX and/or YACC to see how they can help, as the spacing issue is a little annoying.

I'll go ahead and post the source so others can compile it. Also, I am open to suggestions on how to improve the source too, if anyone notices anything funny.

Thanks - the source code compiles fine under Linux with gcc. Lex and Yacc should definitely help you - I wouldn't dream of writing my own parser anymore! Basically, Lex takes the input and converts it into lexical tokens which solves the spacing issue, e.g "if x then" becomes ["IF","VAR(X)","THEN"], and Yacc takes these tokens and converts them into a parse tree to match the grammar (and rejects any invalid syntax), e.g. ["IF", "IF"] would be rejected. I would offer to do this for you, but it has been several years since I used these tools. I will let you know if I think of any more suggestions.

I welcome any/all suggestions! My parser is written by me, and this is why it is so picky. I'll look into LEX and/or YACC to see how they can help, as the spacing issue is a little annoying.

I'll go ahead and post the source so others can compile it. Also, I am open to suggestions on how to improve the source too, if anyone notices anything funny.

Thanks - the source code compiles fine under Linux with gcc. Lex and Yacc should definitely help you - I wouldn't dream of writing my own parser anymore! Basically, Lex takes the input and converts it into lexical tokens which solves the spacing issue, e.g "if x then" becomes ["IF","VAR(X)","THEN"], and Yacc takes these tokens and converts them into a parse tree to match the grammar (and rejects any invalid syntax), e.g. ["IF", "IF"] would be rejected. I would offer to do this for you, but it has been several years since I used these tools. I will let you know if I think of any more suggestions.

Chris

Oh yeah, for anyone else using something other than DOS (I'm not using DOS myself) the following shell script may be helpful, which I used to compile sample.bas:

Thanks - the source code compiles fine under Linux with gcc. Lex and Yacc should definitely help you - I wouldn't dream of writing my own parser anymore! Basically, Lex takes the input and converts it into lexical tokens which solves the spacing issue, e.g "if x then" becomes ["IF","VAR(X)","THEN"], and Yacc takes these tokens and converts them into a parse tree to match the grammar (and rejects any invalid syntax), e.g. ["IF", "IF"] would be rejected. I would offer to do this for you, but it has been several years since I used these tools. I will let you know if I think of any more suggestions.

Chris

I can second that info about Lex and Yacc. We're currently using this to implement a mini debugger language in Stella, so one can type 'breakcond *A = 0xff, or something like that.

I was wondering whe somebody would come up with something like this
this will defently move my game developing ahead.
ironicly, I remember mentioning that if compare 2600 asm language to Ti-extened basic language it's not very different.(It's posted in the 2600 for beginers subforum I think)

I played around with it a bit, still get the "Warning: Unable to..." every time but it compiles ok. If I got the time i'll try and make a simple pong like game with it, always make a pong game on every new 'language' i learn.

I noticed you can't use negative numbers (-4) so made a little work around attached to this post, try it out it worked on StellaX.

It would look nicer if you could remove the extension someway so it will not look like dong.txt.bin (or dong.bas.bin) but dong.bin

BTW. there is an easter egg in the emulator just create a new file (empty.bin) of 0 bytes and (reload) open it with StellaX and watch the egg.

Thanks a = 0 - a worked , saves some lines, but at first i did got an "Cannot pars line |" error when trying to use "if X > 166 | x < 16 then a = 0 - a" so I gues thats not possible (yet).

Hope you'll get the ball thing going, now then "all" it needs is sound support and a nice ide something like notepad but then with quick instruction insertion and compile(&run) function. I could make something like that if you wantt.

Oh and can you make one of those wonderfull beep commands should be simple for you I gues or something like a sound (freq) command.

Thanks a = - a worked , saves some lines, but at first i did got an "Cannot pars line |" error when trying to use "if X > 166 | x < 16 then a = 0 - a" so I gues thats not possible (yet).

Hope you'll get the ball thing going, now then "all" it needs is sound support and a nice ide something like notepad but then with quick instruction insertion and compile(&run) function. I could make something like that if you wantt.

Oh and can you make one of those wonderfull beep commands should be simple for you I gues or something like a sound (freq) command.

It only handles simple if-then statements right now. I will add support for more complicated expressions if I can figure out how to do this

If you want to use sound, the TIA registers are easy enough to use, I just haven't explained how to use them in this BASIC yet. Anyway:

To make a beep, I'd set AUDC0 and AUDF0 at the beginning of the program. I think these might produce a good "beep" sound:

5 AUDC0 = 12 : AUDF0 = 3

then when the ball changes direction, you can also set AUDV0 = 15 to turn the sound on, then set AUDV0 = 0 sometime after the call to "drawscreen" which will keep the sound on for about 1/60th of a second, but should be perfect for a pong game. To keep the sound on longer, you would need to set up a counter or something of that sort and turn it off after several iterations through the game loop.

I have been talking about something like this for YEARS. People said it could not be done. Of course mine would probably be more in-depth than this one is, but this is a start and I'm gonna check it out.

It could be the start of an actually 2600 game design program or a 2600 development system. The way I envision my idea was a graphic editor built in, and different routines that could allow you to make a variety of games with little effort. Almost like a Gamemaker or Click N Play designed to make 2600 games.