Jump to content
IGNORED

New Atari Compiler Dev


Gip-Gip

Recommended Posts

I have given the compiler the name AtaC(Atari C, Pronounced Attack). Any other suggestions?

 

I'm making a new Atari 2600 compiler for a custom C-like language(in C89). It is being created to be efficient but also to hide multi-frame calculations from the programmer(it will notify the programmer, however, if multi-frame calculation is needed), as well as be more readable than assembler.

 

I am currently developing the assembler, and development on AtaC has been paused until it is finished. Here's the GitHub page if you want to watch me develop that mess

 

All examples and syntax specifications have been removed(on accident, to an extent). I will come up with those tomorrow.

Edited by Gip-Gip
  • Like 4
Link to comment
Share on other sites

How are you planning on handling timed code in the display kernels?

While all of it will be handled inside of the init function, I will more than likely add an asm statement like in GCC. while it would require making a built-in assembler, I don't want the main feature of the programming language(smart code placement) to be soiled by slow code generation. This should not be needed with basic graphics, as a few equal statements should not consume that many resources. The amount of scanlines vblank and overscan consume will be up for control from the command line. Any other timing related things such as NOP and STA WSYNC will be provided as functions(nop and next_line)

  • Like 1
Link to comment
Share on other sites

Including an assembler would be a good idea.

 

Will this support two line kernels? What about kernels that are exact multiples of 76 cycles and don't use wsync?

 

I like what you're trying to do. It would be great to have a higher level language for game logic, but still have flexible kernel options.

  • Like 1
Link to comment
Share on other sites

Will this support two line kernels?

It can technically be two lines, since it is going to be a whitespace-insensitive compiler ;)

 

What about kernels that are exact multiples of 76 cycles and don't use wsync?

if you're willing to pad, yes, it will be possible

  • Like 1
Link to comment
Share on other sites

You may want to take a look at K65, a very powerful compiler and linker framework for the VCS: http://devkk.net/wiki/index.php?title=K65

 

It's not really C, but similar to it. It abstracts a lot of things (functions, loops, inlining, bank switching etc.), optimizes the placing of code and data segments for you during linking (aligned/unaligned) and has VCS-specific keywords like wsync, but still gives the programmer full control over everything if needed. Once you get used to its syntax and idiosyncrasies, it speeds up development considerably; especially the linker is a great improvement over having to do it manually like with dasm.

 

KK, the developer, is also quite open to feature requests

  • Like 2
Link to comment
Share on other sites

You may want to take a look at K65, a very powerful compiler and linker framework for the VCS: http://devkk.net/wiki/index.php?title=K65

 

It's not really C, but similar to it. It abstracts a lot of things (functions, loops, inlining, bank switching etc.), optimizes the placing of code and data segments for you during linking (aligned/unaligned) and has VCS-specific keywords like wsync, but still gives the programmer full control over everything if needed. Once you get used to its syntax and idiosyncrasies, it speeds up development considerably; especially the linker is a great improvement over having to do it manually like with dasm.

 

KK, the developer, is also quite open to feature requests

 

K65 looks like a great compiler, but I do have things I want to do differently than it, such as:

 

  • an Open-Source compiler under the ISC license(if the source is legally out there, I can't find it)
  • "cleaner" variable declaration(instead of doing var foo = 0x80, ram: foo = value)
  • "cleaner" data declaration(instead of doing data foo{data}, rom: foo[] = {data} or rom: foo = value)
  • variable declaration inside functions, similar to C99
  • all non-whitespace non-operator characters counting as valid variable names
  • true whitespace-insensitiveness
  • hidden bankswitching(for calc, all the other call will be the first segment)
  • a few more things I forgot when I made this post

I am now going to go make a standard over at GitHub, so my code doesn't change so much anymore ;)

Link to comment
Share on other sites

K65 sure has some questionable design, I have been annoyed by it more than once. :) But its greatest strength is providing a good layer of abstraction while at the same time leaving the developer in full control of everything if need be, which IMHO is key for the VCS with ist limited resources (RAM, ROM) and need for precise timing (cycles).

 

Keep that in mind when developing your compiler, especially when it comes to "hidden bankswitching", "variable declaration inside functions" etc., which (without knowing exactly what you mean by that) look like dangerous candidates to be done wrong. ;)

 

I'll follow your project with interest in any case!

Link to comment
Share on other sites

Keep that in mind when developing your compiler, especially when it comes to "hidden bankswitching", "variable declaration inside functions" etc., which (without knowing exactly what you mean by that) look like dangerous candidates to be done wrong. ;)

 

What I meant by "hidden bankswitching" is that if a function goes over a bank, it will either automatically bank switch in the function or the function will be moved into the other bank, depending on how much room the function takes up in the bank

 

