# The Oberon System

NOTE: Porting of the Oberon System is in progress. It's not working yet.

Dusk OS hosts a port of the Oberon System, which is enabled by the Oberon
Compiler [comp/oberon].

This is not emulation, this is a native port! That is, this code doesn't compile
to some RISC5 bytecode to be emulated on ran on the Oberon-specific FPGA. It's
compiled through the HAL, using native bytecode for all CPUs supported by Dusk.

This of course requires a significant rework of all the lower layers of the
Oberon system which are RISC5-specific. We strip all those parts and hook them
to the appropriate Dusk drivers.

This implies changing a few things here and there. The goals here is to allow
Oberon code to run with as few changes as possible while hooking into Dusk
abstractions as elegantly as possible. Notes about those changes follow below.

## Usage

You load the Oberon system by loading [oberon/sys.fs]. This loads [comp/oberon]
and compiles a wrapper unit that loads all the important oberon modules.

When the porting is finished, you'll launch a Oberon system with "oberon". This
will enter the Oberon runloop and will return to the console on System.Quit.
One of the big features of that Oberon port will be interaction with the Dusk
system. For example, you'll be able to launch a Dusk Console which will give you
a regular Dusk prompt. From within Oberon! Giving you the same Dusk powers!

Hopefully, I'll also manage to design some convenient wrapper around graphical
Dusk apps. For example, run a varvara app from within a Viewer. This means that
to have a "Graphical Dusk", all you have to do is to call the "oberon" runloop
in "init.fs" and tweak your oberon system to launch a Dusk console on boot.
Boom!

But for now, this unit only loads whatever modules are currently ported and
creates aliases for testing purposes. So, for now, there's not much to see
there.

## Files

The Files module thinly wraps [fs/core]. FileDir doesn't exist and its public
API is included in Files.

A Rider hooks to a File and calls "seek" on its target file whenever it needs
to. This means "multiple riders" are going to be slow compared to Oberon design.
But well, is this actually needed anyways?

Oberon has this concept of creating new named files without registering them.
We don't do that. New() creates a new file. Old() opens a new file. Register()
is a noop.

We sometimes see a pattern of creating anonymous files with New("") without ever
registering them. That can't work within our filesystem wrapper. Therefore, what
we do instead is to have NewMemFile(), which creates a new 16kb (let's see if
it's enough...) [fs/memfile] and yields it.

## Display

Ideally, the display module would be a thin layer over [gr/pix] and friends, but
the specified raster operations don't map to the API that gr/pix currently
provides. It's a problem.

Therefore, until a graphics refactoring takes place, the Oberon display will be
a separate buffer (the color one. We don't port Monochrome logic) with 4-bit
per pixel and the same size as the screen. We define a palette for each of the
16 possible colors.

This allows the DisplayC module to be ported pretty much as is. After each
operation, however, we add an "invalidate" call so that the buffer can be pushed
to the screen.

## Input

Oberon's Input module maps rather straight to [io/kbd] and [io/mouse]. We
diverge from original with Input.Available(), in which case we yield a NKC
rather than a PS/2 key code. No code in the Oberon system uses Input.Available()
for its code anyways, only for its nonzero state.
