April 26th, 2010 by Moggen

This week I used GDB debugging with hosted AROS for the first time. I had a bug that was difficult to find using debug log printing. The AROS crew is kind enough to supply some macros to GDB to ease the debugging process. When GDB initially loads the hosted AROS process it only loads the symbols present in the boot ELF executable file. To be able to see symbols for stuff that has been loaded inside AROS you have to load the symbol table manually to the correct memory address. The GDB macro findaddr can be used to identify memory and where it should have its symbol table loaded. This is described in the AROS docs. The bug was an embarrassingly simple case of not initializing a variable.

Other than this I have implemented a memory dump function to aid debugging. It simply dumps a list of all memory mappings currently in Emumiga to the debug console.

I stumbled upon a new thing when I was working on getting Clock running. Clock uses stack memory to set up some structures that gets converted into mappings when they are used with a syscall. This is OK behavior of course. The problem is that I have not implemented a garbage collection of mappings yet. So when the stack frame was released it did not remove the mapping. A later stack frame overlapped this memory and everything broke down. I solved it by always clearing the stack memory below SP when an instruction increases it or sets it to some value directly. No need to clear anything when decreasing SP. This affects all instructions that uses addressing mode (SP)+ and the instructions MOVEA, SUBA, ADDA, EXG, LEA, MOVEM and UNLK when they use SP. RTS is also increasing SP, but I skipped that one. There should never be mappings set up covering the return address.

April 19th, 2010 by Moggen

“Clock” can be shown in digital mode!.

The strange behavior I wrote about last time had an explanation. It was no dirty hack using array layouts, but an extension of the Menu and MenuItem by Gadtools. RKM is hinting it in the docs for CreateMenuA but does not reveal the details of how it is done. I found it better documented in gadtools.h: “A UserData pointer can be associated with each Menu and MenuItem structure. The CreateMenus() call allocates space for a UserData after each Menu or MenuItem (header, item or sub-item)”. There you go. This wasted quite some time debugging :-(

I have implemented locale.library’s FormatDate() this week. It is tricky as it uses a callback. I’ve implemented callbacks before in exec’s RawDoFmt() but this time the special Hook mechanism from utility.library was used. It was some work to get this right and to keep the mapping of the Hook structure as general as possible. Chances are high that it will be used somewhere else.

I’ve started sketching on an illustration in InkScape to show how syscalling works. It is a procedure that uses MsgPort communication between the emulation process and the “real” caller process. Callbacks add another dimension to it making it really complicated. I will post it here of course when it is finished.

April 11th, 2010 by Moggen

The clock is actually ticking now. It continues to redraw itself!
I have implemented GetMsg() and ReplyMsg(). The clock application assembles a signal mask to wait for the timerequest to be done or for any input from the UserPort in the window.
Selecting a menu triggers first a message for refresh to recreate the area that the menu occupied, and then a menupick message.

I stumbled upon a strange thing when clock is handling the menupick. First it uses the menu number from the menupick message with ItemAddress() to get a pointer to the MenuItem structure. Then it suddenly tries to read from a memory location past the end of the MenuItem structure causing a mapping fault. My guess is that it assumes that all MenuItems are arranged as an array in memory. Maybe gadtools CreateMenusA() does allocate them together as one chunk and places them in a specific order. Neither RKM or any other documentation I’ve read defines this behavior.
But it is a program written by the same people that wrote the OS so maybe it was a convention known inhouse but not put in the official API.

A workaround is to make sure that all the generated MenuItems from CreateMenusA is mapped in 68k virtual space tightly and in order so it can be accessed as an array. I will try this approach and see where it leads.

Another problem this week was the return type from GetMsg. The Message struct does not reveal if the message is an extended variant like IntuiMessage. I must simply know what type it is to make the correct mapping. But by keeping track of the message port and where it came from I can know this. If the message port pointer is read from for example Window->UserPort it is surely an IntuiMessage arriving there. And a port is only handling one type of message. It would be difficult to program against this API otherwise.

April 6th, 2010 by Moggen

I’ve been busy with family stuff during easter so there was not much spare time to work on Emumiga this week. But some progress has been made as you can see: Clock now shows the dial and hands!.

Wonderful, but it currently has a small problem.. It takes 3 seconds to draw everything. Lowering the debug level to a deployment level makes it draw in about one second. I must get it to draw faster than this as the clock is redrawn every second normally. But I’m not worried about this, I haven’t even begun with optimizations…

Most of the stuff implemented this week was with graphics.library’s AreaInfo and the associated drawing functions. Both area filling functions and line drawing is used by Clock, and the dial shape is drawn with AreaEllipse() and DrawEllipse().

Clock is using the copied RastPort I wrote about last time for these graphical operations. So when the copied data was used as input to the first of the drawing syscalls I had to parse all memory to create a real RastPort structure from it. I could of course try to identify that it is copying the whole structure by analyzing the 68k instruction flow in some intelligent way and assume that the copy will be used as an object later. But that would add quite some complexity so the easy solution is to emit binary data when copying and later parse it again.