BitMagic The Complete Development Environment for the Commander X16.

BitBench

BitBench is a proof of concept for an early Windows style UI on the Commander X16. It has process management, memory management, a windowing system and events, but no toolkit of controls for building a UI.

It can act as an operating system, or as a windowed UI for a single application.

I wrote it with BitMagic to put BitMagic through its paces, as a form of dog-fooding.

Processes

Each process is loaded into its own base RAM bank. The first few bytes of the bank are a header that says how the process should be called, and holds jump vectors for when events happen.

The X16 has one processor and no way to isolate processes, so BitBench uses simple time slicing:

  • On each VSYNC interrupt, the scheduler looks at the active processes and decides which one to switch to.
  • A process sets how often it’s called, from every frame (1) to every 255 frames. A value of 0 makes it a real time process, called before any process that asks for every frame.
  • A process can hand back control once it’s done with its time. If it doesn’t, it’s interrupted and another process is switched in.
  • The stack, and a block of zero page from $22, are preserved for each process, so from its point of view they never change. The process sets how many zero page bytes to keep in its header.
  • A process that calls the kernal or does other IO should disable interrupts first, so it isn’t switched out and the kernal’s own values aren’t changed underneath it.

Up to 15 processes can run at once. There’s no way to close one yet.

Memory management

Memory is handed out as RAM blocks in the $0400 to $9e00 range, and as RAM banks from bank 1 upwards. A process asks for memory through the API: banks one at a time, or a number of contiguous blocks.

Windows

A process can create windows, up to 16 at a time across the system.

  • Events arrive through a callback set in the process’s header. They’re driven by the interrupt, so they can arrive while the process is busy elsewhere.
  • The API updates a window’s contents from an x, y position using the data structure that’s uploaded to VRAM. A second call is needed to refresh the window.
  • There’s no way to close a window or add extra control icons yet.

How BitBench uses BitMagic

BitMagic’s C# macros are effectively unlimited, so BitBench is built on a framework written in them.

  • Initialisation library. The referenced libraries call macros to define their functionality. This decides what goes into the .prg or .bin files, and sets up the segments, scopes and variables. You control this process, so there’s no mystery in how it works.
  • Typed variables. Variables are defined with a type. The compiler doesn’t use it, but the debugger does: a location defined as a ushort shows as a two byte value in the watch window.
  • Source reuse instead of linking. Functionality is included or left out at build time. For example, the window handler registers a callback for the mouse. That happens in the macro code before the assembly is generated, so if mouse support isn’t needed the whole call chain is dropped from the binary. It doesn’t matter much for BitBench, but it shows how source reuse can produce tighter code than a traditional linker.
  • Scopes. Variables are kept logically separate with scopes, which also give the calling applications an API.
  • Generated code. All of the generated code can be viewed in VSCode.
  • Unit tests. BitMagic is available on NuGet, so the libraries can have unit tests. The tests include checking for side effects.

What’s missing

As a proof of concept, a lot is missing:

  • Processes can’t be terminated.
  • Windows can’t be closed or resized.
  • Updating a window is slower than it needs to be.
  • Events should use a single callback vector, so they’re not constrained.
  • It needs a custom character set with lowercase and inverted tiles.
  • Windows should have icons for closing and other operations.
  • There are no modal windows, such as message boxes.
  • There’s no UI toolkit for buttons, text boxes and so on.

View the source on GitHub