Jump to content

Photo

Atari 2600 BASIC compiler is here!


427 replies to this topic

#1 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 4:10 AM

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...

Please try it out and tell me what you all think!

EDIT: This project now has a homepage! To get the latest builds as well as other tools and documentation in one place, go to http://alienbill.com/2600/basic/

EDIT: Alpha 0.2 has been released. Download "batari_basic_alpha2.zip" below. EDIT AGAIN: updated with slight bugfixes... download Alpha2 again if you already did.

Attached Files


Edited by batari, Tue Jul 19, 2005 2:06 PM.


#2 Cybergoth OFFLINE  

Cybergoth

    Quadrunner

  • 8,821 posts
  • This is Sparta!
  • Location:Bavaria

Posted Thu Jul 7, 2005 4:27 AM

Hi there!

Wow, sounds very cool, can't wait to try that!

Actually I think it's pretty good that it's 2-step, doing assembly code first. So one can probably use it to create a rough framework and then continue development in assembler.

Greetings,
Manuel

#3 PacManPlus OFFLINE  

PacManPlus

    River Patroller

  • 4,630 posts
  • Atari 7800 & NES Developer
  • Location:Florida

Posted Thu Jul 7, 2005 4:37 AM

Look forward to trying this - excellent job!

#4 cd-w OFFLINE  

cd-w

    Stargunner

  • 1,566 posts
  • Juno First!
  • Location:Glasgow, UK

Posted Thu Jul 7, 2005 6:06 AM

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

#5 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Thu Jul 7, 2005 9:15 AM

Looks cool, and fun. Good job! :D

A few comments on the 2600basic.asm kernel you have there...

Since it is a 2-line kernel, you should really use SwitchDraw instead of SkipDraw.

Also, rather than:
lda missile1height;3
 dcp missile1y;5
;c=1 active
 ldy temp4;3
; lda #0;14
; adc #1;16
 rol;2
 rol;2
 sta ENAM1;3
Use this to save a few cycles (at the expense of another byte of RAM):
lda missile1height;3
 dcp missile1y;5
;c=1 active
 ldy temp4;3
; lda #0;14
; adc #1;16
 sbc missile1adjuster;3 -- where missile1adjuster = missile1height - 2
 sta ENAM1;3
Saves 1 cycle for each missile and the ball.

#6 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 2:06 PM

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

View Post

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.

Attached Files


Edited by batari, Thu Jul 7, 2005 11:17 PM.


#7 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 2:16 PM

Looks cool, and fun.  Good job!  :D

A few comments on the 2600basic.asm kernel you have there...

Since it is a 2-line kernel, you should really use SwitchDraw instead of SkipDraw.

Also, rather than:

lda missile1height;3
 dcp missile1y;5
;c=1 active
 ldy temp4;3
; lda #0;14
; adc #1;16
 rol;2
 rol;2
 sta ENAM1;3
Use this to save a few cycles (at the expense of another byte of RAM):
lda missile1height;3
 dcp missile1y;5
;c=1 active
 ldy temp4;3
; lda #0;14
; adc #1;16
 sbc missile1adjuster;3 -- where missile1adjuster = missile1height - 2
 sta ENAM1;3
Saves 1 cycle for each missile and the ball.

View Post

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.

#8 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Thu Jul 7, 2005 2:21 PM

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.

#9 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 2:45 PM

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.

View Post

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.

#10 cd-w OFFLINE  

cd-w

    Stargunner

  • 1,566 posts
  • Juno First!
  • Location:Glasgow, UK

Posted Thu Jul 7, 2005 3:25 PM

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.

View Post


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

Edited by cd-w, Thu Jul 7, 2005 3:26 PM.


#11 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 3:41 PM

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.

View Post


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

View Post

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:
./2600bas<sample.bas>sample.asm
cat 2600basic.asm sample.asm 2600basicfooter.asm > test.asm
./dasm test.asm -f3 -otest.bin


#12 stephena ONLINE  

stephena

    River Patroller

  • 2,962 posts
  • Stella maintainer
  • Location:Newfoundland, Canada

Posted Thu Jul 7, 2005 4:47 PM

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

View Post

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.

Steve

#13 Dan Iacovelli OFFLINE  

Dan Iacovelli

    Quadrunner

  • 5,925 posts
  • Location:westchester,IL

Posted Thu Jul 7, 2005 6:54 PM

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)

#14 potatohead OFFLINE  

potatohead

    River Patroller

  • 4,397 posts
  • Location:Portland, Oregon

Posted Thu Jul 7, 2005 9:49 PM

Hello everyone,

Have been lurking for a very long time. Had a bit of free time today, thought I might give this project a quick try.

I compiled under Linux too. No worries there.

This worked for me, but for the last bit:

./2600bas<sample.bas>sample.asm
cat 2600basic.asm sample.asm 2600basicfooter.asm > test.asm
./dasm test.asm -f3 -otest.bin

I just worked through this and ran into a snag.

dasm says:

