Archive

Archive for February, 2009

OWL BASIC runtime library takes shape

February 11th, 2009 3 comments

For a useful re-implementation of BBC BASIC, especially in compiled form, a run-time system is needed to provide services to the running program which cannot be directly provided by the operating system. In the case of our OWL BASIC implementation, we are targeting .NET so we already have a very sophisticated run-time in the shape of the CLR (Common Language Runtime). Nevertheless, additional services specific to the BBC BASIC language are required, many of them based closely on old Acorn hardware from the BBC Micro and RISC OS eras. Fortunately, many of the services required to produce a functioning BBC BASIC system are fairly well abstracted from hardware details, as the many different implementations on quite different underlying hardware, such as BBC BASIC for Windows, have shown.

Many of the services, such as the VDU drivers, used extensively by BBC BASIC are not strictly part of the language; however, a fairly complete implementation is required in order that existing programs can be run successfully with little or no modification.

Its difficult to know where to draw the line when deciding on the degree of backwards compatibility. Our aim is to get the most widely used features to work well. Some of the obscure features may never be implemented. We must also strike a balance between .NET compatibility and good interoperability with other .NET languages and tools, and what I will call Acorn compatibility, for want of a better term.

Implementation details

Our OWL Runtime Library (ORL) is coding in C# and leans heavily on the existing .NET framework. We plan to support common RISCOS SWI calls and a fairly complete VDU system. Much of the work by my brother Ian and myself has to date has focussed on the VDU system, which uses GDI+ through the System.Drawing2D namespace of .NET to do most of the heavy lifting.

Compatibility Testing

The testing approach has been as follows:

  1. Find write a simple but interesting BBC BASIC program using graphics commands, such as GCOL, MOVE, PLOT and VDU. Execute this program on Acorn hardware or an emulator to get the graphics output.
  2. Convert all graphics commands to their equivalent VDU sequences. For example GCOL 0, 3 becomes VDU 18, 0, 3, and verify that program output is the same
  3. Write a test in C# against our OWL Runtime Library using the VDU codes, and very that output is sufficienly similar.
  4. Compile and run the original BBC BASIC test program using the OWL BASIC compiler and verify the output

Currently we are pursuing steps 1-3 above as the compiler is not yet ready for step 4. This enables us to work on the run-time library and compiler concurrently.

Example program

The following is a fragment from a larger example program.

REM BBC BASIC using graphics commands
size% = 220
radius% = 250
FOR t% = 1 TO 4
radius -= 30
c% = 3
cntr% = 0
cd% = 0
FOR x2% = 100 TO 450 STEP 20
cntr% += 1
GCOL 0, (c% AND 63)
TINT 2, (t% – 1) * 64
MOVE size, size
MOVE size + (COS(RAD(x2% – 20)) * radius%), size% + (SIN(RAD(x2% – 20)) * radius%)
PLOT 85, size + (COS(RAD(x2%)) * radius%), size% + (SIN(RAD(x2%)) * radius%)
CASE cntr% OF
WHEN 1: cd% = 4
WHEN 4: cd% = -1
WHEN 7: cd% = 16
WHEN 10: cd% = -4
WHEN 13: cd% = 1
WHEN 16: cd% = -16
ENDCASE
c% += cd%
NEXT
NEXT

which can be converted to the equivalent program which uses only VDU commands:

size% = 220
radius% = 250
FOR t% = 1 TO 4
radius -= 30
c% = 3
cntr% = 0
cd% = 0
FOR x2% = 100 TO 450 STEP 20
cntr% += 1
VDU 18,0,(C AND 63)
VDU 23, 17, 2, (T – 1) * 64, 0,0,0,0,0,0
VDU 25, 4, size%; size%;
VDU 25, 4, size% + (COS(RAD(x2% – 20)) * radius%); size% + (SIN(RAD(x2% – 20)) * radius%);
VDU 25, 85, size + (COS(RAD(x2%)) * radius%); size% + (SIN(RAD(x2%)) * radius%);
CASE cntr% OF
WHEN 1: cd% = 4
WHEN 4: cd% = -1
WHEN 7: cd% = 16
WHEN 10: cd% = -4
WHEN 13: cd% = 1
WHEN 16: cd% = -16
ENDCASE
c% += cd%
NEXT
NEXT

These programs both give the following output in Arculator :

Colour wheel display in Arculator

Translating the second version above into C# against our run time library, we get the following:

const short size = 220;
int radius = 250;

for (int t = 1; t < 5; ++t)
{
    radius -= 30;
    int c = 3;
    int cntr = 0;
    int cd = 0;

    for (int circle = 100; circle < 450; circle+=20)
    {
        cntr++;
        // TINT action (2) color (t * 64)
        vdu.Enqueue((byte)23, (byte)17, (byte)2, (byte)((t-1) *64));
        vdu.Enqueue((byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0);

        // GCOL action (0) color (c & 63)
        vdu.Enqueue((byte)18, (byte)0, (byte)(c & 63));

        short mov1x = (short)(size + (Math.Cos((circle - 20) * (Math.PI / 180)) * radius));
        short mov1y = (short)(size + (Math.Sin((circle - 20) * (Math.PI / 180)) * radius));
        short mov2x = (short)(size + (Math.Cos((circle) * (Math.PI / 180)) * radius));
        short mov2y = (short)(size + (Math.Sin((circle) * (Math.PI / 180)) * radius));

        // MOVE
        vdu.Enqueue((byte)25, (byte)4);
        vdu.Enqueue(size, size);

        // MOVE
        vdu.Enqueue((byte)25, (byte)4);
        vdu.Enqueue(mov1x, mov1y);

        // PLOT triangle fill
        vdu.Enqueue((byte)25, (byte)85);
        vdu.Enqueue(mov2x, mov2y);

        switch (cntr)
        {
            case 1:
                            cd = 4;
                            break;
            case 4:
                            cd = -1;
                            break;
            case 7:
                            cd = 16;
                            break;
            case 10:
                            cd = -4;
                            break;
            case 13:
                            cd = 1;
                            break;
            case 16:
                            cd = -16;
                            break;
        }
        c += cd;
    }
}

which renders the following display on Windows Vista,

Colour wheel display in Windows Vista

The Windows version is of higher quality because we have double the vertical resolution since Windows is used square pixels each half the size of the original rectangular pixels used in this screen mode on RISCOS. This is an example of a difference between historical implementations and our new implementation which we do not intend to address.

However, its possible to improve quality even further using the facilities of GDI+. We have implemented a new code (in the reserved for future expansion block) VDU 23, 28, n the purpose of which is to control rendering quality. In the current version we have implemented three quality levels. With the highest quality level, we get the following output:

Antialiased colour wheel display in Windows Vista

which was simply never possible with the original Acorn BBC BASIC.