Skip to content

arlm/CSharpTo2600

 
 

Repository files navigation

CSharpTo2600

A compiler and framework for creating Atari 2600 games using C#. It uses the .NET Compiler Platform (Roslyn) to compile C# files, and Mono.Cecil to compile the resulting CIL into 6502 assembly.

Current Status

Initially this project was written to compile C# straight to 6502 assembly. It has since been rewritten to compile C# to CIL, and then compile the CIL to 6502 assembly. The rewrite quickly surpassed the original implementation in both features and development speed. Development will continue towards the goal of porting my 2600 game to C#.

Current Goal

The current goal is to add all the features needed for me to port my attempt at a 2600 game to C#.

Example

There's no collection of samples yet since they may quickly become obsolete. Below is an example of how you could, at the time of writing, write a program to cycle through the NTSC background colors. See the Features section below for a more complete list of features.

using static VCSFramework.Registers;

namespace Samples
{
    public static class NtscBackgroundColorsSample
    {
        private static byte BackgroundColor; // Support for static fields.

        public static void Main()
        {
            // Processor and memory initialization code is automatically injected by the compiler into
            // the program's entry point, so there's no need to manually do it.
        MainLoop:
            // Perform vertical sync.
            // This is the same logic that would be used in 6502 assembly as well.
            VSync = 0b10; // TIA write-only registers implemented as setter-only properties.
            WSync(); // TIA strobe registers implemented as methods.
            WSync();
            WSync();
            Tim64T = 43;
            VSync = 0;

            // Actual logic to increment and set the background color every frame.
            // The least significant bit is unused, so incrementing by 1 instead of 2 slows the flashing down.
            BackgroundColor++;
            ColuBk = BackgroundColor;

            // Kill time until the vertical blank period is over.
            while (InTim != 0) ; // PIA read-only registers implemented as getter-only properties.

            WSync();
            VBlank = 0;

            // Visible image
            byte lines = 191; // Local variable support.
            while (lines != 0) // Support for while loops and some comparisons.
            {
                lines--;
                WSync();
            }
            
            WSync();
            VBlank = 0b10;

            // Overscan
            lines = 30;
            while (lines != 0)
            {
                lines--;
                WSync();
            }

            goto MainLoop; // goto support!
        }
    }
}

Features

An incomplete list of supported features in no particular order.

  • ⭕ Primitive Types
    • bool
    • ✔️ byte
    • sbyte
  • ❌ Array types
  • ❌ Pointer Types
  • ⭕ Custom Types
    • ✔️ Value Types
      • ✔️ Single-byte types
      • ✔️ Multi-byte types
      • ✔️ Composite types (struct-in-struct)
    • ⭕ Reference Types
      • ✔️ Static reference types
      • ❌ Instance reference types
  • ⭕ Static Members
    • ✔️ Fields
    • ❌ Properties
    • ⭕ Methods
      • ✔️ 0-parameter
      • ✔️ >0-parameter
      • ✔️ void return
      • ❌ Non-void return
  • ⭕ Inline Assembly
    • ❌ Implied address mode inline assembly (TXS, SEI, etc)
    • ✔️ Write-only A/X/Y registers
  • ⭕ Optimizations
    • ✔️ Redundant PHA/PLA removal
    • ❌ Reuse memory addresses
  • ⭕ C#
    • ✔️ goto
    • ✔️ unsafe
    • ✔️ default
  • ⭕ CIL OpCodes
    • ⭕ Arithmetic
      • ✔️ Addition (add, no overflow check)
      • ✔️ Subtraction (sub, no overflow check)
      • ❌ Division
      • ❌ Multiplication
    • ⭕ Branching
      • ✔️ Branch if true (brtrue, brtrue.s)
      • ❌ Branch if false
      • ✔️ Unconditional branch (br, br.s)
    • ⭕ Comparison
      • ❌ Equal
      • ✔️ Greater than (cgt.un)
      • ❌ Less than
    • ⭕ Load
      • ✔️ Argument (ldarg, ldarg.s, ldarg.0, ldarg.1, ldarg.2, ldarg.3)
      • ✔️ Constant (ldc.i4, ldc.i4.s, ldc.i4.0, ldc.i4.1,ldc.i4.2,ldc.i4.3,ldc.i4.4,ldc.i4.5,ldc.i4.6,ldc.i4.7,ldc.i4.8)
      • ❌ Element
      • ✔️ Field (static) (ldsfld)
        • ✔️ Address (ldsflda)
      • ✔️ Field (instance) (ldfld)
        • ✔️ Address (ldflda)
      • ❌ Indirect (ldind.i, ldind.i1)
      • ✔️ Local (ldloc, ldloc.s, ldloc.0, ldloc.1, ldloc.2, ldloc.3)
    • ⭕ Store
      • ✔️ Argument (starg, starg.s)
      • ❌ Element
      • ✔️ Field (static) (stsfld)
      • ✔️ Field (instance) (stfld)
      • ❌ Indirect (stind.i, stind.i1)
      • ✔️ Local (stloc, stloc.s, stloc.0, stloc.1, stloc.2, stloc.3)
    • ⭕ Miscellaneous Object Model
      • ✔️ Initialize value type (initobj)

Building

Load the solution into Visual Studio Community 2017 and it should build and run fine.

Usage

The public interface is very rudimentary. You can either invoke it programmatically through VCSCompiler.Compiler.CompileFromFiles(), or through the command line program like so:

dotnet VCSCompilerCLI.dll path_to_source_file path_to_vcsframework_dll path_to_dasm_executable

License

This project is licensed under the MIT License.

About

A compiler and framework for creating Atari 2600 games using C#.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%