DASM V2.20.09, Macro Assembler 1988-2003
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
test.asm (766): error: Syntax Error ''.
test.asm (766): error: Syntax Error ''.
Unrecoverable error(s) in pass, aborting assembly!
Complete.

Specified the include directories on the command line, edited the test.asm file, what gives?

I'm assuming there is some prep for DASM that I don't know about? I just grabbed the latest package, copied the Linux binary into the working directory and ???

EDIT: Everything referenced in the test.asm file is in the same working directory.

Edited by potatohead, Thu Jul 7, 2005 10:19 PM.


#15 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 10:21 PM

One bug has been found so far - at the beginning of the 2600basic.h file, it attempts to include itself, which could be the cause.

If not, please post your test.asm file so I can take a look. I have not tested in Linux at all, just OSX and DOS so far, so it could very well be a bug. Yep, this is definitely an alpha version...

Hello everyone,

Have been lurking for a very long time.  Had a bit of free time today, thought I might give this project a quick try. 

I compiled under Linux too.  No worries there.

This worked for me, but for the last bit:

./2600bas<sample.bas>sample.asm
cat 2600basic.asm sample.asm 2600basicfooter.asm > test.asm
./dasm test.asm -f3 -otest.bin



I just worked through this and ran into a snag. 

dasm says:

DASM V2.20.09, Macro Assembler 1988-2003
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
test.asm (766): error: Syntax Error ''.
test.asm (766): error: Syntax Error ''.
Unrecoverable error(s) in pass, aborting assembly!
Complete.

Specified the include directories on the command line, edited the test.asm file, what gives?

I'm assuming there is some prep for DASM that I don't know about?  I just grabbed the latest package, copied the Linux binary into the working directory and ???

View Post



#16 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 10:42 PM

EDIT: for some reason my edit didn't take and got posted below... Anyway, please get the updated source above.

Edited by batari, Thu Jul 7, 2005 11:15 PM.


#17 Zach OFFLINE  

Zach

    Stargunner

  • 1,620 posts

Posted Thu Jul 7, 2005 11:10 PM

Well done indeed. I look forward to seeing what games the community makes with this.

#18 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Thu Jul 7, 2005 11:14 PM

test.asm (766): error: Syntax Error ''.
test.asm (766): error: Syntax Error ''.
Unrecoverable error(s) in pass, aborting assembly!
Complete.

View Post

EDIT: This was a bug, and it has been fixed (easy fix). Source code above updated. Thanks for finding it!

Edited by batari, Thu Jul 7, 2005 11:14 PM.


#19 potatohead OFFLINE  

potatohead

    River Patroller

  • 4,397 posts
  • Location:Portland, Oregon

Posted Thu Jul 7, 2005 11:41 PM

I'll give it a shot tomorrow.

--Thanks.

#20 potatohead OFFLINE  

potatohead

    River Patroller

  • 4,397 posts
  • Location:Portland, Oregon

Posted Fri Jul 8, 2005 12:15 AM

I lied :)

Success!

The output is still goofy from dasm:

DASM V2.20.09, Macro Assembler ©1988-2003
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
Complete.

But it does indeed produce a working binary file.

Very cool stuff.

I've been watching this stuff with great interest. It's nice to finally have a simple dev path on my Linux box for some futzing around. This project should speed some of the learning curve.

After years of banging around on my 400, as a kid, seeing this 6502 stuff go is just great.

Mandrake 10, BTW, using Stella for emulation.

#21 attendo OFFLINE  

attendo

    Chopper Commander

  • 226 posts
  • Location:nl

Posted Fri Jul 8, 2005 2:56 AM

P r e t t y : n i c e ! :P

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.

greets

Attached Files

  • Attached File  dong.txt   531bytes   707 downloads


#22 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Fri Jul 8, 2005 3:46 AM

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.

There is some support for negative numbers because of the way the variables work. For addition and subraction, another way of expressing 128 to 255 is -128 to -1.

Were you trying to do a = -a? If so, this didn't work because it confused the compiler. However, you could use a = 0 - a instead.

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

View Post

yeah, I'll fix that.

#23 attendo OFFLINE  

attendo

    Chopper Commander

  • 226 posts
  • Location:nl

Posted Fri Jul 8, 2005 4:30 AM

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.

(edited a = - a didn't work but a = 0 -a did)

Edited by attendo, Fri Jul 8, 2005 8:53 AM.


#24 batari OFFLINE  

batari

    )66]U('=I;B$*

  • Topic Starter
  • 6,646 posts
  • begin 644 contest

Posted Fri Jul 8, 2005 4:58 AM

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.

View Post

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:

AUDV0 : channel 0 volume (value is 0-15)
AUDF0 : channel 0 frequency (value is 0-31)
AUDC0 : channel 0 control (detemines the "voice" - value 0-15)
and AUDV1, AUDF1, AUDC1 for channel 1

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.

#25 yuppicide OFFLINE  

yuppicide

    I am the Black Knight. Give me your money!

  • 6,933 posts
  • Location:New Jersey

Posted Fri Jul 8, 2005 7:17 AM

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.

Edited by yuppicide, Fri Jul 8, 2005 7:27 AM.





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users