Aros/Developer/Docs

Navbar for the Aros wikibook
Aros User
Aros User Docs
Aros User FAQs
Aros User Applications
Aros User DOS Shell
Aros/User/AmigaLegacy
Aros Dev Docs
Aros Developer Docs
Porting Software from AmigaOS/SDL
For Zune Beginners
Zune .MUI Classes
For SDL Beginners
Aros Developer BuildSystem
Specific platforms
Aros x86 Complete System HCL
Aros x86 Audio/Video Support
Aros x86 Network Support
Aros Intel AMD x86 Installing
Aros Storage Support IDE SATA etc
Aros Poseidon USB Support
x86-64 Support
Motorola 68k Amiga Support
Linux and FreeBSD Support
Windows Mingw and MacOSX Support
Android Support
Arm Raspberry Pi Support
PPC Power Architecture
misc
Aros Public License

A technical overview of AROS edit

Google translation German, French, Italian, Spanish, Hindi, Chinese, Russian, Polish, Portuguese

AROS,[1] like AmigaOS (TM), is a message-passing, preemptive multitasking OS.

It uses re-entrant shared libraries to save memory space.

AROS is based around an executive library kernel (Exec) and two other libraries:

  • Exec (the "kernel", which is not a kernel in the modern sense),
  • Intuition (graphics and GUI, integrated into the system) and
  • AmigaDOS (Disk Operating System, the Metacomco's Tripos modified to work with Exec).

The design philosophies of AmigaDOS and Intuition are rather different, the former adopting a C-like API and the latter creating an object-oriented, message passing aware environment for the programmer. The system base is the only absolute address in AmigaOS (located at 0x00000004) - everything else is dynamically loaded. The OS is well known for delivering high performance due to its close connections with the hardware, while simultaneously having the flexibility to support re-targetable graphics (Cybergraphics) and retargetable audio subsystems (AHI).

Diagram showing relationships of libraries to system needed


Remember, AROS is a research operating system, and while all contributions to the base AROS code are welcome, please bear this in mind and contact the dev list first. Writing applications for AROS does not have this limitation.

While AROS appears and feels almost feature complete, it is still missing a small number of functions from the Amiga API - as well as implementations of core functionality. There are also a number of user applications that, while not strictly part of the AmigaOS 3.1 environment, need to be written.


If you want to port software there are essentially two supported method: either you compile directly under AROS, which can be running on either real hardware, virtual hardware or in hosted mode under linux/window or you cross-compile from linux.

It all depends on whether you want to work on system itself or be a developer who writes/compiles app software for AROS


the repository for the current development version ABIv1 is located here, the repository for current stable PC version ABIv0 with backported ABIv1 features is located here - AROS One and Icaros based

Further documentation is available here

Any issues or questions can be asked here or slack here, Everyone is over on Discord@AmigaDev, also the AROSExec discord server is available



Software Development for AROS edit

Programming languages edit

Apart from 'The Developer Environment', which primarily supports C/C++ code, there are other programming languages available for AROS:

Scripting

DOS, included in all
LUA, included in all or Hollywood
REXX Regina (AROS' ARexx), included in all
Python [ Info], included in Icaros
Ruby Info/download

Basic

Amos Pro compatible commands (all incomplete)
X-Amos Discussion List
SDLBasic (download)
Alvyn (download)
Basic4SDL (download)
Project Deimos [1]
Blitz Basic none on AROS
Monkey
Amiblitz on JanusUAE amiga(TM) emulator
Amiga Basic
ACEBasic

Misc

AmigaE Portable E
FreePascal FPC Aros-Exec thread, Download, LCL, FreePascal for AROS has its own Wikibook
LLVM,
sge2d, Download 2D Game Engine SDL


Where to get the C/C++ Environment edit

If you want to develop for AROS, its generally easier to be running linux hosted AROS development environment especially for C++, cross compiling the code. That's how most developers are doing it. g++ is used to compile owb web browser as well as some other AROS software. If you were hoping for a rich set of C++ libraries or classes defined for the OS feature set, you might be disappointed.

AROS Native compiling is possible, but you're much more likely to run into the odd bug(s) in the dev environment since it gets little testing and fixing by other developers.

Is there a sftp software or scp over ssh available? Nope. There isn't. Would be easier if at least the security part would be handled, porting amissl


Cross compilers from other OSs edit

Pre compiled versions of AROS ABIv0 Linux hosted can be found here


And as always has been the case you can use the contrib archive to 'obtain' the development directory which contains the /native/ AROS gcc compiler and tools. That compiler is used to build AROS itself but can be used outside the AROS build process by providing --sysroot with indicated directory to cross compile for AROS.


you want to build AROS. No problem.

Here are instructions for 64-bit: https://github.com/deadw00d/AROS/blob/master/INSTALL.md

Here are instructions for 32-bit: https://github.com/deadw00d/AROS/blob/alt-abiv0/INSTALL.md


32-bit Linux hosted AROS and compiling AROS apps for Linux which runs without problems on 64-bit linux distributions and all currently available software will run on it as well


Please install these packages before moving to next step. Below is a reference list for Debian-based distributions. Reference build system is Ubuntu 18.04/20.04 amd64.

subversion git-core gcc g++ make gawk bison flex bzip2 netpbm autoconf automake libx11-dev libxext-dev libc6-dev liblzo2-dev libxxf86vm-dev libpng-dev gcc-multilib libsdl1.2-dev byacc python-mako libxcursor-dev cmake zsh mingw64

Do all of these operations under home directory of your user or another directory where your user has write permissions.

Specifically, in a section "Linux-i386", be sure first to build the cross-compiler (toolchain-alt-abiv0-i386) and only then AROS itself (alt-abiv0-linux-i386).


Clone & build

$ mkdir myrepo
$ cd myrepo
$ git clone https://github.com/deadw00d/AROS.git AROS
$ cd AROS
$ git checkout alt-abiv0
$ cd ..
$ cp ./AROS/scripts/rebuild.sh .
$ ./rebuild.sh

Now to the build selection below - Linux-i386

Select toolchain-alt-abiv0-i386 - Select alt-abiv0-linux-i386 (DEBUG)

Start AROS by:

$ cd alt-abiv0-linux-i386/bin/linux-i386/AROS
$ ./Arch/linux/AROSBootstrap


Pc-i386 Select toolchain-alt-abiv0-i386 (if not built yet) - Select alt-abiv0-pc-i386

ISO image available in alt-abiv0-pc-i386/distfiles


Now that we have linux-hosted build, we can resume native (option 2). Run ./rebuild.sh and selection option 2. Wait until it finished, then:

$ cd alt-abiv0-pc-i386
$ make

Now

$ make bootiso


Now, your compiler is located in toolchain-alt-abiv0-i386 directory and named i386-aros-gcc. Includes are in alt-abiv0-linux-i386-d/bin/linux-i386/AROS/Development/include and libraries are in alt-abiv0-linux-i386-d/bin/linux-i386/AROS/Development.lib.

This is how then can be passed to the compiler:

/home/xxx/toolchain-alt-abiv0-i386/i386-aros-gcc --sysroot /home/xxx/alt-abiv0-linux-i386-d/bin/linux-i386/AROS/Development -L/home/xxx/alt-abiv0-linux-i386-d/bin/linux-i386/AROS/Development/lib

../toolchain-alt-abiv0-i386/i386-aros-gcc --sysroot bin/linux-i386/AROS/Development local/helloworld/helloworld.c -o local/helloworld/helloworld


Slack Dev Forum


Another Linux option is to use cross-compilers for Linux.

Another is using Debian like distros and download the gimmearos.sh script (on aros-archives) to setup the developer environment by downloading necessary packages ... The gimmearos script is a good start in that direction, building the cross compilers and hosted AROS environment, but gimmearos.sh might be out of date or not be completely compatible with any given linux distro.

In order to do that, you have to compile AROS yourself. Download AROS source archive not contrib. Compile AROS by entering the main directory

./configure
make

(More on compiling AROS). The result will be a basic AROS system without development tools.

To compile C++ on Linux, type 'make gnu-contrib-crosstools', creating the cross-compilers in ./bin/linux-i386/tools/, named i386-aros-gcc, etc.

Note: Currently, to make the cross compilers usable copy 'collect-aros' from tools/ to tools/i386-aros/bin/. At the moment the cross compilers if used from the Linux command line will only find it when it's there.

If you want to compile native compilers (the Developer Environment), type 'make contrib-gnu-gcc', creating native compilers in AROS' System:Development/bin directory.

When the output needs to be stripped --strip-unneeded --remove-section .comment

The Obj-C backend should build out of the box.

Open contrib/gnu/gcc/mmakefile.src and search for the line which contains "--enable-languages" and add "objc" to the list of languages that follows it.

   --enable-languages=c,c++,objc

Better make it—enable-languages=c,c++,objc,obj-c++

ObjC++ is broken as soon as you try to use exceptions, but that might change in future GCC versions and it does not hurt having it there already.



Do you need a cross-compiler or a real compiler? In the first case you can get away with just downloading the proper gcc archive, apply the patch and proceed with the normal gcc build. In the case of a real cross-compiler then when downloading the contrib sources, also need to download the normal sources, place the contrib sources into a directory called contrib, need to install autoconf+automake+perl+python, call ./configure, cd into the subdirectory and type make.

to rebuild GCC with host == build == target == i386-pc-aros. So just get the vanilla sources and apply the patches without bothering about the build system?


pre-configured VM environment vmware virtual machine to develop AROS and AROS software


Windows(TM) AmiDevCpp Old versions is a cross-compiling developer environment for Windows, able to create binaries for AROS, AmigaOS, and MorphOS. Upgrading gcc versions



64 bit

First thing you need is Linux system, suggest Ubuntu, with installed cmake and x86_64-aros cross-compiler. In order to get the cross-compiler you need to build AROS (either linux-x86_64 or pc-x86_64, I suggest linux-x86_64) locally on that machine. The build instructions for AROS are available here: http://aros.sourceforge.net/documentation/developers/compiling.php

Once you have the cross compiler and make available, we can continue.

How to create a AROS dev environment if you want to do that by yourself


A hub page to start with Icaros 64 https://vmwaros.blogspot.com/p/64-bit.html


32 bit

A good option for multiple OS is AxRuntime lets developers compile their Amiga API-based applications as Linux binaries being able to utilize modern development tools available on Linux, like IDEs, debuggers, profilers, etc


Native compilers for AROS edit

Namely gcc for C or g++ for C++ are supplied with the Developer Environment, which is already setup and part of any current AROS distribution like AROS One, Icaros or the nightlies but not Icaros Lite

Currently, the developer environment consists of the following software components. GNU GCC 4.x GNU BinUtils, GNU Fileutils 4.x, GNU Textutils and others.

On single partition systems and the Boot ISO, the AROS Developer environment is installed under "SYS:Development/". Systems with multiple partitions - such as a Work: partition - tend to install it to there instead, however it can be installed manually to any location. Please remember, if moving, that you will need to correct the Development packages 'install location' env variable to point to the new locations root - look in SYS:S/startup-sequence.

Assign Development: SYS:Development 
Assign C: Development:bin ADD 


In the aros build instructions. you need to check out contrib and/or ports into your AROS source directory, as subdirs. then, assuming you are building in an external build dir, as you should, you simply configure and "make contrib" for instance or whatever submodule you might want to build.



Beginners Tutorials in C C++ edit

As AROS is C based API compatible to AmigaOS 3.x, so most of the information on programming C on the Amiga applies to AROS as well. Please note that there is a lot of AOS 1.3 (not so useful) and AmigaOS AOS 2.x information around as well.

Curly brackets missing - try SHIFT + ALT + 7 or 0.


Brief overview of what is required to write AROS Applications

  1. Using Intuition for basic screens/windows
  2. Using graphics within windows via 8bit graphics and so onto 15-16-24bit cybergraphx
  3. Load and save work to dos disk drives
  4. Using the ZUNE GUI Environment


Writing native games require this extra information

  1. Using AHI audio hardware independent API
  2. Using USB joystick/joypad with the Poseidon USB stack through LowLevel library


Additional features that could be added later

  1. Adding additional Locale language translations to your program
  2. Adding a AREXX/Regina port to your application
  3. Copy'n'paste actions: using AROS' Clipboard and use open/write/read/close
  4. Executing Amiga(TM) DOS commands from your application
  5. Using icons (.info files) and icon tooltypes (stack, version, and program startup options)

A good introduction to Amiga programming in general, though a little outdated, is Rob Peck's book "Programmer's Guide to the Amiga". The Amiga ROM Kernel manuals: Libraries (3rd edition), and The AmigaDOS manual (3rd edition) are the most generally useful books, the other RKMs, including the Style Guide also have their uses. There were many reference examples from AmigaMail and Devcon notes (available again on an Amiga developers CD).

If using Arexx then "The Amiga Programmer's Guide to ARexx" by Eric Giguere, which was published by Commodore is useful as well as an "Arexx Cookbook".



  • Source can be found here and here and here. Lots of example code can be found inside AROS sources themselves. DOWNLOAD the contrib source archives from Aros site, and study the AROS applications source code, e.g. the test programs from the Tests drawer (folder/directory). Take a look at the code of some smaller AROS programs might be a better and more up to date guide. There a quite a lot of nice examples hidden in the AROS SVN.

When you upload your builds, please write the architecture (like i386-aros, x86_64-aros, etc) in the archive name and it is also advisable to write in the field "Requirements" what ABI (ABIv0 or ABI-WIP or ABIv1)


Compiling C/C++ Code edit

Native, although we have a IDE Integrated Development Environment (Murks), it does lack a debugger. Whilst others use a combination of a text editor and shell to edit code. Most though use an AROS hosted on Linux to take advantage of the better GCC tools like GDB and various IDEs.

Open shell - its a menu option at the top left of Wanderer (desktop). Or by using the right Win key and w (or F12 and w) within the directory with the source code. Type in

sh 

to change the amiga shell into a unix shell. You can then type in ls (unix equivalent to amiga dir). Take a look here for more commands.

For a single file program-name.c or program-name.cpp

gcc -o program-name program-name.c  

or

g++ -o program-name program-name.cpp

or

g++ -o test -Wall -g main.cc texturelib.cpp xmodelib.cc -lsdl -lgl

To close the shell, click on the top left-hand corner to close (twice). Once to get back the aros shell and then again to close finally. Use cksfv as a test.

Some source code requires the addition of Amiga API libraries, like dos, which you can flag at the compile time as

gcc -o julia.exe julia.c -ldos

For DOS use -ldos as example and if you are compiling mui codes it will be -lmui or intuition -lintuition. Other missing symbols are due to linker libraries being necessary for linking in functions that aren't in the standard C libraries. For example some source code would need added

-lz or -lm or -lpng or -larosc etc.

use this in unix line command mode to search for 'search-item' in many .c files (*.cpp for c++, etc.)

grep -l 'search-item' *.c

If the program is not executable, try using parameter fno-common


More information: Aros/Developer/Porting software


How to make Apps have AROS 64-bit specific support code edit

Portable code

AROS64 already uses 64bit addressing, it just doesn't setup the MMU for more than 4GB physical memory currently. When porting software to AROS64 it is "mostly" a case of converting ULONG's that are used to store pointers, into IPTR's instead, etc. Another quirk, is making sure items on the stack are the correct size by using the STACKED attribute for them.

  • Use texteditor or some tool to replace all "ULONG" with "IPTR" and "LONG" with "SIPTR" in the sources.

compiling mui stuff for aros setting -std=gnu99 is necessary, had -std=c99 usually A MUI application most likely needs only the HOOKPROTOxxx SDI macros. They are compatible with AROS, only the attributes (hook, object attribute) must be given in the right order.


Coding conventions edit

As the AROS core source is a shared developer experience, there are rules regarding structure and style. When it comes to your creating your own app and coding, the structure and style should be your own, i.e. you should enjoy what you do and do it so that you can understand what is going on.

Layout edit

static void 1st_function()
{
    program
    exit(0);    
}

int main(void)
{
    1st_function();
    2nd_function();
    3rd_function();
    return 0;
}
struct Screen * openscreen(void);
struct Window *openwindow(struct Screen *screen, const char *title, LONG x, LONG y, LONG w, LONG h);

VOID 1st_function();
VOID 2nd_function();

int main(int argc, char **argv)
{
    program
    return 0;
} /* main */

VOID 1st_function()
{

}

VOID 2nd_function()
{

}

General style edit

This code is used by many people and therefore you should keep some things in mind when you submit source code:

  • Keep things simple
  • Keep the source clean
  • Always know what you are doing, if not flag it and describe what needs to be done...
  • Explain clearly/simply what you are doing
  • Remember that you write code once but that it is read many times by many people

Comments edit

AROS uses some of the comments in the source to generate the documentation. Therefore it's necessary to keep a certain format so the tools can find their information. Other comments are ignored but they should explain what you thought when you wrote the code. If you really can't think of an explanation, then don't write the code a second time like this:

/* This adds 1 to t */
t ++;

What we think of is this:

/* Go on with next element */
t ++;

Formatting edit

This is only IMPORTANT if you are going to work on the core AROS code or contrib but not applications which may reside outside like on AROS Archives or other websites.

{
    /* a */
    struct RastPort * rp;
    int               a;

    /* b */
    rp = NULL;
    a  = 1;

    /* c */
    if (a == 1)
        printf ("Init worked\n");

    /* d */
    if
    (
        !(rp = Get_a_pointer_to_the_RastPort
            (
                some
                , long
                , arguments
            )
        )
    ||
        a <= 0
    )
    {
        printf ("Something failed\n");
        return FAIL;
    }

    /* e */
    a = printf ("My RastPort is %p, a=%d\n"
        , rp
        , a
    );

    return OK;
}

Looks ugly, eh ? :-) Ok, here are the rules:

If several lines contain similar code, put similar things below each other (see a and b);
Put spaces between operands and operators
Put braces {}, brackets [] and parentheses () below each other (d) if there is much code between. 
Brackets and parentheses may be in one line if the code between is small (c)
Indent by 4 Spaces. Two indent levels may be abbreviated by one tab.

Before committing please normalize the indentation - if you have a mixture of tabs and spaced - please always use spaces, 1 tab = 4 spaces.

The reasons for this are:

  1. While some editors can use an arbitrary sizes for tabs, it's a bit complicated to tell another editor which tab size was used by the one used to write the code.
  2. Most code in AROS was written this way and your code should look like the rest.
  3. You can print this code on any printer without special tools to "fix" the tabs.
  4. Most editors have smart tabs which do exactly this. If your editor doesn't, write a bug report.

If you have a function with many arguments (d, e) you should put the parentheses in lines of their own and each argument in one line (d) or put the first argument behind the opening parentheses (e) and each following argument in a line of its own with the comma in front. The closing parentheses is in a line of its own and aligned with the beginning of the expression (i.e. the a and not the opening parentheses or the printf()).

Use a single blank line to separate logical blocks. Large comments should have a blank line before and after them, small comments should be put before the code they explain with only one blank line before them.

If you see any TABS in AROS core sources then the suggestion is to "detab the file and commit that separately" either before or afterwards from making functionality changes. Make two commits instead of one. This makes it easier for others to see the real changes instead of having to dig through multiple lines of irrelevant diffs.

Eliminating Global Variables edit

i.e. pass variables to functions (local scope) or classes making it easier to track and debug your code.

Any time you find that you need a particular thing in 'a lot of different places', chances are that all those places are conceptually related, and so you can create a class, a namespace, a function, or some other higher-level organizational unit to represent that relationship. This makes the program easier to understand.

Bad Designs

  • All variables are global.
  • There are no standalone functions, only sub-procedures which act on the global variables.
  • Every sub-procedure is at least 500 lines to several thousand
  • Every sub-procedure has more than one task to perform
  • Copy-paste is preferred to writing methods, AND subtle changes are made in the middle of the code

Good Designs

  • structure program into functions (C or basic) - top-down procedural approach
  • put in class(es) (freepascal or C++) - the object is fixed and you use methods to access the object
 class String_List
 {
 private:
 list<string> m_List;  // member
 public:
 void read_strings() { /* read strings into m_List */ }
 void print_strings() { /* write contents of m_List to stdout */ }
 void sort_strings() { /* sort contents of m_List */ }
 void sort_strings_reverse() { /* reverse-sort contents of m_List */ }
 void unique_strings() { /* remove duplicate strings */ }
 };

 int main()
 {
 String_List myList;  // local
 myList.read_strings();
 myList.sort_strings();
 myList.print_strings();
 myList.sort_strings_reverse();
 myList.print_strings();
 myList.unique_strings();
 myList.print_strings();
 return 0;
 }

This way it is very easy to replace the list with new list for debugging purposes, or replacing the methods without replacing the list, when you want different results. You only have to replace the content of the local variables.

So create the structure that matches your data (linked lists, trees, arrays, etc) and what to do with them (sorting, searching, etc)
.h usually contain #define #include typedef enum struct extern screen and window definitions (data structures)
.c should contains functions and algorithms

One way to look at it is that menu headings act as the .c file and sub-menu headings as functions.

When you start a project, you place a couple of declarations in the include file. As the project continues, you place more and more declarations in the include file, some of which refer to or contain previous declarations. Before you know it, you have a real mess on your hands. The majority of your source files have knowledge of the data structures and directly reference elements from the structures. Making changes in an environment where many data structures directly refer to other data structures becomes, at best, a headache. Consider what happens when you change a data structure.

Use good variables names to help clarify code and only comment when you need to explain why a certain programming approach was made.

You're Refactoring Legacy Code, you see a global, you want to get rid of it. How do you do this?

Exactly what to do depends on how the global is used. The first step is to find all uses of the global throughout the code, and get a feel for what the significance of the variable is and how it relates to the rest of the program. Pay particular attention to the "lifetime" of the variable (when it gets initialized, when it is first used, when it is last used, how it gets cleaned up). Then, you will probably make the global a data member of a class (for OO languages), or you will write some get/set functions. Converting to the Singleton Pattern is common, but you may discover that it makes more sense for the data element to be a member of an existing singleton, or maybe even an instance variable.

  1. Create a basic read method, either as a class or a global function. Replace all reads with the access method, but leave the variable defined as a global.
  2. Review each of the writes to the method and extract action functions one at a time. Unless two operations are coded identically in the original code, extract each write access separately.
  3. Change the variable scope from global to local.
  4. Analyze similar action functions to determine if any can be merged, i.e., there are no functional differences in the results of the function, just differences in the implementation details.
  5. Review the calls to the read method and see if a more complex functionality should be applied. Follow the approach for writes and unless implementations are identical, create separate access functions.
  6. Analyze the access functions for duplication.

As returning variables by "passing by value" are forgotten, so "passing by reference" is often used instead. The reference is a pointer to the variable so the value is remembered when returned.

Alternatives

  • Hidden Globals
  • Singleton Pattern
  • Database or TupleSpace
  • Context Object
  • Dependency Injection
  • Stateful Procedures

AROS/AmigaOS APIs and Docs edit

Library:
   - Private data structure
   - Many public access methods

Device:
   - Private data structure
   - Two (BeginIO/AbortIO) access methods

Resource:
   - Public data structure
   - *NO* access methods

And, being Amiga OS-compatible, there are exceptions to all of these.


System Libraries edit

The AROS Guide To Libraries can be used as a guide to individual commands and Old Dev Docs are used in application programming.

The generated Aros AutoDocs HTML Read or download docs-html.bz2 from here.

Amiga/Aros styles libraries are very different from windows and linux libs. Typical .so/dll libraries are foreign to most Amiga-like OS



AROS Subsystems edit

  1. Zune MUI compatible GUI
  2. AROS Application Packages
  3. AHI Audio Drivers - Usage/Development
  4. AROSTCP Sana2 Network Interface Drivers - Usage/Development
  5. gfx.hidd/cybergraphics Video Drivers - Usage/Development
  6. IO Device Drivers - Usage/Development
  7. USB Device Drivers - Usage/Development
  8. PCI Device Drivers - Usage/Development
  9. SDL
  10. Gallium 3D openGL aka Mesa - Usage/Development Swfitless
  11. A small subset of GTK2 through MUI-GTK
  12. Cairo 2D Engine - Usage/Development
  13. Scalos desktop API and plugin modules


HIDDs edit

HIDD are used for device/peripheral low level hardware support drivers. The HIDD system is split up into a collection of classes with a strict inheritance hierarchy. A HIDD class implements a device driver for a single device or in rare cases a group of devices and provides an interface for other programs and devices to access.

In order to maintain portability of interfaces across a wide range of hardware this interface will in general not present the raw interface to the underlying hardware. Instead it will present a generic interface that describes many different hardware implementations. This allows for the best reuse of both interfaces and code.

HIDD API is heavyweight though. You need to open a HIDD library, open oop.library, instantiate an object (even if there's no object); and object calls are more costly compared to plain library calls.


Basically your task is to implement a subclass of hidd.ata.bus for your hardware. just implementing the XXXATA__Hidd_ATABus__xxxxxx methods for the Amiga chipset - and appropriate versions of the interface_xxx.c file(s). pretty much everything in probe.c could be ignored - just write a replacement scan for relevant amiga devices and store whatever info you need in the bus data? only the "SUPPORT_LEGACY" blocks might be related.

You do not need to depend on PCI API. PCI is just a way to discover the hardware on PCs, etc. <hidd/pci.h> includes (at some depth) <interface/HW.h>, which defines IID_HW. This comes from the 'generic' HIDD class in:

rom/hidds/hidd/hiddclass.conf

did not split up HIDD and HW because they are always used in pair. It's the same as hidd/pci.h bringing definition for: PCI, PCIDriver and PCIDevice. PCI is actually PCIHW, just the name was not changed for backwards compatibility reasons. HW is a 'hub' where HIDD instances plug in.

ATA HIDD aoHidd_ATABus_Use32Bit value is completely ignored unless ata.device first detects correct command line parameter. Yes. Unfortunately I was unable to find any comment in code or svn history with explanations. Looked at Linux source, there 32-bit PIO is also controller driver's property. Some of them enable it, some don't.

Actually, switching the default to ON should be safe. ata.device is fail-safe at this because during IDENTIFY command it validates upper 16 bits, and if they appear to be zeroes in all 128 longwords, then 32-bit mode is switched off. But, nevertheless, I know how tricky hardware can be, so I decided not to change original behavior. If you think it's wrong in some cases, then it's possible to add one more attribute like aHidd_ATABus_Default32Bit. If set to YES, then this means that 32-bit PIO is safe to use by default.


Devices edit

The Amiga used Devices to communicate with additional hardware. AROS has replaced these hardware devices with hidd equivalents but some are still retained for backwards compatibility.

Local libraries/devices/handlers,etc are supposed to override the ones in ROM if their version is higher than the one in ROM.

Here is the list of commands exec default:

CMD_CLEAR Purge the buffer of the device
CMD_READ Playback Control
CMD_STOP Stopped the activity of the device
CMD_FLUSH Empty the queue of commands
CMD_RESET Reset a device
CMD_WRITE Playback Control
CMD_INVALID Create an error
CMD_UPDATE Gets updated device
CMD_START Will restart the device

While most other "stuff you communicate with" in AmigaOS are devices [2] that share a common base interface. OS 1.3 Device Drivers.


Handlers edit

pipe.handler
port.handler
sfs.handler
fat.handler
pfs.handler
fuse.handler
ffs.handler

filesystem handlers have their own separate system consisting of completely differently structured messages that dos.library use to pass requests (for things like reading, writing, getting directory contents etc.) to them. AROS originally went with implementing filesystem handlers as devices, which might arguably be more consistent with the rest of the AmigaOS API but which is quite incompatible with AmigaOS itself. However, it made it far harder to port filesystems and the gains were comparatively small, and so there's been a long standing goal of fixing this incompatibility. It has now, June 2011, been reintroduced to all AROS flavors.

are argstr and argsize valid for the handler startup environment? DOS/RunHandler() calls DOS/CreateNewProcTags(), and then CallEntry() (in rom/dos/exit.c) to start the handler, so yes, argstr and argsize are *present* in the call signature of the handler.

Granted, argstr will be NULL and argsize 0, but those values *are* passed to the handler function using:

AROS_UFC3(ULONG, entry,
                         AROS_UFCA(STRPTR, argptr, A0),
                         AROS_UFCA(ULONG, argsize, D0),
                         AROS_UFCA(struct ExecBase *, SysBase, A6));

Creating your own [without the whole build tree http://pagesperso-orange.fr/franck.charlet/temp/radeon.zip] and then

make stub
make
make install

SFS has two Root blocks, one at the start and one at the end of the disk. The Root blocks both contain the same information. They hold various information about the disk structure and have the locations of some important blocks used by the filesystem.

The Root ObjectContainer contains the Root directory Object. The name of this Object is the name of the volume. It is identical to a normal directory Object.

The Bitmap is used to keep track of free space. Each bit in a bitmap represents a single block. A set bit indicates a free block and a cleared bit a used block.

AdminSpaceContainers are used to keep track of space which has been reserved for storing administration blocks. Only the Bitmap, the Root blocks and the actual data stored in files aren't stored in administration space. Administration space is allocated in chunks of 32 blocks at a time. A single AdminSpaceContainer can hold information about a large number of such areas each of which has its own little bitmap of 32 bits.

Extents are stored in a B-Tree. The Root block holds a pointer to the root of the Extent B-Tree. Extents keep track of space in use by a specific file. Each fragment a file consists of has its own Extent. Extents are in a double linked list. The list can be used to locate the next or previous fragment of a file.

Below is the standard block header. This header is found before EVERY type of block used in the filesystem, except data blocks. The id field is used to check if the block is of the correct type when it is being referred to using a BLCK pointer. The checksum field is the SUM of all LONGs in a block plus one, and then negated. When applying a checksum the checksum field itself should be set to zero. The checking a checksum the checksum is okay if the result of the checksum equals zero. The ownblock BLCK pointer points to the block itself. This field is an extra safety check to ensure we are using a valid block.

Field Type Description id ULONG The id field is used to identify the type of block we are dealing with. It is used to make sure that when referencing a block we got a block of the correct type. The id consist of 4 bytes and each blocktype has its own unique foure letter code. checksum ULONG This field contains the sum of all longs in this block, plus one and then negated. The checksum can be used to check if the block hasn't been corrupted in any way. ownblock BLCK Points to itself, or in other words, this field contains the block number of this block. This is yet another way to check whether or not a block is valid.

struct fsBlockHeader {
    ULONG id;
    ULONG checksum;
    BLCK ownblock;
};

The algorithm to calculate the checksum of a block:

ULONG calcchecksum(struct fsBlockHeader *block, LONG blocksize} {
    ULONG *data=(ULONG *)block;
    ULONG checksum=1;

    block->checksum=0;

    while(blocksize>0) {
        checksum+=*data++;
        blocksize-=4;
    }

    return(-checksum);
} 

A Root block contains very important information about the structure of a SFS disk. It has information on the location and size of the disk, the blocksize used, locations of various important blocks, version information and some filesystem specific settings.

A SFS disk has two Root blocks; one located at the start of the partition and one at the end. On startup the filesystem will check both Roots to see if it is a valid SFS disk. If either one is missing SFS can still continue (although at the moment it won't).

A Root block could be missing on purpose. For example, if you extend the partition at the end (adding a few MB's) then SFS can detect this with the information stored in the Root block located at the beginning (since only the end-offset has changed). Same goes for the other way around, as long as you don't change start and end point at the same time.

When a Root block is missing because the partition has been made a bit larger, then SFS will in the future be able to resize itself without re-formatting the disk.

Field Type Description bheader struct fsBlockHeader Standard block header. version UWORD The version of the filesystem block structure. You can check this field to identify what version of the filesystem your dealing with it and to see if you can handle this structure correctly. Don't try to interpret the disk's structure when this field contains an unknown version number! sequencenumber UWORD Used to identify which Root block was written last in case the sequencenumber on both Root blocks don't match. datecreated ULONG Creation date of this volume. This is the date when the disk was last formatted and will never be changed. bits UBYTE Various settings, see below. pad1 UBYTE Reserved, leave zero. pad2 UWORD Reserved, leave zero. reserved1 ULONG[2] Reserved, leave zero. firstbyteh ULONG High 32-bits of a 64-bit number. This is the first byte of our partition relative to the start of the disk. firstbyte ULONG Low 32-bits of a 64-bit number. lastbyteh ULONG High 32-bits of a 64-bit number. This is the last byte (exclusive) of our partition relative to the start of the disk. lastbyte ULONG Low 32-bits of a 64-bit number. totalblocks ULONG The total number of blocks this partition consists of. blocksize ULONG The size of a block of this partition. reserved2 ULONG[2] Reserved, leave zero. reserved3 ULONG[8] Reserved, leave zero. bitmapbase BLCK Block number of the start of the Bitmap. adminspacecontainer BLCK Block number of the first AdminSpaceContainer. rootobjectcontainer BLCK Block number of the ObjectContainer which contains the root of the disk (this is where the volume name is stored). extentbnoderoot BLCK Block number of the root of the Extent B-Tree. reserved4 ULONG[4] Reserved, leave zero.

struct fsRootBlock {
  struct fsBlockHeader bheader;
  UWORD version;
  UWORD sequencenumber;
  ULONG datecreated;
  UBYTE bits;
  UBYTE pad1;
  UWORD pad2;
  ULONG reserved1[2];
  ULONG firstbyteh;
  ULONG firstbyte;
  ULONG lastbyteh;
  ULONG lastbyte;
  BLCK  totalblocks;
  ULONG blocksize;
  ULONG reserved2[2];
  ULONG reserved3[8];
  BLCK  bitmapbase;
  BLCK  adminspacecontainer;
  BLCK  rootobjectcontainer;
  BLCK  extentbnoderoot;
  ULONG reserved4[4];
};

AdminSpaceContainers are used to store the location and bitmap of each administration space. The AdminSpaceContainers are located in a double linked list and they contain an array of fsAdminSpace structures. There is one fsAdminSpace structure for every administration space on disk.

Field Type Description bheader struct fsBlockHeader Standard block header. next BLCK The next AdminSpaceContainer, or zero if it is the last in the chain. previous BLCK The previous AdminSpaceContainer, or zero if it is the first AdminSpaceContainer. bits UBYTE The number of bits in each in the bits ULONG in the fsAdminSpace structure. pad1 UBYTE Reserved, leave zero. pad2 UWORD Reserved, leave zero. adminspace struct fsAdminSpace An array of fsAdminSpace structures. The size of the array is determined by the current blocksize.

struct fsAdminSpaceContainer {
  struct fsBlockHeader bheader;
  BLCK next;
  BLCK previous;
  UBYTE bits;
  UBYTE pad1;
  UWORD pad2;
  struct fsAdminSpace adminspace[0];
};

Field Type Description space BLCK The first block of an administration space. bits ULONG A small bitmap which is used to determine which blocks in an administration space are already in use. The number of bits in this bitmap is determined by the bits field in the AdminSpaceContainer.

struct fsAdminSpace {
  BLCK  space;
  ULONG bits;
};

The fsBitmap structure is used for Bitmap blocks. A bitmap block is used to keep track of which space is in use and which isn't for a particular area of a disk. All bitmap blocks together keep track of the free space for an entire disk. The location of the first bitmap block is known and all other bitmap blocks are stored in order after the first one.

Field Type Description bheader struct fsBlockHeader Standard block header. bitmap ULONG An array of ULONG's. These hold the actual information on which blocks are in use and which aren't.

struct fsBitmap {
    struct fsBlockHeader bheader;
    ULONG bitmap[0];
};

Each bit in a bitmap block (except for the block header) represents a single block. If the bit is set than the block is free, and if the bit is clear then it is full. The first ULONG in the bitmap area of the first bitmap block represents blocks 0 through 31 on the disk. Bit 31 of this ULONG is block 0, 30 is block 1, and so on. Bit 0 of the first ULONG represents block 31.

Below is a table to clarify how bitmaps work even further. The first column is the bitmap block number, the second column is the number of the ULONG in the bitmap array. The third column is the bit number in this ULONG, and the last column is the block which this specific bit, in this specific bitmap block represents.

We'll assume here that a bitmap block has room for 120 ULONG's (meaning there is room for storing 32 * 120 bits).

Bitmap block	ULONG number	Bit number	Block represented
1 (first)	0	31	0
1	0	30	1
...	...	...	...
1	0	1	30
1	0	0	31
1	1	31	32
...	...	...	...
1	2	31	64
1	2	30	65
...	...	...	...
1	119	0	3839
2	0	31	3840
2	0	30	3841
...	...	...	...

The last bitmap block doesn't need to be completely used. The unused bits (which belong to blocks which do not exist) all have to be clear, to indicate that these blocks are in use.

The fsObjectContainer structure is used to hold a variable number of fsObjects structures (Objects) which have the same parent directory. Each ObjectContainer must contain at least one Object. If there is space in the ObjectContainer not used by the variable number of Objects then that space is zero filled. Objects always start at 2-byte boundaries, which means sometimes a padding byte is inserted between two Objects.

Field Type Description bheader struct fsBlockHeader Standard block header. parent NODE The node number of the parent Object, or 0 if this object has no parent (which is only the case for the Root directory). next BLCK The next ObjectContainer belonging to this directory, or zero if it is the last in the chain. previous BLCK The previous ObjectContainer belonging to this directory, or zero if it is the first ObjectContainer in this directory. object struct fsObject A variable number of fsObject structures. The number of structures depends on the individual sizes of each fsObject structure and the blocksize. These structures are located directly after each other with at most 1 byte of padding between them to get the structures aligned on a 2 byte boundary.

struct fsObjectContainer {
    struct fsBlockHeader bheader;
    NODE parent;
    BLCK next;
    BLCK previous;
    struct fsObject object[0];
}; 

fsHashTable is the structure of a HashTable block. It functions much like the hash table found in FFS user directory blocks, except that it is stored in a separate block. This block contains a number of hash-chains (about 120 for a 512 byte block). Each hash-chain is a chain of Nodes. Each Node has a pointer to an Object and a pointer to the next entry in the hash-chain. Using such a hash-chain you can locate an object quickly by only knowing its name.

Field Type Description bheader struct fsBlockHeader Standard block header. parent NODE The node number of the directory Object this HashTable block belongs to. hashentry NODE An array of Nodes. Each Node represents the start of a hash-chain (singly linked). A hash-value is calculated using the name of a file or directory, and this value determines in which chain the Object is linked. If there are no entries in a hash-chain then the hashentry value is zero.

struct fsHashTable {
    struct fsBlockHeader bheader;
    NODE parent;
    NODE hashentry[0];
};

To calculate the hash-value using a name of an Object as input use these routines:

UWORD calchash(UBYTE *name) {
    UWORD hash=0;
    /* Calculates a hash value over the passed in string.
       The end of the string can be either a NUL byte or a
       slash. The hash function is the same as the one
       used in FastFileSystem set to international mode. */
    while(name[hash]!=0 && name[hash]!='/') {
        hash++;
    }
    while(*name!=0 && *name!='/') {
        hash=hash*13+upperchar(*name++);
    }

    return((UWORD)(hash % (UWORD)((blocksize-sizeof(struct fsHashTable))>>2)));
}
UBYTE upperchar(UBYTE c) {
    if((c>=224 && c<=254 && c!=247) || (c>='a' && c<='z')) {
        c-=32;
    }
    return(c);
}

The BNodeContainer is used to store B-Trees. Currently only one B-Tree is in use by this filesystem and it is used to store the location of file data. The fsBNodeContainer structure contains two other structures. The fsBlockHeader structure and the BTreeContainer structure.

Field Type Description bheader struct fsBlockHeader Standard block header. btc struct BTreeContainer Contains information about the B-Tree and its nodes contained in this block.

struct fsBNodeContainer {
    struct fsBlockHeader bheader;
    struct BTreeContainer btc;
}; 


First try and locate the Root block. It should start with "ROOT". SFS has two of these, one at the start of the partition and one at the end. One of the fields contains the block size, which will be the size of all important SFS blocks.

The root block has the root object container, which contains information about files and directories in the root directory. The object containers basically hold one or more smaller structures that represent files and directories. Scanning them all should give you a list of files and directories.

The root block also has the root of the Extent B-Tree. This is a standard B-Tree structure (not a binary tree) that is used commonly in all kinds of system, you can read about how they work on Wikipedia if needed. The B-Tree holds the information about *where* all the data is located for your files.

To recover your files, I'd do this:

  • Find one of the root blocks, if not present, then figure out the block size your disk was using, and scan every block in turn to see if it

looks like an ObjectContainer (check the fsBlockHeader's ID, check if the ownblock number is equal to the block you are currently scanning, and check its checksum). So if you currently have block 12, and you see a block with the correct id, and ownblock = 12 and its checksum is good, then that's probably a valid ObjectContainer.

  • With all the ObjectContainers found, you can extract filenames and directory names from these, but also the number of their first data

block (in the field data) and the file size. For small files (less than blocksize) this data block will be enough to recover the data. For larger files, you might be lucky and all the remaining blocks are found after the first one (if the file was defragmented). You can't be sure of that though so...

  • For larger files, you need to find all the BNodeContainers. You could scan these in the same way you found all the ObjectContainers (look for

blocks with the correct id, ownblock number and checksum).

  • With all the BNodeContainers found, you can try looking up the first data block of a file in the B-Tree structure. This is a bit complicated

-- the B-Tree consists of non-leaf nodes (blocks that only contain pointers to other B-Tree blocks), the isLeaf flag indicates this. Or it can be a B-Tree leaf block. The leaf blocks contain extra information per entry (see https://hjohn.home.xs4all.nl/SFS/extents.htm)

struct fsExtentBNode {
     ULONG key;
     ULONG next;
     ULONG prev;
     UWORD blocks;
};

The key should be a block of a file (the first of a range), that is 1 to 65535 block long (depending the "blocks" field). If the file is split up into more parts, then "next" will contain block number of the next range of blocks. You need to look this up again in the B-Tree structure to find out how large it is.

You can for the most part ignore the other structures (bitmap, admin containers). The fsObjects and B-tree containers is what you'll need to recover the data.


Resources edit

rom/storage/mmakefile.src 
rom/storage/storage.conf 
rom/storage/storage_device.c 
rom/storage/storage_ids.c 
rom/storage/storage_init.c 
rom/storage/storage_intern.h 
rom/storage/storage_mount.c 
rom/storage/storage_unit.c
rom/storage/includes/device.h 
rom/storage/includes/unit.h 
rom/storage/includes/volume.h 
rom/storage/storage_intern.h 

Debugging Code edit

Please use the AROS Bug Tracker if any issues are found.


GRUB Command line list

sysdebug  
usbdebug - allows to see Poseidon's log in debug output


How do I get debugging out of InitResident ? If running i386 hosted on linux sysdebug=initresident on command line. This way you can enable any of listed flags. sysdebug=all stands for "everything"


Have an executable (crosscompiled C++ code) which has 6 MB size on disk, but after loading it in memory, 250 MB RAM is taken. Any software that would split AROS executable into ELF part which would show actual size values?

readelf -S executable

it will show you all sections in elf file, including sizes and requested alignment.

objdump -h filename

That's will give you a quick overview of the sections and sizes. Ignore all the .debug.* sections. Would hazard a guess that you have a large .bss section. That's pretty common in C++.

Next step:

nm—size-sort filename | grep ' [bB] '

The last few will be your biggest consumers. Would suggest -C to demangle the symbols... ;)


Suggest profiling the program (just use some printf's in the main loop for time spent in each part), it usually is quite easy to spot slow parts in games or apps.

If someone has '#define IPTR ULONG' somewhere. To see where that define is, redefine IPTR in the source code that fails, just above the line that fails, and the preprocessor will tell you where it was defined first.

How to setup gdb with AROS/hosted edit

Download AROS sources (AROS-xxxxxxxx-source.tar.bz2, where xxxxxxxx is the current date) and AROS contrib sources (AROS-xxxxxxxx-contrib-source) from aros.sourceforge.net/download.php

Untar-bzip2 and cd to the unpacked archive directory.

> tar -xvjf AROS-xxxxxxxx-source.tar.bz2
> cd AROS-xxxxxxxx-source

Check the link to "contrib" (contrib-source) inside directory, e.g. correct like this:

> rm contrib
> ln -s ../AROS-xxxxxxxx-contrib-source.tar.bz2 contrib

Make sure you have the correct locale setting, otherwise compilation will fail at some point. See here (or link below) for more on that. You might have to enter this:

> export LANG="en_US.ISO-8859-1"

Now configure for a debug build - see "./configure --help" for more - here are two examples:

> ./configure—enable-debug=stack,modules,symbols

> ./configure—enable-debug=all

You may "make" now, or choose a separate directory for your build (e.g. for easy removal), for example if compiling for i386 architecture you could create a directory like this:

> mkdir linux-i386
> cd linux-i386
> ../AROS/configure—enable-debug=stack,symbols,modules

When done configuring you're ready to go:

> make

Building AROS takes some time - minutes on fast machines (e.g. 2.5 GHz quadcore), up to hours on slower machines. The result will be AROS Linux hosted with gdb debugging enabled.

See aros.org documentation for more on compiling AROS, including more --enable-debug options.


When finished, enter bin/linux-i386/AROS directory (replace "linux-i386" with your compilation target platform, e.g. linux-x86_64, etc.) inside the unpacked archive directory. This directory contains the required .gdbinit file for properly running AROS inside gdb.

> cd bin/linux-i386/AROS

Run AROS (here: with 128MB of memory) from gdb:

> gdb—args boot/aros-unix -m 128

or

> gdb—args boot/arosboot -m 128
(gdb) r

Watch the shell output - in case AROS complains about "LoadKeyCode2RawKeyTable: Loading "DEVS:Keymaps/X11/keycode2rawkey.table" failed!" you should also see some instructions on how to create a keymap table. (see link above "more on compiling", too.) Quit gdb, and try default keymap table:

(gdb) q
The program is running.  Quit anyway (and kill it)? (y or n) y
> cd ../../..
> make default-x11keymaptable

Re-run AROS, as described above. Try e.g. RAros (= right windows key) + W to open a shell. If this doesn't work you have to create a keymap table yourself, quit gdb again, and make a new keytable:

> make change-x11keymaptable

A window will open. Watch the window's title bar, and follow the instructions.

When done, re-run AROS. RAros + W should now open a shell.

Next, compile your program with gdb support.


When you start GDB is there a warning which says

  warning: File "<whatever>/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to ...

If so start gdb with "-ix .gdbinit"


Summary - In short:

* build AROS with debugging support (i.e. ./configure --enable-debug=all)
* build your application with debugging support (i.e. option -g)
* run AROS in the GNU debugger (you may use the GUI frontend "ddd" which simplifies usage a bit)
* start your application
* use the commands "findaddr" and "add-symbol-file" as written in the debugging manual
* if the debugger doesn't find the source code of your application use the "dir" command of the debugger. 

How to use gdb edit

In AROS open a shell, then (in host shell) use CTRL-Z to go into gdb. Use "b Exec_CreatePool" (one of the functions used early on by startup code in programs) to add a breakpoint, then "cont" and gdb will interrupt somewhere early during startup of "program". Use "bt" to show backtrace and "loadseg" for "??" entries. One of them will be for "program". After that you can use "disassemble program".

One thing you need to make sure is that .gdbinit you have in your build directory is the same as in source tree. It has been modified some time ago, but the build system does not refresh it - you need to copy it manually

To recap, please read our debugging manual:


To detect segfaulting when loading, try...

./configure—enable-debug—with-optimization="-O2"

Because crash or no crash may depend on optimization. For newer compilers maybe this helps...

--with-optimization=-"-O2 -fno-strict-aliasing"

One way to make crashes less random (more easily reproducible) is to activate the munging of free memory in rom/exec/freemem.c which is normally commented out:

Index: freemem.c
===================================================================
--- freemem.c   (revision 34289)
+++ freemem.c   (working copy)
@@ -154,11 +154,12 @@
         * created with their TCB placed in the tc_MemEntry list. The workaround
         * is to avoid munging when FreeMem() is called with task switching disabled.
         */
+
        /* DOH! it doesn't work even this way. What's wrong???
-        *
-        * if ((SysBase->TDNestCnt < 0) && (SysBase->IDNestCnt < 0))
-        *      MUNGE_BLOCK(memoryBlock, MEMFILL_FREE, byteSize);
         */
+
+       if ((SysBase->TDNestCnt < 0) && (SysBase->IDNestCnt < 0))
+           MUNGE_BLOCK(memoryBlock, MEMFILL_FREE, byteSize);

     }

Mungwall can be turned on at runtime. Currently this works in all hosted versions. Just specify "mungwall" on kernel command line and it works. It can work on native too. In order to enable it you need to parse kernel command line, and if "mungwall" is present, set EXECF_MungWall bit in IntExecBase.IntFlags.

This needs to be done before the first AllocMem() for obvious reasons. And never reset back this flag! If you change it on a working system, you are doomed.

Hosted ports do the processing in rom/exec/prepareexecbase.c --enable-debug=mungwall option in configure still works but is going obsolete. A kludge in rom/exec/allocmem.c is responsible for this and it needs to be removed when the transition is done.

BTW, on i386-pc port it can be activated by "mungwall" argument on command line, you don't need to rebuild AROS. New mungwall affects not only AllocMem()/FreeMem(), but also pools. I also tested it with AllocAbs(), seems to work correctly.

Runtime mungwall works on:

  • pc-i386
  • pc-x86_64
  • linux-i386
  • linux-x86_64
  • darwin-x86
  • linux-ppc

Works on all hosted ports, if the port itself is working.

  • amiga-m68k
  • Not on sam440-ppc and efika-chrp-ppc, even if they would be able to be built at moment. Does not work on (for now, need NVRAM support)

When starting my freshly rebuilt i386-linux-aros which was compiled with full debugging support I get sometimes the error "Program exited with code 0377". Add the following to your .gdbinit:

set follow-fork-mode child

Here are some of the custom AROS gdb functions (defined in ".gdbinit" file) to resolve "in ?? ()" entries in backtrace:

#0 0xb7ffd424 in __kernel_vsyscall ()
#1 0xb7e2a657 in sigsuspend () from /lib/libc.so.6
#2 0xb7c63900 in ?? ()
#3 0xb7c640e3 in ?? ()
#4 0xb7c641e0 in ?? ()

You can use

loadseg 0xb7c63900
loadframe 2

or

loadbt

and some others. Use "help " for a little help text. If the commands do not work try "loadkick" first.


Use "thistask", "taskready", "taskwait" to get list of AROS tasks. "bttask " shows backtrace of a task which is in ready or in wait queue and "loadseg" to resolve "??" entries in it's backtrace ("loadframe" would not work as it assume current running task).

Native debugging tools for AROS edit

to enable debugging at boot time entering the GRUB menu editing line (E key) and adding "debug=memory" to your boot line, then press Ctrl+X to complete booting.


SYS:Tools/Debug/Bifteck

Open a shell and enter the line below to run Biftek and grab the debug messages collected in RAM into a text file.

tools/debug/bifteck > ram:debug.txt

and certainly does not open a window. It is a shell tool and only dumps data located from the debug location. It is therefore important to 'catch' that debug data as soon as possible (before it gets overridden). You should invoke bifteck at the first opportunity before doing anything else. You can use the TO option to store bifteck output to a file or you can pipe it manually to a file.


SYS:Tools/Debug/Sashimi - displays error messages

One suggestion is to do a bug() debugging. Each time bug() is executed it will be output on sashimi. You include <aros/debug.h> and place bug("something\n"); in your source code at location though which control passes.

To get the output - open an aros shell

SYS:Tools/Debug/sashimi > RAM:out.txt

Ctrl C to end the output to the RAM Disk.

  1. open shell, and type
  2. ram: (to switch to ram drive)
  3. System:Tools/Debug/Sashimi > mylogfile.txt
  4. open AHI prefs using wanderer (or use another opened shell)
  5. play test sound
  6. close AHI prefs
  7. shell still open with Sashimi running: press ctrl-c to break Sashimi and return to prompt.
  8. in shell: copy mylogfile.txt System: (or to your required location)


SYS:Utilities/Snoopy - monitors OS function calls, run "Sashimi" to see Snoopy's output


SYS:Tools/WiMP - the Window (and Screens) Manipulation Program

You can use the -E option of gcc to find out how preprocessor macros are expanded.

Errors edit

crash in strcasecmp usually means that one of its arguments is NULL.

empty space between these two names, prossibly some invisible character

Old Amiga Guru Codes

If the crash is in intuition. Sometimes, if it relates to text, a null pointer sets it off. an uninitialised pointer can have any address (this is a common fault).


Compiling on 64bit, Many old code would not properly typecast when doing pointer-integer conversions and thus at least throw a warning. This can easily be located and fixed.

Portable code

  • Use texteditor or some tool to replace all "ULONG" with "IPTR" and "LONG" with "SIPTR" in the sources.
  • Fix (change IPTR/SIPTR back to ULONG/LONG) the few places which really rely on ULONG/LONG being exactly 32 bit. That's for things like pixel (ARGB) buffers, structs written/read to disk, colormaps, but probably not much else.

Then again, many current compilers also throw a warning when you try to assign a pointer value to an integer and the integer is possibly too small. This happens under .NET for example when a 64 bit pointer is assigned to something like an ULONG - so exactly the case which you described.


Linux edit

/* 1. Header for your name,date,purpose of program.
2. Pre-processor directives. This will include the #includes for files you want to add. 
3. Includes for function prototypes if necessary.
4. Main()
Create Pointers for Libraries and any Window you want to open.
5. Open necessary libraries.
6. Check if open exit program if fail.
7. Open a window exit program if fail.
8. Add your program
9. Close Window
10 Close Libraries.
11 End Program. */

/* standard os included headers <.h> */
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <utility/utility.h>
#include <intuition/intuition.h>

/* define as unresolved external references (proto/xxx.h) and compiler will link to auto(matically) open library */ 
#include <proto/arossupport.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/cybergraphics.h>
#include <proto/datatypes.h>
#include <proto/icon.h>

#include <workbench/workbench.h>
#include <workbench/icon.h>

#include <datatypes/pictureclass.h>

#include <proto/muimaster.h>
#include <libraries/mui.h>

#include proto/bsdsocket.h

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* my own headers ".h" */

#define CTRL_C      (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
#define  isDir(fib) ((fib)->fib_DirEntryType >= 0)

#define ARG_TEMPLATE    "FILE/A,ALL/S,QUIET/S,W=WIDTH/N,H=HEIGHT/N,M=METHOD,DEFTOOL"

int main(void)
{


	return retval;
} /* main */

If you used c++, there is not yet c++ support in our shared library system. The easiest way to create / compile a shared library would be to use the AROS build system but the libraries can be created manually. You have to create a ROMTAG structure and some header files.

A shared library is built with the %build_module macro with a line like this:

%build_module mmake=MetaTarget modname=mylib modtype=library files=SourceFiles 

This macro can build different AROS module types, like devices, Zune classes, HIDDs, etc.

##begin config
version 1.0
##end config

##begin functionlist
void func1(LONG a, LONG b)
int func2(char *s, ULONG a)
##end functionlist

There is more here

Alternatively,

#ifndef LIB_H
#define LIB_H

#define __NOLIBBASE__

#include <exec/libraries.h>
#include <exec/semaphores.h>
#include <dos/dos.h>

#ifdef __AROS__
//#include <aros/debug.h>
#define reg(x)
#define __saveds
#endif

#define USESYSBASE struct ExecBase *SysBase = Base->My_SysBase;

struct MyTestBase
{
  struct Library   My_Test_Lib;
	struct ExecBase *My_SysBase;
	APTR             My_SegList;
  int              testint;
};

#endif
/*--------------------------------------------------------------------------*/
/* Resident header written for mytest.library */
/*--------------------------------------------------------------------------*/

#define __NOLIBBASE__

#define VERSION         1
#define REVISION        0

#define LIBHEADNAME     mytest
#define LIBHEADNAMESTR "mytest"
#define COMPDATE        "04.10.2015"
#define VERS            "1.0"

#define LIBBASETYPE 	struct MyTestBase
#define LIBBASETYPEPTR  LIBBASETYPE *

#include <aros/debug.h>
#include <exec/exec.h>
#include <proto/exec.h>
#include <exec/resident.h>
#include <exec/nodes.h>
#include <exec/libraries.h>
#include <aros/symbolsets.h>
#include "lib.h"

const UBYTE lib_name[] = LIBHEADNAMESTR ".library";

const UBYTE lib_id[] = "$VER: " LIBHEADNAMESTR ".library " VERS " (" COMPDATE ") by ALB42\n";

extern const APTR FuncTable[];

AROS_UFP3 (LIBBASETYPEPTR, InitLib,
    AROS_UFPA(LIBBASETYPEPTR, Base, D0),
    AROS_UFPA(BPTR, seglist, A0),
    AROS_UFPA(struct ExecBase *, sysbase, A6)
);

static struct LibInitStruct
{
    IPTR                   LibSize;
    const APTR             *FuncTable;
    const struct DataTable *DataTable;
    APTR                    InitFunc;
}
const LibInitStruct =
{
    sizeof(LIBBASETYPE),
    FuncTable,
    NULL,
    (APTR)InitLib
};

const struct Resident romtag =
{
  RTC_MATCHWORD,              /* match word */
  (APTR)&romtag,              /* back pointer */
  (APTR)(&romtag + 1),        /* skip pointer */
  RTF_AUTOINIT | RTF_EXTENDED,/* flags */
  VERSION,                    /* version */
  NT_LIBRARY,                 /* type of module */
  0,                          /* init priority */
  (STRPTR)lib_name,           /* module name */
  (STRPTR)lib_id + 6,
  (APTR)&LibInitStruct,
  REVISION, NULL
};

AROS_UFH3 (LIBBASETYPEPTR, InitLib,
    AROS_UFHA(LIBBASETYPEPTR, Base, D0),
    AROS_UFHA(BPTR, seglist, A0),
    AROS_UFHA(struct ExecBase *, sysbase, A6)
    )
{
    AROS_USERFUNC_INIT
    
    Base->My_SegList = seglist;
    Base->My_SysBase = (APTR)sysbase;
    Base->testint = 0;
    
    USESYSBASE
    bug("InitLib\n");
    
    if (!set_open_libraries())
    {
      set_close_libraries();
      return NULL;
    }
    
    return Base;
    
    AROS_USERFUNC_EXIT
}

AROS_LH1(LIBBASETYPEPTR, LibOpen,
    AROS_LHA (ULONG, version, D0),
    LIBBASETYPEPTR, Base, 1, LIBHEADNAME
    )
{
    AROS_LIBFUNC_INIT
    
    USESYSBASE
    bug("LibOpen\n");

    (void)version;
    
    Base->My_Test_Lib.lib_OpenCnt++;
    return Base;

    AROS_LIBFUNC_EXIT
    
}

__saveds APTR LibExpungeInternal(LIBBASETYPE *Base reg(a6))
{
  USESYSBASE
  APTR seglist;
  bug("LibExpungeInternal\n");

  if (Base->My_Test_Lib.lib_OpenCnt)
  {
    return 0;
  }

  seglist = Base->My_SegList;

  Forbid();
  Remove((struct Node*)Base);
  Permit();
  FreeMem((APTR)Base - Base->My_Test_Lib.lib_NegSize, (LONG)Base->My_Test_Lib.lib_PosSize +
    (LONG)Base->My_Test_Lib.lib_NegSize);
  
  set_close_libraries();
  return seglist;
}

AROS_LH0(BPTR, LibClose,
    LIBBASETYPEPTR, Base, 2, LIBHEADNAME
    )
{
    AROS_LIBFUNC_INIT
    USESYSBASE
    bug("LibClose\n");

    if (!(--Base->My_Test_Lib.lib_OpenCnt))
    {
      return LibExpungeInternal(Base);          
    }
    return 0;
	
    AROS_LIBFUNC_EXIT
}

AROS_LH1(BPTR, LibExpunge,
    AROS_LHA(LIBBASETYPEPTR, Base, D0),
    struct ExecBase *, sysBase, 3, LIBHEADNAME
    )
{
    AROS_LIBFUNC_INIT

    (void)sysBase;
    
    USESYSBASE
    bug("LibExpunge\n");

    return LibExpungeInternal(Base);
	
    AROS_LIBFUNC_EXIT
}

AROS_LH0(LIBBASETYPEPTR, LibReserved,
    LIBBASETYPEPTR, Base, 4, LIBHEADNAME
    )
{
    AROS_LIBFUNC_INIT
    USESYSBASE
    bug("LibReserved\n");

    return 0;
    //return (APTR)LibReserved();
    
    AROS_LIBFUNC_EXIT
}


// Space for your own functions
// do not forget to update the FuncTable as well

AROS_LH1(int, TestFunction,
    AROS_LHA(int, TestValue, D0),
    LIBBASETYPEPTR, Base, 5, LIBHEADNAME
    )
{
    AROS_LIBFUNC_INIT
    USESYSBASE
    bug("TestFunction\n");

    Base->testint = TestValue + Base->testint;
    
    return Base->testint;
    
    AROS_LIBFUNC_EXIT
}

// Functable -> Table of all functions in the Library, in right order - important!

const APTR FuncTable[] = 
{
    &AROS_SLIB_ENTRY(LibOpen,LIBHEADNAME,1),
    &AROS_SLIB_ENTRY(LibClose,LIBHEADNAME,2),
    &AROS_SLIB_ENTRY(LibExpunge,LIBHEADNAME,3),
    &AROS_SLIB_ENTRY(LibReserved,LIBHEADNAME,4),
    &AROS_SLIB_ENTRY(TestFunction,LIBHEADNAME,5),
    (void *)-1
};

// AutoInit stuff
void *__PROGRAM_ENTRIES__symbol_set_handler_missing;
void *__LIBS__symbol_set_handler_missing;
// end of AutoInitStuff

Makefile

VPATH = 
CFLAGS = -O2 -g -fomit-frame-pointer -W -Wall -Wno-parentheses
CC = i386-aros-gcc
LD = i386-aros-gcc
LDFLAGS = -nostartfiles -Wl,-Map -Xlinker linkermap
LIBS = -lautoinit -llibinit
STRIP = i386-aros-strip --strip-unneeded --remove-section .comment

OBJS = lib_header.o 

all: mytest.library

mytest.library: $(OBJS)
	$(LD) $(LDFLAGS) $^ $(LIBS) -o $@

lib_header.o: lib_header.c lib.h

clean:
	rm -f *.o *.library *.ppu testlibrary linkermap


Porting UNIX library to AROS - dealing with static variables which would make it easy to port such libraries to AROS, keeping the benefits of sharing them on disk, but losing the benefit of actually sharing them in memory.

Our problem arises by the fact we want to share the actual code (the .text section of the library) and constant data, but we need to have per-task .bss and .data sections. If we get rid of our intention to share the .text and .rodata sections, things get quite easy: just load and relocate the library whenever it's open, by whoever it's open. It's like statically linking the library into the executable, except that the final linking is done at runtime.

In the V0 branch, in workbench/hidds/hidd.nouveau was committed pcimock.hidd. This is a pci driver that allows mocking real PCI devices under linux-hosted. The main idea is to be able to run the real hardware driver under linux-hosted with as little changes as possible (some changes will always be needed though unless someone wants to write complete device simulator) so that driver's code paths can be executed and debugged using gdb. This was a very helpful capability when porting nouveau. Now it is externalized from nouveau.hidd and can be used by other people porting drivers. The pcimock.hidd can currently mock 4 different nvidia cards, 1 AGP bridge and also mock irq.hidd.

What's the difference between this driver and the pcilinux.hidd? I used that one to develop many different HW drivers for aros. As far as I understood the intention of pcilinux.hidd it is supposed to get access to real hardware that is running under linux. The pcimock.hidd goal is to mock the hardware. For example my dev box is a PCIE system, but I still would like to run the AGP codes paths in nouveau under linux-hosted to check if they don't seg fault. The other case would be to run codes paths for hardware that the developer does not have (Fermi cards in my case). In the case of pcimock.hidd, the AROS driver's code paths will execute as long as you add proper mocking (for example fill in PCI config area or values for registers in BARs). This is an advantage for ported drivers - the code should already work (since it worked on another system) but there might have been mistakes made during porting which can be detected easily with gdb.

In case you are writing your driver from scratch, pcilinux.hidd hidd will give you more advantage, since you can actually access the real hardware from linux-hosted.



Misc edit

APL, MPL, BSD, GPL and LGPL Licences edit

The majority of AROS sources in licensed under AROS Public License (APL) which (to a degree) protects us from someone taking AROS sources and not contributing improvements back (for example MorphOS took some AROS source and then contributed changes back)

It is written to allow the use of AROS code in other open source or commercial projects without exception whilst providing a mechanism so that improvements/additions can find their way back to the original source in one form or another.

There are "3rd" party applications used by AROS that do not fall under this license, which are an extra "Contrib" download for convenience.

Anyone can port GPL-ed network and sound drivers as AROSTCP and AHI are GPLed. Direct using (porting) GPL-ed code in other parts of AROS (gfx, sata, usb) is not possible because AROS license is not compatible with GPL. You need to utilize permissive licensed code like BSD or MIT/X11.


BSD and MPL license are the closest to APL.

APL however is not so compatible with LGPL/GPL.

LGPL case - you cannot statically combine APL code with LGPL. You can, however thank to LGPL being "lesser" restrictive, use LGPL dynamically loaded libraries in APL codes.

GPL case - you cannot combine APL code with GPL in any way if there is no explicit clause by GPLed code authors allowing that. If you do combine APL with GPL in "bad" ways described above - you have a problem (you violate GPL). This problem might result in everything in AROS becoming GPL or everything running or AROS becoming GPL (here I'm not sure really). The other scenario is that you are not allowed to legally distribute such code at all. To be honest I have grasped how to violate GPL, but I'm still no exactly sure what happens when you violate it (but I'm sure it's not anything nice)

GPL software can run on top of non-GPL "system components" (see system components exception of GPL), but the other way around (non-GPL using GPL) leads to problems. This means applications like scout, or Quake III are ok (in the majority of cases).

Theres no reason GPL drivers cannot be ported - but they cant be in AROS's ROM (requires linking APL code with GPL), nor can AROS depend on them (e.g. they must use existing apis). If they are launched (dynamically linked) by a user action that is allowed. It is also allowed to distribute such binaries together for convenience.

GPL is not about statical or dynamic linking but is about executing process and function calls.


These components - SFS, isapnp, Zune texteditor, AHi, network drivers, freetype, openuirl, BHFormat, Edit and (" dynamically loaded libraries") are LGPL, not GPL. Mesa/Nouveau stuff is MIT. Some user tools are GPL though.

AROS (system)

  • system components (libraries/classes/devices/etc) cannot be GPL as they would propagate GPL to complete system as well as GPL is not compatible with MPL from which APL is based
  • system components can be LGPL v2 or a permissive license (MIT/BSD)
  • system applications can be anything you like (but still I would prefer APL or permissive so the code can be reused if needed)

Contrib:

  • no rules - contrib does not impact AROS system since nothing in AROS system depends on contrib.

About stealing code: The chances of this happening is exactly the same whether we are APL or GPL. If any closed-source option wanted to do it, there is no one that can validate otherwise. MorphOS has used some AROS codes, but contributed changes back.

The rationale behind APL is that while it guarantees that the original developer will get the improvements back (to a certain degree - file based), the person who uses the codes does not have to open his original codes. BSD does not guarantee that the original developer gets improvements. GPL requires the person using the codes to open his codes as well.

The copyright holders needs to stay - we just need information from them that the codes are available under APL (for example a checked-in file like in case of Poseidon). We don't do transfer of copyrights.

Ultimately what can and cannot be done is up to the author(s) - not the licence.

AROS source code tree edit


Found this interesting (non-GPL) licensing 'anomaly' - to keep in mind for distributors.

Programs that lose their license if sold ("non-profit only" licensed):

 contrib/aminet/comm/term/TinyTerminal
 contrib/aminet/dev/basic/bwBASIC
 contrib/aminet/text/edit/xdme
 contrib/fish/aroach
 contrib/fish/lotto
 contrib/fish/shuffle
 contrib/fish/touch
 + cdvdfs.


Here is a list of all the GPL/GPLv2/GPLv3 licenses fossology found, what have explicit licenses in their comments.


excluded LGPL, BSD/GPL dual licensed and programs (such as Prefs/Edit and BHFormat)
AROS/rom/dbus/include/  AFL_v2.1 ,GPL_v2+  (supposedly AFL < 3 is GPL incompatible) 
AROS/workbench/classes/zune/betterstring/include/  GPL_v2+
AROS/workbench/classes/zune/texteditor/include/  GPL_v2+
AROS/workbench/classes/datatypes/gemimage/ GPL_v2+ GPL
AROS/workbench/classes/datatypes/degas/  GPL_v2+
AROS/workbench/libs/openurl/README: GPL
AROS/workbench/network/smbfs/documentation/  GPL_v2
AROS/workbench/network/smbfs/source_code/  GPL_v2+
AROS/workbench/network/stacks/AROSTCP/bsdsocket/kern/  GPL_v2
AROS/workbench/network/stacks/AROSTCP/bsdsocket/mmakefile.src conf.h  GPL_v2
AROS/workbench/network/stacks/AROSTCP/bsdsocket/sys/  CMU ,GPL_v2
AROS/workbench/network/stacks/AROSTCP/bsdsocket/net/  GPL_v2
AROS/workbench/network/stacks/AROSTCP/bsdsocket/api/  GPL_v2
AROS/workbench/network/stacks/AROSTCP/bsdsocket/conf/conf.h: GPL_v2
AROS/workbench/network/stacks/AROSTCP/netinclude/net/radix.h: CMU ,GPL_v2
AROS/workbench/devs/AHI/AHI/  GPL_v2+
AROS/workbench/devs/AHI/AddAudioModes/ GPL_v2+  AROS/workbench/devs/AHI/AddAudioModes/COPYING: GPL 
AROS/workbench/devs/AHI/Docs/texinfo.tex: GPL_v2+
AROS/workbench/devs/AHI/COPYING: GPL
AROS/workbench/devs/AHI/Drivers/EMU10kx/  GPL_v2+
AROS/workbench/devs/AHI/AHI-Handler/  GPL_v2+
AROS/workbench/devs/networks/rtl8029/  GPL   GPL_v2+
AROS/workbench/devs/networks/pcnet32/  GPL   GPL_v2+
AROS/workbench/devs/networks/ppp/LEGAL: GPL
AROS/workbench/devs/networks/atheros5000/  GPL_v2+
AROS/workbench/devs/networks/rhine/  GPL_v2+
AROS/workbench/devs/networks/nForce/  GPL_v2+  GPL
AROS/workbench/devs/networks/prism2/  GPL  GPL_v2+
AROS/workbench/devs/networks/fec/LEGAL: GPL
AROS/workbench/devs/networks/rtl8139/  GPL  GPL_v2+
AROS/workbench/devs/networks/etherlink3/  GPL  GPL_v2+
AROS/workbench/devs/networks/intelpro100/  GPL  GPL_v2+
AROS/workbench/devs/networks/rtl8169/  GPL   GPL_v2+
AROS/workbench/devs/networks/emac/   GPL   GPL_v2+
AROS/workbench/devs/networks/rtl8168/  GPL  GPL_v2+
AROS/workbench/devs/networks/realtek8180/   GPL_v2+
AROS/workbench/devs/networks/via-rhine/via-rhine.c: GPL_v2+
AROS/workbench/devs/networks/via-rhine/   GPL  GPL_v2+
AROS/workbench/devs/networks/e1000/  GPL_v2
AROS/workbench/devs/networks/sis900/  GPL   GPL_v2+

AHI: it has special provisions (COPYING.DRIVERS). The library is LGPL, preferences software is GPL and drivers can be anything without breaking GPL/LGPL.

Network stack: well, we are long overdue for a new, IPv6 enabled network stack anyway, anyone interested? ;) Seriously though it seems like the glue code is GPL and as all the drivers. However some of the drivers are our own code, so they could be relicensed to LGPL.

Same filter as the AROS trunk list. These should all be libraries or plugins - no programs.
contrib/regina/utsname.h: GPL_v2+

contrib/mui/classes/nlist/include/default-align.h: GPL_v2+
contrib/mui/classes/nlist/include/amiga-align.h: GPL_v2+

contrib/mui/classes/BWins/include/MUI/BWin_mcc.h: GPL
contrib/mui/classes/BWins/include/BWin_private_mcc.h: GPL
contrib/mui/classes/BWins/COPYING: GPL_v2
contrib/mui/classes/BWins/MCC_BWins.readme: GPL_v2

contrib/mui/classes/thebar/include/default-align.h: GPL_v2+
contrib/mui/classes/thebar/include/amiga-align.h: GPL_v2+

contrib/gfx/libs/wazp3d/LEGAL: GPL
contrib/gfx/libs/wazp3d/Wazp3D.readme: GPL
contrib/gfx/libs/wazp3d/Wazp3D-src/soft3d.c: GPL
contrib/gfx/libs/wazp3d/Wazp3D-src/soft3d_opengl.h: GPL
contrib/gfx/libs/wazp3d/Wazp3D-src/soft3d_opengl.c: GPL
contrib/gfx/libs/wazp3d/Wazp3D-src/Wazp3D.h: GPL
contrib/gfx/libs/wazp3d/Wazp3D-src/Wazp3D.c: GPL

contrib/libs/mpega/  GPL_v2+

http://www.evillabs.net/AROS/Audit-2012-03-14/AROS-contrib.txt

Types edit

On AROS following rules apply:

 
1. BYTE/UBYTE is 8bit, WORD/UWORD is 16bit, LONG/ULONG is 32bit, QUAD/UQUAD is 64bit, the types are comparable with stdint types (int8_t, int16_t, int32_t, int64_t)
2. IPTR/SIPTR are integer types large enough to fit pointer, that is sizeof(IPTR) = sizeof(APTR) = 4 on 32bit system, and = 8 on 64bit system
3. ti_Data in TagList is large enough to hold a IPTR/APTR type.
4. never store a pointer in integer of type LONG. It may work (if the pointer has upper 32bits clear), but does not have to. Compiler should warn you about that.
5. If you are unsure about point 4, allocate your memory with MEMF_31BIT flag set. But don't expect that AROS internals will do the same.

point 4 is actually important.


  • UBYTE/BYTE for 8bit
  • UWORD/WORD for 16bit
  • ULONG/LONG for 32bit
  • UQUAD/QUAD for 64bit
UBYTE    Unsigned 8 bit integer variable (byte).
BYTE     Signed 8 bit integer variable (byte).
UWORD    Unsigned 16 bit integer variable (word).
WORD     Signed 16 bit integer variable (word).
ULONG    Unsigned 32 bit integer variable (longword).
LONG     Signed 32 bit integer variable (longword).
FLOAT    32 bit IEEE floating point variable.
UQUAD    Unsigned 64 bit integer variable.
QUAD     Signed 64 bit integer variable.
DOUBLE   64bit IEEE floating point variable.
BOOL     Boolean variable, TRUE and FALSE are also defined in exec/types.h.
VOID     Void.

APTR     A generic pointer for multiple purposes - Arrays.
STRPTR   A pointer to a null-terminated string.
IPTR     Really important in AROS, the only way to declare a field that can contain both: an integer or a pointer.

if you want to write really portable app, you may be interested in standard datatypes defined in C99: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, intptr_t, uintptr_t. They are all defined in inttypes.h include file.

In exec/types.h the following short-cuts are typedef'd. They are used often in AROS, so you should nearly always include exec/types.h and soon only they will be removed from sys/_types.h include, all types are now defined in include files named aros/types/xxx.h.

(Preparation for C library split; sys/xxx.h include will only be available there when compiling with POSIX C library)


Compiler specific types, like int and long might change their size. In case of AROS, similar to linux, int remains 32 bit whereas long grows to 64 bits in size.

If you use Amiga-like data types, i.e. BYTE/UBYTE, WORD/UWORD, LONG/ULONG and QUAD/UQUAD or the C99 standard types (uint8_t and so on, see stdint.h include) then you should have less issues to solve than by using types without size guarantee.

Of course, all pointers grow to 64 bytes using 64bit cpu. Most of the code can be just recompiled and will work. In rare cases, where e.g. pointers are casted to integers, a special care must be taken. Especially in the cases, where pointer is casted to LONG/ULONG (this code will break on 64 bit AROS) e.g. '#define IPTR ULONG'.

With compiler delint patches which the majority of them are simple casting issues to make the compiler happy. Notice some of the changes involve introducing double casts. In very recent versions of GCC. Yes, the bulk of the double casts are for converting 32 bit addresses (ie from a 32 bit PCI DMA address register) to a 64 bit pointer. First cast is to IPTR (to expand to 64 bits, and prevent sign extension if the address is above 0x7FFFFFFF), and then to APTR.

ULONG != IPTR except on 32bit .. so if you need to store pointers make sure and use IPTR and not ULONG (which some old code does). For this reason things like Taglist elements are 64bit (since the tag data can be a pointer). If your passing items on the stack you should use the STACKED attribute to make sure they are correctly aligned (on 64bit all items on the stack are 64bit..)

There is more issues like using "== 0L" causes problems.

Endian edit

  • BE
  • LE

Use the macros from <endian.h> instead making a guess based upon architecture defines

#if _BYTE_ORDER == _BIG_ENDIAN

#elif _BYTE_ORDER == _LITTLE_ENDIAN

#else
+
#error <whatever.h> - Byte order for this architecture is unsupported! 


SVN and GIT edit

If you want to help develop AROS OS itself, you can

If you have SVN access (early 2015 introduced a new SVN server, create a new account at trac aros org) and/or have obtained the source AROS site - you can compile the current build tools/environment using:

> make development

and follow this procedure or Guide


https://trac.aros.org/trac#Developing

If you plan on contributing back changes, please post information about such changes first on this mailing list for more experience developers can validate whether they are correct.


Then there are the nightly build machines. They svn update before the build and run configure as one of the next steps. autoconf might be added to the nightly build scripts.

Our build relies on packages downloaded from Internet (SDL for example) - it always worked this way. The minimal requirement (when just building core AROS) is binutils and gcc. If you build contrib as well, you need many more packages to be downloaded.

https://gitorious.org/aros/aros/commits/crosstools-II

git://gitorious.org/aros/aros.git

Branch crosstools-II there is only one commit on top of ABI_V1

../../aros-src/AROS/configure --enable-ccache
--with-portssources=~/aros/Sources --target=pc-x86_64
--with-aros-toolchain-install=/home/weissms/media/data/aros/test/crosstools/pc-x86_64

and

../../aros-src/AROS/configure --enable-ccache
--with-portssources=~/aros/Sources --target=pc-i386
--with-aros-toolchain-install=/home/weissms/media/data/aros/test/crosstools/pc-i386

build OK.


More information: AROS Maintainer Docs

SDI Calls edit

Integrate the 'SDI'-headers to allow easier porting to all amiga-like platforms.

PUTCHARPROTO( PutTheChar, char c, struct SPrintfStream *s  )
{
 // REAL CODE
}

have "SDI_compiler.h" and "SDI_hook.h" included

its more organized like

#include SDI/SDI_hook.h

than

#include SDI_hook.h

option 1 --- i also use when back porting from amiga's..

#ifdef __AROS__
#include SDI/SDI_hook.h
#else
#include SDI_hook.h
#endif

also

you can add the -i include/sdi/ location if you do not want to add or edit any files.


Defining HOOKPROTO to IPTR name(struct IClass * cl, Object * obj, Msg msg); solved the problem

A MUI application most likely needs only the HOOKPROTOxxx SDI macros. They are compatible with AROS, only the attributes (hook, object attribute) must be given in the right order. examine compiler/include/aros/symbolsets.h (AROS_LIBREQ)

compiling mui stuff for aros setting -std=gnu99 is necessary (i have had -std=c99 most of the time).

Locale with Flexcat edit

Most languages have a locale, but not every app is localized, the only thing needed is to translate the "catalog" files. It is a case of locating the correct catalog and saving the translated version.

For every app that lacks of your language catalog and is localized anyway, you should find (in the sources) files related to locale:

  • file.cd = catalog descriptor, contains base msg, with internal language (usually english)
  • language.ct = catalog translation, contains every translated msg, indexed as in the file.cd.

Compare with other localized apps... Then, "make my_app-catalogs" should create and install your translated catalogs. ex : for, saying, sys:prefs/wanderer:

on root of AROS sources, type:

"make workbench-prefs-wanderer-catalogs"

then (if you changed the .cd file):

"make workbench-prefs-wanderer"

For apps not localized, you have to adapt their code to support it, if it is possible...

noticed the original .cd file has many (//) strings at the end of any voice, so added them also to the .ct file. That (//) is only for cd files. I'm highly recommending to use FlexCat for updating ct files, e.g. like this:

flexcat app.cd deutsch.ct newctfile deutsch.ct

You'll get error checking and new entries are marked in the resulting ct file.

When editing .ct files, only change those lines containing translation and perhaps version string, nothing else. The rest is up to the relevant tool, flexcat. In order to update your translation, type in the following in your shell:

flexcat xyz.cd xyz.ct NEWCTFILE xyz_upd.ct COPYMSGNEW

This way you will not only make sure you have correct translation file but flexcat also pre-fills newly added strings with "*** NEW *** text. Even better tool for checking cd/ct/catalog files is catcheck, but this one is sadly only available for AmigaOS/68k...

Some languages have variations, like portugues from portugal and portugues from brasil differs...

This is the way to go. I will have a look at language files, but basically if those two languages differ you have to do two separated set of translation files, yes. (you could create a brazilian slang language localization too)

  • At system level localization for one language is a dot language file.

(ex: locale:languages/klingon.language)

  • At app level localization is a dot catalog file

(ex: locale:catalogs/klingon/system/libs/dos.catalog)

  • At sources level, the dot ct file, and "$language" dot cd files and some building framework.

(ex: catalogs/my_app.ct catalogs/klingon.cd catalogs/mmakefile.src support.c support.h)

Please, use Flexcat to generate CT files:

FlexCat wanderer.cd NEWCTFILE=deutsch.ct

Then fill the first 2 lines with something useful:

## version $VER: wanderer.catalog 1.1 (9.2.2006)
## language deutsch

You can even update the CT-File: (This adds the new strings)

FlexCat wanderer.cd deutsch.ct NEWCTFILE=deutsch.ct


To compile a catalog you only need the .cd file and your translation (.ct file):

FlexCat multiview.cd deutsch.ct CATALOG=MultiView.catalog


Linux version of FlexCat

More information


A script which compares the required version (i.e. the version which an application/module etc. tries to open) with the version of the existing CT files. The result is in this table:

https://github.com/aros-translation-team/translations/wiki/Progress

The following cases are highlighted:

   n/a i.e. CT misses at all
   version in existing CT file is lower than the required version


It might be a bit difficult to participate if you haven't worked with Git before but alternatively you can send your CT files to our Slack channel.

When the ct file has been generated via flexcat (flexcat keyshow.cd NEWCTFILE=spanish.ct) it has the following header:


    1. version $VER: <name>.catalog <ver>.<rev> (04.01.2021)
    2. language nolanguage
    3. codeset 0

Those values <ver>.<rev> are the version and revision of the CT file for the languaje or are the values of the application being localized?

The <ver> part must match with version which the application tries to open. You can find the value either in the column "Required Version" in the table which I've linked above, our you can look in the git repository. For keyshow it would be https://github.com/aros-translation-team/keyshow. You can find in the file "catalog_version.h" the right version number. The <rev> part starts for new CT files with 0 and should be increased every time the CT file is updated.

Updated several files and created a few more that were missing on the spanish catalog.

The catalogs are in Git repositories at https://github.com/aros-translation-team

a) You tell me your Github user name. I'll invite you. You can work directly with the Git repositories.

b) You create Github forks of the catalog repositories and create pull requests.

c) You send the CT files to mrustler gmx de


C Utils Misc edit

The AROS source uses at several places the __DATE__ macro to fill the date entry of a $VER tag. Problem is that c:version doesn't understand that date format (e.g. "May 21, 2011"). As a result the output of e.g. > "version c:shell full" contains "(null)". Is extending the version command to understand the format of __DATE__ the right solution for that problem?

AmigaOs compilers should use __AMIGADATE__ macro or similar form, if it isn't implemented it could be emulated in makefile: -D__AMIGADATE__=\"$(shell date "+%d.%m.%Y")\"

BTW. I think DD.MM.YYYY is better format than "Month DD YYY" because "Month DD YYY" is not localized in any way.

"strnicmp" shouldn't work with NULL pointers

The Situation:

compiled a linklib using c++ object files (using the c++ cross compiler). compiled a C stub that uses the linklib (using the c++ cross compiler).

Try to link them together (using the c++ cross compiler) with C object files (using the normal target c compiler) that need to use -nostartup = cant do because using the c++ files pulls in arosc (for stdio etc) - so wants to have the autoinit stuff present.

What can I do about this??

If it is possible to manually open it then what do I need to do exactly?

ENV edit

The philosophy behind ENV: is that keeping configuration files there allows you to 'Use' preferences by keeping a copy in ENVARC: intact. However in some cases (like this one) it is not required.

99% of the time that statement is true (not required) for pretty much every file in ENV: or do people change their default icons - and prefs settings - every boot?

There seem to be a bad habit of late with developers changing things to reflect their own personal preference when the change isn't actually necessary - It would be nice if people could refrain from doing that in the tree without at least discussing it on the dev-list first (and with good reasoning unless they commited said work in the first place..)

We're not keen on the pollution of the "S:" dir: it's meant to be for scripts. What's wrong with "ENV:"? Only the fact that it takes up RAM. I understand that for PCs with several gigabytes of RAM this is irrelevant. But let's remember about other machines. The philosophy behind ENV: is that keeping configuration files there allows you to 'Use' preferences by keeping a copy in ENVARC: intact.

However in some cases (like this one) it is not required.

How about implementing in the style of HappyENV then? RAM-disk handler that falls through to reading from ENVARC: if there is no such file stored in it already. Removes RAM usage for unchanged files, removes the need to copy ENVARC to ENV in startup-sequence. Shouldn't be too hard to make from AmberRAM, or even just extend AmberRAM to provide this service.

Is it feasable to build a special version of AmberRAM handling ENV: that will try and copy the requested file from ENVARC: if it isnt found in ENV: ? Additionaly it could mark closed "files" as untouched - and expunge them from ENV: after a period of time to free up additional RAM:, or when the system is running low on free memory?

Silenty disappearing files may not be a good plan. Would be nice if the following would work:

ASSIGN :ENV SYS:Prefs/Env-Arc ADD ASSIGN :ENV RAM:ENV ADD

Where new files put in ENV: end up in RAM:ENV, and opening files looks in RAM:ENV first, then SYS:Prefs/Env-Arc

Well - that's essentially what im proposing but without the assigns - or need for a RAM:ENV directory. Adding it as a feature of AmberRAM sounds like the most memory efficient way (one handler to load in RAM) but that's only if it is possible to make it handle ENV: additionally to RAM:, and if it is even possible to add the proposed functionality (...and how to make it enable it when accessing ENV:).

(AS)MP support edit

If one has to recompile software for SMP multi core, is there any thing special one has to do to get software to run? Use task.resource if you need to query information about what tasks are running, and clear msgports completely when they are allocated.

Most code should not need Forbid. Use Semaphores, Messages etc to sync your own code.

Accessing system structures is a different thing. Use the proper API whenever possible.

How single structures will be protected in the future is still a moving target, at least it is not documented. And you should never use undocumented stuff



Ideas on for SMP multi-core

Another suggestion is ... Forbid/Permit function calls are meant to halt multitasking so as no other task could intervene with what ever the calling task is doing, e.g. setting semaphores. Disable/Enable calls are meant to halt interrupts and as a side effect they also halt task switching.

One option is to make it compulsory to protect shared resources with semaphores and forbid the use of simple Forbid() calls as to protect something. Setting semaphore should be done if possible with atomic instructions (check and alter in one instruction). Or make the second concurrent ObtainSemaphore call halt the second calling task and force if possible a task switch which ever gives better results.

Semaphores could store the owning tasks task pointer instead of boolean to make things easier.

As long as the CPU initiates the DMA transfers through the OS, and the OS ensures that the transferred memory is within the region accessible to the user initiating the transfer, everything is fine. The CPU is the conductor, and the CPU by that has the control of which DMA transfer is initiated and which is not. All you need to do is to write device drivers reasonable. Hint: CachePreDMA and CachePostDMA exist. All the Os has to do is to verify that the memory regions to be transferred are valid, and prohibit direct access to the DMA control registers from user space. None of these algorithms imply huge costs. The current OS design doesn't really allow virtual memory in first place, Forbid() is again the problem.

memory.library API seem to low level. IMHO the programs should not know how the swapping is implemented. I would just go for one new memory flag MEMF_SWAPPABLE that indicates that a certain memory region or a whole memory pool won't be accessed during Forbid()/Permit() etc. It only solves part of the problem, it only implements virtual memory and not memory protection. For the latter you need to be able make certain memory inaccessible by other programs, some memory read-only for one task and read-write for other tasks, etc. And I think this should be done in the same Address Space in order to avoid you constantly need to swap between different address spaces. So to summarize, if there are programs using this API we may provide a wrapper layer to get them working but I am not convinced this API should be the reference API with whom to provide VM to AROS programs.

Variadic edit

variadic functions (i.e. functions with an arbitrary amount of arguments).

    #include <stdarg.h>
    [...]

    char * STDARGS GetKeyWord(int value, char *def, ...)
    {
        [...]
        va_list va;
        [...]
        va_start(va, def);
        [...]
        va_end (args);

Please keep with using stdarg rather than having va casted to a LONG * type and varargs handled manually. Doing so, prevents tons of casting, where a simple va_arg can be used. So, string = *((char **) args) instead of string=va_arg(va, char *).

#include <stdio.h>
#include <stdarg.h>

int printf (const char * format, ...)

{
    int     retval;
    va_list args;

    va_start (args, format);

    retval = vfprintf (stdout, format, args);

    va_end (args);

    fflush (stdout);

    return retval;
} /* printf */

Couldn't find varargs.h or stdarg.h. and have no use for AROS_SLOWSTACKHOOKS or AROS_SLOWSTACKTAGS.

GCC looks for stdarg.h in a different place:

/bin/linux-i386/tools/lib/gcc/i386-aros/4.2.2/include/stdarg.h

Here is a path for a "normal" header:

bin/linux-i386/tools/lib/gcc/i386-aros/4.2.2/../../../../i386-aros/sys-include/aros/system.h


The use of vararg.h isn't supported by newer gcc versions. If you want your code to run on architectures that pass part of variadic arguments in a number of registers you need to use AROS_SLOWSTACK macros. Otherwise your program will not work on powerpc and x86_64 ports.

Of course the SLOWSTACK stuff is not needed in a function that can use va_list, va_start, va_arg and va_end. It's only needed if you want to write functions like DoMethod or similar.

#include <stdarg.h>

should be enough no matter if you do cross or native compiling. If it does not work, something is wrong and should be corrected.

Stdarg.h is here, Development:lib/gcc/i386-aros/4.2.2/include/

...which is part of the compiler's default include paths. In other words, #include <stdarg.h> works out of the box, indeed. (sorry, I should have just tried it before invoking "search" or "find"...)

furthermore, myprintf() as shown above won't work, because...

printf(format, args);

...is wrong - the second argument does not match printf() prototype, it expects a argument list, but args is of type va_list (obviously) - so one has to use...

vfprintf(stdout, format, args);

...instead, just like in the original printf(), and add fflush(stdout).

additionally, one could use...

int myarg = va_arg(args, int);

...between va_start() and va_end() to access individual arguments, where each call to va_arg() returns an argument casted to the desired type (here: "int") from the list given (here: "args") and advances to the next one.

wrapping up vfprintf() and modifying the format string now is a major speedup! no more backslash-n typing! this has been haunting me for years!

On MOS and AmigaOS, the NewObject variadic function is kept in the static library. It takes most of the parameters on the stack - thanks to that the implementation of NewObject calls the NewObjectA function. Everything works perfect, and the typical MUI macros may be easily used.

This, however, is not the case when you compile for AROS. Here, NewObject is a variadic macro, not a function. Thanks such approach we do not need any custom compiler in case of systems, where the arguments of variadic functions are passed partially through registers and partially through the stack (This is the case of PPC and x86_64, this is also the reason why both OS4 and MOS require specially patched compilers).

Since NewObject is a macro, the gcc's preprocessor expects the list of macros arguments enclosed within parentheses. In MUI macros it is not the case. Imagine the following test code:

#define foo(a,b) ((a)+(b))

int loosy_function(int a, int b)
{
    return foo(a,b);
}

This will compile and work, but the following piece of code:

#define foo(a,b) ((a)+(b))
#define END )

int loosy_function(int a, int b)
{
    return foo(a,b END;
}

will fail with the error: unterminated argument list invoking macro "foo"

There are two ways of fixing your issue. Either create your new objects outside this huge MUI constructions, and in there use just a pointer, or get rid of the "End" macro and exchange it with "TAG_DONE)".


Badly written software is, for example, casting va_list to an APTR or even doing so as if va_list were a plain table of function arguments. Such code needs to be fixed because it has very few chances to work anywhere but on author's machine ;)

The problem is nOt that they assume sizeof(APTR) == 4, its that they often do not use APTR, and use ULONG to store pointers exclusively. If the code used APTR/IPTR as it should - most of the "problems" wouldn't exist.

It would also help if people would start using variadic arguments properly. Many coders do assumptions which shall never be made. Instead, they should consider using stdarg.h file and all the va_* functions :)

ABI edit

In the head of our SVN repository there are now only 3 directories:

admin/
branches/
trunk/

We have added two extra dirs there: tags and imports

As discussed when we branch ABI V0 and ABI V1 it would also be good to introduce tags. Normally this is done in a directory in the repository called tags. Currently we don't have this directory there. (We do have branches/tags that is a hack I have done because one doesn't have write access in the top directory. I think this directory is not clean and should be removed).

The second directory I would introduce is an imports directory for implementing vendor branches as discussed in the svn book. Currently we use code from several different projects and that code is stored inside the AROS tree; we seem to have problems with keeping this code up to date and merge our changes upstream. Maintainers of up stream projects like the MUI classes etc. have complained about this (to put it lightly).

Introducing these vendor branches would make it easier to see what changes we have made and make patches to be sent upstream and make it easier to import newer upstream versions of their code. Although can't "copy" the vendor branch into the main branch because it's already there, so start with a "merge".

Yes, the first step to make the code already in the repository compatible with the vendor branches will be the most difficult. The best way to do it the following way:

  • first import the version on which the current AROS code is based into the vendor branch
  • then import the new version over it in the vendor branch
  • finally merge the difference between these two version in the AROS code present in the repository.

For example, place NList directly under vendor and not in a subdirectory like "contrib/zune/classes".

Actually after we have a stable ABIv1 (2012 or later). We need to move away as much as possible from the contrib directory to some other repositories. The reasons are ...

  • The AROS repository should be for the core AROS code.
  • other contrib projects should be tried to be compiled for all Amiga-like OSes.
  • The release scheme for AROS and the other programs should not have to be aligned.
  • Binary versions should be provided on aros-archives and on aminet and/or OS4Depot to install them. (Some clever programs should maybe be provided to make the life of distribution developers easier).
  • avoid parallel forks of programs for AROS and the other amiga OSes.

If there is really a need for a place for hosting AROS projects we may investigate setting up such a server but then including bug tracking, governance, maillist, etc. for each project separately. I personally think there are already enough places like sourceforge, google code, savannah, etc. where people can go for hosting such projects.

Links edit

In the future...?
  • AROS 64bit - SMP, Vulkan with OpenGL compability layer
  • AROS 32bit - keep for historic reasons

What would you like to see implemented in AROS? ABIv1 completed, SMP (x86_64), SendMsg()/GetMsg() to support memory protection between target and destination, in that order. Michal Schulz and Jason McMullan have been toying with the question "What are the minimal changes needed to the AmigaOS 3.1 API to support SMP"? The answer so far seems to be "few, but subtle". For example, SysBase->ThisTask is no longer meaningful on SMP, but FindTask(NULL) is. Disable() and Forbid() are shockingly bad on performance, but adding a spinlock semaphore mode to SignalSemaphore will help new code on SMP.

Leveraging a 'common' OS with a lot of machine support (Linux, MacOS, Windows, QNX, etc) is something that AROS has been doing for quite a long time, and it is the biggest strength of AROS. This AROS experience and programming model, in the same way the Google's Android layers on top of Linux, or MacOS X layers on top of the Darwin/BSD kernel, as a first step

  • The graphics + layers subsystem could be implemented as a shim on top of a OpenGL ES implementation (ie on any modern Linux system, or the RaspberryPI's hardware, MacOS X, etc).
 - This also allows every window to be on its own 3D surface with backing store, allowing Wanderer (or a Commodity)

rearrange/zoom/animate app windows without having to send a pile or refreshes to them

  • Use OpenAL as the sound backend
  • AROSTCP would be a thin layer over the native OS's TCP/IP stack
  • dos.library, poseidon.library, and input.device would be slim shims over the native APIs
  • If we move to loading all libraries' into the application's task space, instead of a single global instance of the library, this will allow SMP and MMU more easily.
 - Yes, it will require a lot of work in the libraries to make this transition
 - Yes, I do think it will be worth it in the end.
  • A 'fat binary' install format (or, maybe LLVM bytecode) that can be 'flattend' to the target architecture on installation.

So, what would this 'AROS of the future' look like?

  • AmigaOS 3.x style API, with certain 'fundamental changes' to message passing
  • Uses the underlying OS' device drivers, so more AROS developer effort can go to user-visible features and bugfixes
  • Allows AROS applications to run side-by-side with the OS's native apps


And why would anyone want to program on such a system?

  • AROS applications would run on any system that has the AROS Framework installed
  • AROS applications are pixel-for-pixel the same on all platforms.
  • Develop with the knowledge that you are guaranteed OpenGL and OpenAL, and the rest of the AROS Framework

an option for mmake to dump its dependency of metatarget in a graphviz[*] input file. This should make it possible to visualize the dependencies and hopefully be inspiration for cleaning up some mess, circular or unneeded dependencies and so on.




References edit

  1. References and sources
  2. AMIGA ROM Kernel Reference Manual: Devices, 3rd Edition. Commodore-Amiga, Inc. Addison-Wesley, 1991. ISBN 0-201-56775-X