Wednesday, July 01, 2009

What's working

In the screenshot below, you can see the following:

Two NetSurf windows (without any toolbar and with the status in the title bar).

A terminal window running a modified Brandy, the BASIC interpreter, with SYS calls available. The ROOL BASIC will also run, once decompressed, on the ARM emulator, which has the advantage of an inline assembler but the disadvantage of not being released under a free licence.

A native image viewer application, displaying an ArtWorks image rendered using the AWRender module.

A movie running on MPlayer.

And, of course, the Icon Bar and Filer windows.



All of the applications need a good deal of polishing up, but I'm quite happy with the state of the ARM emulation, which is good enough to run two quite demanding pieces of software (AWRender and BASIC105), and the SWI support is easily extendable. The emulator could be faster (it takes about 10 seconds to render the ArtWorks StartUp file, where my RPC takes 3-4s), but there are several ways to achieve that.

Monday, June 01, 2009

Some progress on the emulator

I've been working on the emulator, trying to get the ArtWorks file viewer AWViewer running on an x86 computer. I finally have some progress to report!



ROLF is being viewed via VNC, and the ArtWorks StartUp file is being displayed entirely using the AWRender module, called from AWViewer.!RunImage running on ROOL's BASIC105.

The blue border is due to some debug code (clearing the area to be redrawn to blue), the title of the window is not taken from the CreateWindow request, and the green text is because the font code needs some more work. There's still a long way to go, but it's a significant step forward.

Update:
The size of the text is due to the font manager being told that the screen is 90dpi, but ArtWorks expects 180dpi (because that's what my software tells it).

There's no transparency in the image (the droplets of water should be transparent), which, I'm told, was due to the renderer not being able to get dynamic areas properly. I've fixed the dynamic areas, but now I have to work on allowing the code to redirect output to sprites.

Thursday, April 16, 2009

Getting BBC BASIC to run on ROLF

I'm trying to get the BASIC105 module from ROOL to run using the compatibility library and ARM emulator.

Downloaded the module from:
http://www.riscosopen.org/content/downloads/module-zipfiles

Next, a program to load a single Relocatable Module:


#include <stdlib.h>

#include "rolf/compatibility/compatibility.h"
#include "rolf/compatibility/arm_emulator.h"

int main( int argc, const char *argv[] )
{
uint32_t regs[16];
uint32_t flags;

setenv( "RISCOS_MODULES", "BASIC105", 0 );

// Any old SWI, the first call to riscos_swi loads and
// initialises all the modules in RISCOS_MODULES (a
// colon-separated list of filenames)

riscos_swi( 0x0, regs, &flags );

return 0;
}


First problems:

1. I haven't implemented arguments to be passed to the module on initialisation (in r10). I can fake that in gdb, for the time being.

2. The module expects to be decompressed by the operating system (the init code has bit 31 set). What algorithm does it use?

[Update]
The decompression algorithm appears to be private, so I've ripped a decompressed version from my Risc PC.

The start code assumes it has memory to use at 0x8000, so I've given it some to be going on with.

The code makes use of multiple load and store instructions which load or store the base register, which I hadn't implemented.

I believe I've fixed that, now, and with the (quick and dirty) implementation of a few OS_ SWIs (WriteS, Write0, WriteI+... and ReadLine) I've got to the point where it prompts for input, but segfaults at a strange address that's exactly 0x20000000 lower than the return address in r14. I suspect that the module requires loading in the lowest 512MB, or even lower.

[Update 2]
Yes, allocating memory around the 64MB mark means that the code runs a lot longer.

A whole lot longer; it's time to disable logging the register contents on each ARM instruction!

[Update 3]
OK, the underlying problem is that the BASIC I have is 26-bit, and I'm not implementing that (yet). The 0x20000000 offset was due to the code clearing the C flag.

On the plus side, I found a bug in the emulator where loading a byte didn't clear the top 24 bits of the register. I'll go back to trying to get AWRender to work, now that's fixed.

Tuesday, February 24, 2009

Beagle board

A week or so ago, I got a Beagle board. So far, I've proved that it is unbrickable (by corrupting the NAND ROM and practically bricking it, then spending a couple of days and using a wide selection of computers and software to nurse it back to health).

Today I just got a self-built linux kernel to boot on it (not doing anything useful yet, though).

Once I'd got a set of working binutils and gcc (built for the arm-elf target), I got a long way, until the kernel was generating the uImage file. There were two problems.

The second, mkimage not found, was simple to fix - it comes with the u-boot code, also available here:
ftp://ftp.koansoftware.com/public/linux/mkimage


The first was heralded by the following error message:

"arm-elf-ld: ERROR: arch/arm/boot/compressed/misc.o uses VFP instructions, whereas arch/arm/boot/compressed/vmlinux does not"

It turned out the problem wasn't with arch/arm/boot/compressed/vmlinux at all (which is not surprising, since it's actually the output file), but with the head.o and piggy.o in the same directory.