As for "variable declaration inside functions", it was an idea I had that came from experience with C, where variables could be declared in functions(which I somewhat put inside the syntax standard, but it's only allowed in init).

 

The cleaner variable declaration is simply to make variable declaration more automatic and less manual, but there will also be alias object handlers(some weird word I chose for the part of a logical line that "handles" what's done with it) and a RAM array, for those who really want it(and there will also be some way to work with addresses).

Edited by Gip-Gip
Link to comment
Share on other sites

Personally I find the design of this language a bit awkward. Some if seems like it tries to be different just to be different. I also have serious concerns about how well it lends itself to making an actual Atari game. The draw function in particular raises the most concern. I just don't think the VCS has enough resources to right anything but the most basic kernels using your proposed language.


Have you thought about trying to make a framework first before tackling something as complex as a compiler? You could take an existing c++ compiler and couple it with some hand written assembly routines to produce something similar to what you are proposing here without having to reinvent the wheel.


Here is some feedback on the current syntax outline:


Addresses may need to deal with ZeroPage vs Absolute.

You may want to assign the high/low byte of an absolute address to a variable.


Logical Lines example says value 0 in description but uses 1.


Is there no single line comment? //


Functional separators lack clarity on bank and inline status.


draw is problematic because you can't easily switch kernels or handle multiline kernels

draw should probably have a scanline count parameter too for performance reasons


asm: shouldn't require ;, instead a new line should terminate the statement


"ROM variables are constant" - so call them contants


Multiply(+=) should be *=


support for fixed point, signed/unsigned, and 16bit integers seems to be missing?


Shouldn't keep if equal be if: foo != bar[1] { foo = 0 } instead of foo = foo == bar[1];


I find it odd that the RAM variables are declared init. They have global scope, so I would expect to declare them outside of a function separator.


The concept of pointers/references seems to be omitted.

Link to comment
Share on other sites

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:
Logical Lines example says value 0 in description but uses 1.
Multiply(+=) should be *=

Those where typos, thanks for pointing those out :)

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:

Personally I find the design of this language a bit awkward. Some if seems like it tries to be different just to be different.

It may seem that way, but it's actually just so the compiler classifies as truly whitespace-insensitive. For example, I can't make a variable in C without putting a space between the type identifier(it's int in the example int number = 0) and the variable name(at least in GCC). To go around this, I just made it mandatory to put a colon between the handler and the variable(and then the handler became a large part of code).

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:
Is there no single line comment? //

Now there is :)

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:

Shouldn't keep if equal be if: foo != bar[1] { foo = 0 } instead of foo = foo == bar[1];

Good point. It is fixed.

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:
I find it odd that the RAM variables are declared init. They have global scope, so I would expect to declare them outside of a function separator.

RAM variables are declared in init as that initializes them to zero(or any other number provided), as well as shields them from looping. I have included the syntax specification to allow RAM variables outside of init, but they will not be initialized(whatever value is at that address is what it is).

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:

The concept of pointers/references seems to be omitted.

I expanded the definition of addresses to include variable representation(crappy pointers that can only access zero-page memory), and added the reference operator

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:

"ROM variables are constant" - so call them contants

asm: shouldn't require ;, instead a new line should terminate the statement

It's a consistency thing.. the semicolon thing will be optional(some people, including myself, like the feature) but the reason rom variables are called such is because that's the part of memory they're part of. It would seem out of place(to me) for a C type identifier in a source file. They will be interchangeable.

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:Addresses may need to deal with ZeroPage vs Absolute.


This is automatically handled by the compiler(depending on the value of the address)

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:support for fixed point, signed/unsigned, and 16bit integers seems to be missing?

Done(ish), done(ish), and done :)

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:You may want to assign the high/low byte of an absolute address to a variable.

It is now possible.

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:draw is problematic because you can't easily switch kernels or handle multiline kernels
draw should probably have a scanline count parameter too for performance reasons

You're right. My solution? Multiple Draw Functions of course(with their accompanying draw variable perimeters) :D (what you meant by multi-line kernels is false, remember, wsync(and padding) is always an option. the language is not that high-level. draw loops do not have an wsync placed at the end anyways, so was it the wording?)

ZackAttack, on 07 Apr 2016 - 5:22 PM, said:Functional separators lack clarity on bank and inline status.

you can specify the bank a function is in with the bankX: handler, and I think object: handlers are sufficient as inline functions(tell me otherwise, if you think so)

I'm surprised my standard is even readable! Thanks for the feedback!

Edited by Gip-Gip
Link to comment
Share on other sites

What is the reason for "whitespace-insensitive" being a major design goal?

 

Regarding the multiple draw functions. Imagine you are building a small game that has a title screen. When you press the button it starts the game which has a status bar at the top and the level on the rest of the screen. So you have 3 kernels. The first kernel for the title screen will apply to all 192 scanlines. The second kernel will apply to the top 32, and the third will apply to the bottom 160. I think your spec still fails to address this common situation where depending on the state of the game you will need to display different kernels.

Link to comment
Share on other sites

Regarding the multiple draw functions. Imagine you are building a small game that has a title screen. When you press the button it starts the game which has a status bar at the top and the level on the rest of the screen. So you have 3 kernels. The first kernel for the title screen will apply to all 192 scanlines. The second kernel will apply to the top 32, and the third will apply to the bottom 160. I think your spec still fails to address this common situation where depending on the state of the game you will need to display different kernels.

 

Thanks for bringing that up! I replaced that with layouts(essentially inline linker scripts).

 

 

