Jump to content

splendidnut

+AtariAge Subscriber
  • Content Count

    500
  • Joined

  • Last visited

Blog Entries posted by splendidnut

  1. splendidnut
    I've been working on and off for the past several weeks and I've made some progress; which can, at times, seem like a lot.  Other times, this all still seems to very much be a daunting task.
     
    When I started writing this entry, I realized I should probably give a general overview/background of how this compiler works under the covers.  Here is a basic outline of the process that the compiler follows:
     
      (1)  Input files are run thru a handwritten Recursive Descent parser to generate an Abstract Syntax Tree (AST) composed of linked lists with each node in the linked list can be a token (enumerations), a single char, an identifier (string), a number, or another list.  Using an AST allows multiple passes with less processing (walking the tree) and easier manipulation (potential optimizer step before code generation)  The AST is essentially following "Greenspun's Tenth rule"... a crude, implementation-specific version of a LISP list.  (see footnote)
     
      There is a semi-implemented, semi-separate tokenizer/lexer utilized by the parser that's implemented in an on-demand way... As parser attempts to fetch a token, the tokenizer checks the next input character and uses that to determine what to fetch.  It skips comments and the newline characters (and keeps track of the current line number).  It usually returns a string to the parser with a token type... that token type indicator also serves as an indicator of a double symbol (++, --, and the like).  Beyond that, the parser is mainly responsible for doing token selection when building the tree.
     
      (2)  Next the symbol table (list of variables and constants) is generated from the AST.  The code walks the tree, finds the variable declaration statements and function definitions, and adds them to the table.  It keeps track of 3 different symbol tables: Global, current Function Parameters, current Function Locals.  The symbol tables for each function's params and locals are stored under that function's entry in the symbol table.  After table is generated, variable allocations are done.
     
      (3)  Finally, the code generation is done.  The code generator is made up of two parts: the AST walker, and the Instruction Generator.  The code generator walks the tree in similar fashion to how the parser builds it, walking each node list in order and processing all sub-list nodes first before handling the operation of the parent list.  When handling the operations, the Instruction generator is called to output the code, in DASM-compatible assembly language.
     
     
    In a way, it feels like it's been way too long with still nothing to show.  I've actually done a ton of work that's only partially visible on the surface of the compiler.  I've done a lot refactoring of the underlying code:
      - I've switched the parser->AST to rely more on using enumerations for tokens instead of string comparisons for operation designation.  Originally there were a LOT of string comparisons all over the place; more or less due to procrastinating this rework.  I'd like to try and push this more into the "tokenizer" but that's not really necessary... more of a nice to have.
     
      - I've filled out most of the code generation code for handling all the operations... although most operations are still 8-bit only.  That's mainly because features have only been added as I've run into the need for them.  And there have been a few cases where I've put off adding a feature because I don't want to spend the time implementing it... I just want my example code to run.  I know, lazy. 
     
      - I've created a constant expression evaluator that I call at a few different points in the code generator.  The most obvious case is when initializing a constant variable.
     
      - I've got a full blown inline assembly language processor working.  Inline assembly code has access to the symbol tables; it can use variables and preform simple array and structure accesses.
     
    I'm currently deep in decoupling the assembly instruction generation portion of the code.  I'm working on building an Instruction List module to encapsulate a block of instructions so that I can more easily determine code size for dealing with conditional branching and making sure to only use jumps when necessary.  The Instruction List will also help with function inlineing and allow me to finally implement a module system.  Currently, only variables are processed in any included files.
     
    ------------
     
    Things I still need to do:
     - implement better variable allocation for local variables.  Currently local vars are located immediately after the global vars... Nested function calls don't work well because, for every function, the local vars start at the exact same spot.  I need to add a function call tree to finagle that around a bit... that and automatic function inlining...
     
     - work on the expression processing code.  It's still not quite working for more complex expressions... I have some simple stack-based code generation stuff written that isn't quite working right.  Also, there are some complications with conditional expressions that I need to handle.
     
     - improve the handling of function parameter passing.  I've started with the approach of using just the registers with a hinting system in place.  I first implemented this to handle the inline assembly version of the position sprite function.  But that's about the only case where it works nicely.  That and very simple functions... since the code generation for the functions themselves doesn't quite know about register preservation
     
     - pass line and position information into the AST to allow for use when generating errors beyond the parsing stage.  Currently I'm only spitting out the AST chunk that contains the erroneous code, which is generally enough for me, but not very user-friendly.
     
     - clean up memory management.  I'm very loose with memory management for the compiler code itself at the moment.  So far I've been relying on the OS to clean up afterwards.  I should trying compiling this using an old 16-bit compiler and see what kind of fallout there is on an older computer.
     
    ------------------
     
    I'm thinking and hoping that with another month of work on this project, that it should be at a good point for a beta release.  I still need to figure out a new name for the project.  I've come up with a few so far:
     
     - Nimble - It's short, simple, and seems to capture the spirit of this project (easy mixing of C and Assembly)
     - Elemental -> ElementalC  - denotes the origins of the language while also subtly signifying that it's a subset.
     - Jumble - A bit of humor, since mixing of two languages can end up jumbled together.
     
    I'm leaning towards Elemental... but I haven't quite decided yet.
     
    ----------------------------------------
    (footnote - from wikipedia)
    *  Greenspun's tenth rule of programming is an aphorism in computer programming and especially programming language circles that states:
        Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
  2. splendidnut
    Mocha/BCA Announcement
     
    Usually, the biggest hassle with getting things done for me has always been a lack of enough big chunks of free time to do stuff.  Due to the current pandemic, that is no longer the case.  Since I'm pretty much home-bound waiting for the weather get warmer, I have a lot more free time to work on personal projects.
    I've been wanting to announce and talk about my current projects for a while.
     
    I'm in the process of developing a C-like compiler focused on generating optimized 8-bit code for the 6502 to use for developing projects for the Atari 2600.  There have been a few people that have announced projects like this a few years ago, all of which seem to have stalled out.  That's why I'm a bit hesitant to annouce this.  I wanted to wait until I was further along, so that I could actually feel confident enough to release a beta-version of the compiler.
     
    Currently the compiler does work to a point... As long as the code remains relatively simple, the compiler produces decent assmebler code which can then be fed thru DASM to get a working program.  Anything the compiler can't handle, it either yells loudly about (usually syntax errors that can't make it thru the parser), or let's you know there was an error and still produces an assembly file containing all the code it could compile.
     
    In parallel with the compiler, I'm working on a game that I started long before ChaoticGrill.  I've been able to get a somewhat simpler version of the original display kernel programmed and running in C code.  Which shows that, Yes, you can write a display kernel in C for the 6502.  The only thing in the demo that has strickly been written in 6502 code, is the Sprite Positioning routine.
     
    Working on the two in parallel, while a bit slower... seems to keep the motiviation going as I flip back and forth between the two.  While working on the game/demo when I hit a need for something to be implemented in the compiler, I can switch over and implement it.  And when I get tired of working on the compiler, I can always switch back.
     
    ----
    This all came about because I was playing around with a lot of different things the past several months...

      *  Progress on Chaotic Grill has been slow because I'm now at the point where I need to fill in the framework surrounding the game:  the titlescreen, menu system, extra features... like SaveKey support.  On top of debating whether I want to add anything to the gameplay.
     
      *  I've been thinking about writing a compiler for a while now.  It's something I've always wanted to do, but just haven't had the time or motivation.  I've spent some of my free time playing around with some old Turbo Pascal projects, experimenting with old C/C++ compilers, and digging more in depth into Javascript.  And that has all led me back around to thinking of developing my own compiler... which led to the root of this project.
     
      *  I did some experimenting with CC65 and trying to get something compiled and running for the Atari 2600.  I was able to get a very simple display kernel working... but only after I started hacking away at the CC65 code base, adding my own code optimizers into CC65's vast optimizer code base.  There was some success... but it was a bit of a painful process.  Ultimately I came to the conclusion that, while you could do a project in it (other's have... Robo Ninja Climb / https://atariage.com/forums/topic/280856-robo-ninja-climb-atari-2600/ ), you kind of had to jump thru hoops to do it.
     
      *  I attempted to experiment with the C02 Compiler (https://atariage.com/forums/topic/267074-c02-compiler/), but it appears there's a very constraining identifier length limit (6 chars!!!!)... which the codebase itself adheres to also.  After trying my previous efforts hacking away at CC65, I was not about to do that again.... There were also some other reasons, but I don't remember what they were.  This was the final push into developing my own compiler.
     
    ----
    For the most part, the compiler I've written trys to following somewhat closely with the C89 (Ansi) spec.  My main reference has been "The C Programming Language: Second Edition" by Brian W. Kernighan and Dennis M. Ritchie.
     
    I'm probably not going to implement Preprocessor stuff...  I currently have one, it only processes the #include stuff (in a very hacky/not quite implemented fully way), but I'm debating just pushing that into the parser itself.  I will not be one to enable "macro abusers" Constants are currently implemented and working, and I'll be adding either a manual or automatic function inliner.  Both of which are usually what macros are used for.
     
    I've greatly simplified the variable declaration stuff.  Only handling 8/16 bit values, pointers and arrays.  The most complicated thing you can create is an array of pointers:  char *gfxPtrs[5];  So far, I've found this to be sufficient.
     
    I've yet to implement one of the features I'd really like to see:  Inline assembly.  It hasn't been done yet, mainly because I'll need to write a parse/code generator for that.  i.e.  Lazy...  I've got my position sprite routine... what more do I need?  Uhh... a score kernel...
     
    So far, the compiler mainly deals in byte-based operations... there are a few things that can work with integers (mainly for the current pointer support), but for the most part, the 16-bit support is missing.  For comparisons, signed/unsigned-ness has generally been ignored, mainly because I haven't used it that much.

    -----

    Overall, despite that half-implementation of most things... I've been slowly adding features to make the compiler ready for general consumption.  Or at least tolerable.  Since I currently don't know when I can throw anything out there, I decided to make this a blog post instead of a general announcement. 

    Oh... and here's two binaries.  One of the original game project in ASM (pre-ChaoticGrill), and one of the C reimplementation using the aforementioned compiler.  And might as well throw some C source code out there too.
     
    Feel free to ask questions or comment.
     
    --Philip
     
     
    bca-asmEng.bin bca-mocha.bin bca.c
     
  3. splendidnut
    Sorry about the lack of updates; I got distracted by a trail of other things: acquiring an Atari 5200 and games, working on the house, dealing with fleas in the basement, etc. Basically real life really snuck up on me and turned my attention towards other things. So I've decided to open up the project to the community for those who wish to collaborate and hopefully help drive this project to be completed sooner.

    So how can you help? I could really use help on the game logic... I know this project is in assembly language... but if someone could create a crude demo of the game in Batari Basic that implemented the actual game logic, it would give me something to work off of.

    There are definitely other areas (music, character graphics, etc.) that I could use help in too.

    One of the big reasons I want to open up this project is incase there is someone out there more motivated than me to drive the project home sooner

    I just recently switched it from using DPC to DPC+ because I have some ideas on how to harness the more advance features to take care of some of the issues I'm having now with not having enough cycles while drawing to really make the playfield usable.


    Oh... if anybody wants to give input on the name... I'm torn between calling this project ChaosGriller or ChaoticGrill.


    Sorry if this seems like just a quick update, but I really wanted to just get this out there.
  4. splendidnut
    I'm long overdue for an update... so here it is:

    There are now 4 enemies (including a Mr.Egg, and Mr. Pickle) running around on the screen utilizing a 20/30 Hz Flicker routine. I'm planning on improving it by attempting to fit in some mid-screen sprite changes into the display kernel. For the most part, the enemies run around the level properly. But every once in a while it seems one or more of them get lost following their own path. Code has been moved around and spread out across a couple of banks. I've done this to give elbow room and hopefully keep the code better organized.


    Code and ROM attached.
  5. splendidnut
    After recovering from the holidays, I finally got a chance to sit down and work some more on this.

    What's new in this update:
    The display kernel has been updated to take advantage of the DPC+ capabilities. Mainly this affects the burger pieces on the level which now actually look like the finished burgers... both in shape and color. This is done by utilizing DPC+'s fast fetch and the ability to write to Display Data to create a frame buffer for storing the burgers. Also using Fast Fetch allows color and bitmap of both sprites to be updated every line... as opposed to the previous version which could only update one of the sprite fully. Updates to the enemy AI now allow Mr. Hot Dog to chase the chef around. It still needs work though. Still thinking about how to implement a round-the-corner algorithm for the joystick control to help ease the movement of the player thru the level. I'm still planning to use the 20/30 Hz flicker routine (seen in the Pac-Man 4k remakes) to display upto 6 detailed sprites.




  6. splendidnut
    M Network's BurgerTime for the Atari 2600 is a decent game. It was one of the first games I played on an Atari 2600 emulator back in the late 1990's. But it is not without it's issues. The chef moves quite sluggishly, the graphics are bit on the bland side, and the controls could do with some improving. The graphics were a compromise made when the game was developed to avoid as much flicker as possible. The only time the game flickered was during the use of pepper (which wasn't too bad) and when a bonus item is shown (which was bad since it was a 2 frames on/2 frames off interleaved with the hotdog).

    Not too long ago, I spent some time working thru a disassembly I created of the game. I tweaked the "finished" burger colors and doubled the speed of the chef. The game became much easier to play, maybe a little too easy. But there was a really nasty bug that emerged (or became easier to trigger). When dropping more than a couple of burger pieces at the same time, an infinite loop would be triggered which would black out the screen and freeze on whatever musical note was playing at the time.

    So after seeing a couple of people discussing the issues, I've decided to take on the challenge of creating a better version/conversion/port of the game for the Atari 2600. I figured the best way was to start from scratch.

    My main goal is to create a more accurate arcade version while still working within the limitations of the Atari 2600.

    What I've done so far:
    I have programmed in the graphics for the first level from the Arcade version. I'm currently using an asymmetric kernel for the displaying the level. The level and ladders are colored based off the first write to PF1. The burger pieces are properly colored within the level and there can be four different pieces on a line. They are still just colored rectangles but being properly colored helps them stand out better. I still need to figure out a way to show them after being stepped on by the chef. I'm currently using DPC (the Pitfall 2 chip not the more recent DPC+) to be able to display 2 sprites updated as a 1-line Kernel. Currently only 1 of the sprites has their color updated every line. The other is just a solid color. I don't quite have enough cycles to do both. I'm working on a round-the-corner algorithm for the joystick control to help ease the movement of the player thru the level. I plan to use the 20/30 Hz flicker routine (seen in the Pac-Man 4k remakes) to display upto 6 detailed sprites.

    The display kernel is 5 lines long.
    One line for the level platform or ladder piece. A blank line for figuring out what burger pieces are displayed. Three lines for displaying the burger pieces.


    Time-wise, I'm not sure how long this will take since I'm only working on it sporadically. But I'm going to try to give updates maybe once a month.


    That's basically it. I've attached a screenshot of what I have so far running in Stella.





×
×
  • Create New...