The output of this command:

readelf -a arch/arm/boot/compressed/*.o | grep Flags:

included the lines:
Flags: 0x200, GNU EABI, software FP
Flags: 0x600, GNU EABI, software FP, VFP
Flags: 0x200, GNU EABI, software FP

What was needed was to re-assemble the head.S and piggy.S files with the -mfpu=vfp flag. Now, I doubt I've run any floating point code in the kernel since it's only booted up and hasn't really done anything, so it could be that I've compiled everything else wrong and it shouldn't use VFP, but that can wait for now.

Oh, I also edited drivers/video/omap/Makefile, to add the following line:

objs-y$(CONFIG_ARCH_OMAP3) += dispc.o



(I won't be able to work on anything for the next week and a half, but I'm looking forward to getting ROLF working on my TV, it's already worked with OMAP on the Nokia N800, and the VNC code points to a better solution.)

Friday, February 06, 2009

ARM emulation

Yesterday, I decided to implement my own ARM code emulator.

I think my problems with getting AWRender to work have been to do with self modifying ARM code in the AWRender module. I had a half-hearted go at finding a way to implement OS_SynchroniseCodeAreas with QEMU, then I decided to just implement my own.

The interface is very simple: global storage for the registers, and a routine that returns a pointer to some x86 code that implements whatever ARM code is pointed to by r15 on entry. The x86 code will return when it comes to an instruction it can't deal with by itself, such as a SWI or a floating point operation.

The idea is to keep the emulator as the core of an ARM system, and anything else that needs emulating (like an Operating System, or a co-processor) will be taken care of outside the core. That way, I think, I can create something that can be finished!

I'm moving away from QEMU for a couple of reasons. Firstly, because it does much more than I need and it's heading off in a direction of increased complexity. For example, when I found a bug in the (latest release) version I was using, I discovered that later versions (with that bug long since fixed) don't work the same way as the one I had been working with, and I was told that, surprisingly, I didn't really want to use it that way!

Another reason is that a stripped version of the QEMU library is a little under half a megabyte in size (478568 bytes, to be specific), whereas my replacement is about 8k, at the moment, with maybe half the instruction set dealt with (bearing in mind that floating point is a co-processor feature). Perhaps I could strip QEMU down, but not that far, and not that quickly.

QEMU has given me some good ideas about how to approach the problem, but it's too bloated for my liking, now.

Update: It's going quite well.

It took me a while to work out that the x86 uses the carry flag in the opposite way to the ARM when subtracting, that jb isn't quite the same as BHI, and a day and a half to realise that I'd implemented BIC as AND instead of AND NOT.

Anyway, I'm now at the point where I have to start looking at which SWIs to emulate in order to get AWRender to, well, render something. I've chosen to attempt to get the freely available ArtWorks renderer working as a proof of concept for the compatibility layer (the whole thing isn't free, but apparently very good). Unfortunately, the application doesn't work out of the box, because the BASIC uses inline assembler and Brandy (http://sourceforge.net/projects/brandy) doesn't include that. I'll ask on comp.sys.acorn.programmer if there's an alternative that does.

Wednesday, December 10, 2008

Update

I'm moving my code into an SVN repository, something I should have done a while ago.

I've sorted out the rather horrible looking text problem by ignoring FT2's 1/64th pixel resolution in favour of absolute millipoints. If text should fit in an inch at 12pt size, it should fit in a half inch at 6pt (and the dpi of the display should not be allowed to affect that).

NetSurf is coming along, in a horrible, hacked way!

In general, nothing to release, but still working on it.

Thursday, October 30, 2008

RISC OS Compatibility

The primary goal of ROLF was always to produce an operating system that provided a programming and user experience as similar to RISC OS as possible. It was never about running particular RO programs, although I had given the concept some thought.

In response to some postings on Drobe, I thought I'd have another look at the compatibility library that is intended to be used by Brandy and QEMU.

I've implemented a very few SWIs in the library and sucessfully integrated (hacked) it into Brandy (although any programs using TIME= will get out of sync with OS_ReadMonotonicClock).

I've since started looking at QEMU, and it looks promising.

The emulator code is released under the LGPL and so I should be able to integrate it into the compatibility library. That should mean that I can provide SWI decoder code that can search both native i386 routines and also Relocatable Modules from RO, which can then call i386 SWIs.

Some outstanding questions:

Should the RMA be a shared memory area? (This would allow RMs to provide inter-process communication, but opens up a whole can of worms with locking the code/memory areas.)

Can restricting RM SWI calls to when the application has a lock on the Wimp (i.e. has received a non-redraw event from the Wimp) work? (Not really, Artworks, for example would need it's RMs' routines when redrawing.)

Update: [3 Nov] After a little more work, I've got various relocatable modules initialising and executing SWIs. For simplicity, I've gone for loading all the modules in each application, no shared memory; that means that only utility-style modules will work (task modules won't at all). ARM SWIs may call native (i386) code SWIs, but they can't call ARM module provided SWIs. (Also, I haven't looked at returning flags properly, including setting the V flag on a failed exit.) For each SWI a module needs, I either have to soft-load another module or implement the SWIs natively; of course the RISC OS modules aren't freely distributable.

Update 2: [4th Nov] I made the mistake of softloading Font Manager 3.40 (17 Aug 1998), which got some distance, but then failed for what I finally worked out was a non-32bit compatible instruction (of course, it's from 1998). So, now I'll have a look at the 41 Font_ SWIs.

Update 3: [10 Nov] I've been trying to get the ArtWorks renderer module to work, with permission and documentation from Martin Wuerthner. It's an interesting interface, in that it gives you a pointer to a routine within the relocatable module for the application to call and you have to pass the address of a callback routine to the renderer, so it can request more memory (among other things). That seems to be working, in that the ARM code runs and, with the addition of two special SWIs ROLF_RunARMCode and ROLF_CallOut, native code can call the ARM routines and ARM code can call native code (i.e. C, written and compiled under x86 Linux). Unfortunately, I seem to have done something wrong and the simple AWRender_DocBounds SWI fails. I'm working on that, and on making RO applications transparently executable on Linux.

Update 4: It seems to be a bug in QEMU, and Justin Fletcher's already been there! Unfortunately, it doesn't look like his quick fix is sufficient, so it looks like I'll have to have a look at the qemu internals.

Update 5: [12 Nov] OK, I've made a patch for QEMU which seems to work, but I should test it a bit more before sending it in. I'm trying to get the ArtWorks renderer module, http://www.mw-software.com/software/awmodules/awrender.html (and its dependencies) to work; it's a utility module that stresses the compatibility library (so similar modules should be easier to get to work), and Martin Wuerthner is supportive of my attempts. The framework appears to be working OK, so now its back to adding support for more low-level SWIs.

The comments are appreciated, I'll try to keep posting updates.