What is the reason for "whitespace-insensitive" being a major design goal?

 

It's for compiler simplicity and a personal preference(I did remove the colon requirement for handlers though)

Link to comment
Share on other sites

 

It's for compiler simplicity and a personal preference(I did remove the colon requirement for handlers though)

I don't get how it simplifies the compiler though. Either way the lexical specification will need a token class for white space. The parser will have slightly different semantics, but it doesn't seem like it would be significant. Your rainbow example is laid out nicely and easily readable thanks to white space. It doesn't seem like no white space is really your personal preference.

 

Also, can you add some more complete examples that demonstrate the layout construct? I'm having trouble visualizing how it would be used for the three kernel example I gave before.

Link to comment
Share on other sites

I don't get how it simplifies the compiler though. Either way the lexical specification will need a token class for white space. The parser will have slightly different semantics, but it doesn't seem like it would be significant. Your rainbow example is laid out nicely and easily readable thanks to white space. It doesn't seem like no white space is really your personal preference.

 

Before you pointed that out, I was thinking of loading the line into a buffer and parsing the text. Now, I realize that I could just convert everything into symbols as things are read in. Wow, I was overthinking this. :(

 

As far as personal preference goes, sometimes I like to make code into blobs of text or ASCII art(it's a thing I do when I'm really bored), which isn't really practical at all(and more than likely will never be done with this language). :P

 

Either way, thank you for pointing everything out and criticizing me(your making me think)!

  • Like 1
Link to comment
Share on other sites

Converting source code into ascii art is a great idea!

 

There are a lot of good resources about compiler design theory and implementation. You may want to read up on it some more before you start writing any code. There are a lot of existing tools out there that you can use to generate the lexing and parsing code for you once you've put the specifications into regex form. This youtube playlist is a pretty good spot to start.The book "Compiler Design" (ISBN-13: 978-0198066644) is also a good read and can be obtained for a reasonable price.

  • Like 2
Link to comment
Share on other sites

Nice white paper Gip-Gip! :) I agree with Zack about considering first building a runtime library (Framework) and testing it's object set.

 

You can write the compiler now to compile all of that syntactic sugar (which is very cool) in your intrinsics to asm, but need the runtime library to surface objects from it.

 

The BASIC to C translator layer used by Jaguar BASIC has no runtime library, it is simply translated into C so a runtime had to be added and the objects surfaced to the BASIC afterwards.

 

I think it's easier to build the language around the objects than to add them afterwards but there's no one set way to do it so if you're more motivated to write the compiler first I think you should.

 

--- ascii art code sounds really cool, are you going to include a provision to use ascii art to draw sprites and screen bitmaps inline in AtaC source?

 

 

 

Link to comment
Share on other sites

--- ascii art code sounds really cool, are you going to include a provision to use ascii art to draw sprites and screen bitmaps inline in AtaC source?

 

I would like to come up with a decent system for it, but I'm not exactly sure how to implement it(in other words, sometime in the future)

Link to comment
Share on other sites

I would like to come up with a decent system for it, but I'm not exactly sure how to implement it(in other words, sometime in the future)

I used to include a header file with a bunch of constants defined like this:

zz________ = %00000000; $0 0
zz_______X = %00000001; $1 1
zz______X_ = %00000010; $2 2
zz______XX = %00000011; $3 3
...
zzXXXXXX__ = %11111100; $FC 252
zzXXXXXX_X = %11111101; $FD 253
zzXXXXXXX_ = %11111110; $FE 254
zzXXXXXXXX = %11111111; $FF 255

which would let me to this:

Digits:
       .byte zz____X___ ; ZERO
       .byte zz__XX_X__
       .byte zz_XX___X_
       .byte zz_X____X_
       .byte zz_X___XX_
       .byte zz__X_XX__
       .byte zz___X____

       .byte zz____X___ ; ONE
       .byte zz____XX__
       .byte zz____XX__
       .byte zz__X_XX__
       .byte zz___XXX__
       .byte zz____XX__
       .byte zz_____X__

       .byte zz____XXX_ ; TWO
       .byte zz_XXXX___
       .byte zz__X_____
       .byte zz___XX___
       .byte zz_____X__
       .byte zz__X___X_
       .byte zz___XXX__

Nowadays I just use standard binary notation and created syntax rules so my programmers editor would colorize the binary values for me:

post-3056-0-16968900-1460152129_thumb.png

Link to comment
Share on other sites

Now that development has started, I won't be posting anything big until some basic code generation is finished(or I come across a major flaw in the syntax and I have to restart all over again). After that development will continue over at GitHub.

Link to comment
Share on other sites

  • 2 weeks later...

Just to keep everyone informed:

 

Compiler development is running smoothly, as I work on it about 1-4 hours per day

The major parts of code segregation are almost finished

Code generation is planned out

 

The project currently contains 15 files: main.c, main.h, getArg.c, getArg.h, replaceExt.c, replaceExt.h, compile.c, compile.h, memmang.c, memmang.h, getOp.c, getOp.h, enums.h, messages.h and Makefile

  • Like 1
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

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

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...