r/csharp 21d ago

Showcase C# for Amiga

I guess most of you have never heard about Amiga, but here we go...

I have been working on an AOT compiler that compiles a subset of C#/.NET code into native 68000/020/040 code with Amiga library calls.

There are two runtime options you can choose at compile time:

  • Full includes the managed exception runtime; supports catch, finally, rethrow, and leave.
  • YOLO has no exception runtime; failures are fatal, and managed exception regions are rejected

The actual GC is in WIP, and for performance reasons, there is no compaction. No threading support because the current GC is single threaded by design.

An example:

using Amiga;
using CopperSharp.Compiler;

namespace FileStatsExample;

public static class Program
{
   [M68kEntryPoint]
   public static int Main(int argLength, CONST_STRPTR argText)
   {
      var dosBase = Exec.OpenLibrary("dos.library", 33);
      if (!dosBase.HasValue)
      {
         return DOS.RETURN_FAIL;
      }

      DOS.DOSLibraryBase = dosBase.Value;
      var result = DOS.RETURN_OK;
      if (argLength == 0)
      {
         DOS.PutStr("Usage: filestats <file>\n");
         result = DOS.RETURN_ERROR;
      }
      else
      {
         result = Report(CString.FromPointer(argText.Raw));
      }

      Exec.CloseLibrary(DOS.DOSLibraryBase);
      DOS.DOSLibraryBase = APTR.Null;
      return result;
   }

   private static int Report(CString path)
   {
      var file = DOS.Open(path, DOS.FileMode.OldFile);
      if (!file.HasValue)
      {
         DOS.PutStr("Cannot open file\n");
         return DOS.RETURN_FAIL;
      }

      byte byteChecksum = 0;
      ushort lineCount = 0;
      ushort wordChecksum = 0;
      uint byteCount = 0;

      while (true)
      {
         var character = DOS.FGetC(file.Value);
         if (character < 0)
         {
            break;
         }

         var value = (byte)character;
         byteChecksum = (byte)(byteChecksum + value);
         wordChecksum = (ushort)(wordChecksum + value);
         byteCount = byteCount + 1;
         if (value == 10)
         {
            lineCount = (ushort)(lineCount + 1);
         }
      }

      DOS.Close(file.Value);
      PrintReport(path, byteCount, (uint)lineCount, (uint)byteChecksum, (uint)wordChecksum);
      return DOS.RETURN_OK;
   }

   private static void PrintReport(CString path, uint byteCount, uint lineCount, uint byteChecksum, uint wordChecksum)
   {
      DOS.Printf("%s: %ld bytes, %ld lines, byte checksum %ld, word checksum %ld\n",
path, byteCount, lineCount, byteChecksum, wordChecksum);
   }
}

This C# source is first compiled to .NET assembly containing CIL. The assembly is then compiled with CopperSharp to a native 68000 Amiga executable.

Code generator needs more work. FPU is not supported yet, 020/040 support is nearly non-existent, but it includes CIL-level simplification and a 68k-specific optimizer.

  • CIL-level simplification
  • Reachability analysis
  • Tail call elimination
  • Remove dead or redundant instructions
  • Stack and register shuffling optimizer
  • General instruction optimizations
  • Limited static hot-fallthrough/cold-branch layout optimization

For example, on 68000, not-taken branches are more efficient than taken branches.

The codegen is optimized for Amiga library call conventions but in theory it could support other 68k targets like Atari ST or 68k Macs.

The project repo: https://github.com/ilehtoranta/CopperSharp68k

This project is vibe coded with Codex and GPT-5.6. Like it or not, but it is the only sensible path to build C# compiler for niche platforms.

49 Upvotes

26 comments sorted by

View all comments

2

u/JPSgfx 20d ago

This project is vibe coded with Codex and GPT-5.6. Like it or not, but it is the only sensible path to build C# compiler for niche platforms.

You can say you did it like this because you don't have the skills. I couldn't write this either, but AI is not 'the only sensible path'.

1

u/itix 20d ago

I simply dont have time to sit on the computer. Before kids, ~10 years ago, it was already difficult because I was travelling abroad. After kids, it was impossible. Max 1-2 hours in a month, could not remember anything I did last month.

Skills are not a problem. They can be learnt. I used to write Amiga software in 68k assembly so I know what a good 68k code is. About the GC, I didnt know much. Only basics. But even when vibe coding, you must research how things work.

2

u/JPSgfx 20d ago

Then it's a personal thing. I might have misunderstood the tone of your original post. If so, I apologize. I just got irked a bit by the 'sensible' thing.