*************************** * * * MorphOS development FAQ * * * *************************** ****************** * * * Multithreading * * * ****************** Q: What is the multithreading? A: When an application is multithreaded, it is written to execute in a parallel maner rather than in a serial or sequential one. Q: What is the difference between a task and a process on MorphOS? A: A process is a task with an extended structure. A process can call any dos.library function, a task can not. In most of the cases, it's simpler to only use process. A task is not faster. Q: How does the multithreading work on MorphOS? A: There is an example in the SDK, it properly handles process startup and shutdown: SDK:Documentation/Examples/Multithreading/procmessages.c - To start a PowerPC process, use exec.library/CreateNewProc() with NP_CodeType, CODETYPE_PPC. - To start a PowerPC task, use exec.library/AddTask() with TASKTAG_CODETYPE, CODETYPE_PPC. Or just use the new exec.library/NewCreateTaskA() V50 function. - Never use RemTask() on a process. Do not use RemTask() on a running task. When they reach the end of their main function, task and process cleanly exit and are automatically removed by exec. That's the way to go. **************** * * * Include file * * * **************** Q: How to create the needed include files if they are not provided in the SDK ? A: You need the original "fd" and "clib" files. The cvinclude.pl perl script can be used to created all kind of include files. - Examples: * To create a proto file for blah.library, use cvinclude.pl --fd=fd/blah_lib.fd --clib=clib/blah_protos.h --proto=proto/blah.h * To create a ppcinline file for the blah.library, use cvinclude.pl --fd=fd/blah_lib.fd --clib=clib/blah_protos.h --inline=ppcinline/blah.h - cvinclude.pl can also create glue lib, trampolines, stubs, etc... Use "cvinclude.pl --help" to get the inline help. - Attention: do not forget to align your extra include files or you will produce broken binary ! SDK:Documentation/Articles/Porting/MorphOS.pdf section 2.1.2 All include files provided in the SDK are already aligned and are a very good example. Q: Where is it possible to add new include files ? A: Do not add non-SDK include in gg:os-include/ directory, or updating the SDK will be difficult. Put extra include files in gg:usr/include/ and you can use -I/usr/include/ in your makefile if needed. Q: How to compile using inlines instead of gluelibs ? A: Define USE_INLINE_STDARG. Please remember C++ doesn't support vararg macros, therefore you can not use this define with C++. Q: What is the difference between inline and stubs ? A: ********* * * * Debug * * * ********* Q: How to debug under MorphOS ? A: There is an online article available on www.biclodon.com: http://www.biclodon.com/documentation/morphosdebug/ There is also an offline version available at the same URL. Q: Where is the GDB (GNU Project Debugger) ? A: There is no GDB port for now. Q: Is there any debugger for MorphOS ? A: For 68k code, there is BDebug. SDK:Contributions/Barfly/ For PPC, there is nothing yet. Q: What is ENVARC:shellppc.prefs ? A: It is an environment variable (local or global) used to control the shell preferences. Try to execute the folloxing command: setenv SAVE shellppc.prefs SIGNALCHECK 3 FORBIDCHECK 3 DISABLECHECK 3 Now, the shell will output some message when an application quits with a pending Forbid() or Disable() or without freeing a signal bit. There are different levels: 0 - don't check 1 - check, don't fix, print 2 - check, fix changes from last command, print 3 - check. fix all changes, print Example: ***Unfreed signals 80000000! ****************** * * * Shared library * * * ****************** Q: How to write a shared library ? A: There are three examples in the SDK: 1) SDK:Documentation/Examples/Library/skeleton - The old library style. - Can be used by 68k and PowerPC ABox code. - Uses the old 68k ABI. - Functions parameters are using virtual 68k registers so: * Limited number of arguments. * No defined FPU register model. * Doesn't match with the SystemV varargs ABI used by MorphOS native PowerPC code. 2) SDK:Documentation/Examples/Library/newskeleton - The new library style. - Can be used by PowerPC Abox code. Can not be used by 68k ABox code. - Uses the new PowerPC SystemV ABI No limitation of the old library style. - It is possible to completly redefine the function table and to mix old and new library styles in the same shared library. So any legacy library can be extended with PowerPC SystemV functions. It is already the case for all new style libraries. The LibInit/Open/Close/Expunge functions are still using the old style. 3) SDK:Documentation/Examples/Library/relskeleton - Used to create base relative library. Usefull for libs with global variables, as sometimes used in the Unix world. - Works by saving the r13 register to provide an own data segment to each instance of the library. - Can be implemented for both old and new style libraries. Q: How to port a 68k library to MorphOS? A: Look in SDK:Documentation/Examples/Library/skeleton Add FUNCARRAY_32BIT_NATIVE to the function table. Then you can write PPC functions usable from 68k code. You get arguments using the REG_#? macros (see emulregs/reg.h). You can also add RTF_PPC in the library's Resident structure, so LibInit() is called as a standard SystemV function. It saves you from using REG_#? macros at this point. Finally, add this symbol: ULONG __abox__ = 1; to tell the loader it is a MorphOS binary (and not a PowerUP/ppc.library one). Just for reference, it used to be __amigappc__ in the early days. Q: If a PPC native application calls a PPC native library using the 68k ABI, does it run through the 68k emulator ? A: No. Q: What does "ABI" mean ? A: Application Binary Interface. SystemV ABI used by MorphOS is documented in the SDK: SDK:Documentation/Articles/Porting/PowerOpenAPI.txt Q: Why is there no dynamic binding ? A: It would add non needed complexity and such a library would not be usable from 68k code without some external fake glue library. It is possible to do dynamic symbol binding on ELF objects by using ppc.library API, though. The native MorphOS version of Quake2 uses this feature. Q: Is it possible to use fopen/fclose/fseek/malloc/realloc/free/... libc function in a shared library ? A: No. These functions needs the startup code that is not linked with shared libraries. If you want to use fopen, malloc and other such functions, you need to reprogram them yourself. ************* * * * The stack * * * ************* Q: How to change the stack size ? A: When using libnix, it is possible to control the PPC stack with unsigned long __stack = PPCSTACKSIZE; /* PPCSTACKSIZE is the PPC stack size in bytes */ * Experts could use exec.library/StackSwap() to control the 68k stack and exec.library/NewPPCStackSwap() to control the PPC one. * The shell builtin stack command only controls the 68k stack. Not the PPC one. A bugfree software does not require that users set the stack size anyway. Q: Why is there two different PPC and 68k stacks ? A: PPC and 68k code have different alignment restriction. Q: Why is there no automatic stack extension ? A: It would be possible in a few limited cases but it would not be generaly reliable in the ABox environment. We want stable software. Q: What is -mstackextend ? A: ************** * * * The memory * * * ************** Q: Why should I use memory pool ? A: They reduce memory fragmentation and are more efficient. Avoid to use exec.library/AllocMem() and exec.library/AllocVec(). Always use memory pools when possible (pool allocation is not thread safe though, but see below). Q: When should I allocate memory using the MEMF_SWAP flag ? A: When you want to allocate memory that the virtual memory manager can swap on disc (the vmem manager is not available yet). Q: When should I allocate memory pools using the MEMF_SEM_PROTECTED flag ? A: When you need to allocate memory from the same pool from different tasks. need to be more precise... Q: Are libnix's malloc(), free(), realloc(), ... all multithread safe ? A: Yes! They use memory pools and you can control the puddle size through the _MSTEP global variable. Example: ULONG _MSTEP = 16384; /* it is the current libnix's default value */ **************** * * * timer.device * * * **************** Q: Which timer.device unit should be used ? A: If your program will only run on MorphOS, you should always use UNIT_CPUCLOCK because it is the most precise timer. All other timers are here for legacy support... and are derived from UNIT_CPUCLOCK. If your application also runs on 68k systems, you should read the original autodocs and pick the right timer for your needs. Or add a check for MorphOS and use UNIT_CPUCLOCK only when running/compiled on MorphOS for improved accuracy. ***************************** * * * MUI dispatchers and hooks * * * ***************************** Q: How to write an internal sub-class in a MUI application ? A: There are many examples in SDK:Documentation/Examples/MUI/ DISPATCHER/DISPATCHER_END/DISPATCHER_REF macros are defined in SDK:Documentation/Examples/MUI/demo.h They are very easy to use: DISPATCHER(MyDispatcher) { /* * dispatcher function */ } DISPATCHER_END mcc = MUI_CreateCustomClass(base, supername, supermcc, datasize, DISPATCHER_REF(MyDispatcher)); Q: How to use hooks in a MUI application ? A: Please always subclass MUI. Hooks are bad design. However some classes enforce the usage of hooks. Then it is possible to write: #include #include static ULONG MyHookFunction(struct Hook *h, Object *obj, struct NList_ConstructMessage *msg) { /* * hook function */ } static struct Hook MyHook = { {0, 0}, (HOOKFUNC)HookEntry, (HOOKFUNC)MyHookFunction }; And &MyHook is the pointer to the hook, of course. Please note the HookEntry() function is part of libabox.a and automatically linked if you use the MorphOS DevEnv. Q: If some PPC code calls some other PPC code through HookEntry(), does it run run through the 68k emulator ? A: No. Q: What is a callback hook? A: Q: How to write a MCC ? A: google sourceforge+mui+mcc mui38dev.lha Q: If a MUI application fails, how is it possible to know the reason ? A: Do something like this:    Object *prefswin, *mainwin, *text, *rect, *app;  app = ApplicationObject,  SubWindow, prefswin = WindowObject, End,  SubWindow, mainwin = WindowObject,  WindowContents, VGroup,  Child, rect = RectangleObject, End,  Child, text = TextObject, End,  /* create objects */  End,  End,  End;    If it fails, you simply check which objects (prefswin, mainwin, rect, text, etc) are NULL.  ******* * * * GCC * * * ******* Q: Why should I always use -O2 or higher optimisation levels ? A: Q: Why should I always use the -Wall switch ? A: Q: Why is the MorphOS SDK based on GCC v2.95.3 instead of the latest v3.x ? A: GCC3 is a major effort and gives many improvements over GCC2.95.x: C99 support, faster code, etc... You can be sure an official MorphOS version will be available on the MDC when it will be ready. But GCC3 is still heavily in development and it didn't reach a stable level yet. It's not a MorphOS only problem and there are also a lot of issues on other OS and CPU. The changelog easily demonstrates it (check http://gcc.gnu.org/). Please look at the list of optimization bugs and other regressions... Of course, it's only a list of discovered and fixed bugs. GCC3 will be ready one day but we have to be patient. Q: Is there any way to define a macro with variable number of arguments? A: Yes, C99 can do it and so GCC too: #define foo(...) bar(__VA_ARGS__) ********************* * * * Ixemul and Libnix * * * ********************* Q: What are ixemul and libnix ? A: "ixemul" means ixemul.library and ixnet.library "libnix" means Both provide all the standard functions needed by C applications: malloc(), fopen(), memcpy(), etc... Q: What is the difference between ixemul and libnix ? A: The applications built for ixemul.library are running in an unix like environment (with unix dos path style, etc) while the libnix applications do not. Q: How to built for ixemul or libnix ? A: * IXEMUL: To compile using ixemul includes (gg:include/): gcc -O2 -c blah.c -o blah.o To link for ixemul: gcc blah.o -o blah * LIBNIX: To compile using libnix includes (gg:includestd/): gcc -noixemul -O2 -c blah.c -o blah.o To link using libnix: gcc -noixemul blah.o -o blah Q: What are constructors and destructors ? A: ******* * * * AHI * * * ******* Q: Where is the AHI SDK ? A: http://www.lysator.liu.se/~lcs/files/ahi/beta/ *********** * * * varargs * * * *********** Q: A: SDK:Documentation/Articles/Porting/MorphOS.pdf section 2.1.3.2 ******** * * * Misc * * * ******** Q: How to detect if a program is running on MorphOS ? A: There is a MorphOS resident. if(FindResident("MorphOS")) { /* * Running on MorphOS */ */ } else { /* * Not running on MorphOS, too bad */ } Q: A: libabox/libamiga libaboxstubs/libamigastubs Q: Why do my code craash when I use the private commodities.library/CxCustom() function ? A: CxCustom() always expects a 68k function pointer. Your PPC code is executed in 68k mode and you get a crash. You must create a gate using an emulation trap and provide it to CxCustom() instead of the real function. Q: But if an emulation trap is used, is the code run through the 68k emulator ? A: No. If some PPC code calls another PPC code through a 68k emulation trap, the 68k emulator is never run. Q: Sending a ctrl-c terminates the program but it doesn't quit and free everything properly. A: Disable the builtin ctrl-c signal handler. #include signal(SIGINT, SIG_IGN); Then you can detect ctrl-c using exec/SetSignal() and act accordingly. if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { /* ctrl-c */ } *********** * * * Display * * * *********** Q: How to do fullscreen multi-buffering ? Q: Q: Do Winners use SmartRefresh? Should I use SmartRefresh or SimpleRefresh? A: SHORT ANSWER NO! Remember to turn on SimpleRefresh in all applications where available. With MUI, simply set the refresh with the Windows->Refresh gadget. The reason why you should avoid smartrefresh is that it uses a lot of RAM, and is also slow due to a lot of allocating/copying of gfx data. While smartrefresh was meaningful with slow CPU's and small amount of gfx data (low color ECS/AGA resolutions), it makes no sense with high color and big resolutions. In addition, the cliprect defined by old layers is so stupid, superlayers was unable to lessen the amount of gfx-data transfere happening. A: LONG ANSWER - by the Superlayers author With smartrefresh, the machine doesn't have to "think" very much, it simply copies a lot of gfx data, because the system automaticly saves and restores window contents. This copying from gfxcard<-->fast ram is pretty slow, even with zorro III. Reading from gfxcard ram is worst, it's dead slow. With smartrefresh this happens all the time. .. With simple refresh, there's more "thinking" involved, because the system doesn't save and restore window contents. Instead it orders the application to redraw itself in the damaged portions of the window. .. Now, this is what happens in a typical "window-arrangement" situation (simplified): With "buffers" i mean offscreen bitmaps in fastram. .. Smartrefresh: - Allocation of buffers - Copying some stuff from old buffers to new buffers (fastram->fastram) - Copying some stuff from screen to new buffers (gfxram->fastram) VERY SLOW! - Moving on-screen gfx using blitter (VERY FAST) - Copying some stuff from old buffers to screen (fastram->gfxram) - Free old buffers Simplerefresh: - Moving on-screen gfx using blitter (VERY FAST) - Repair damaged regions in the window, which usually means: - Text rendering - Linedrawing/Rectangle filling (blitter) - Image rendering, in other words copying from fastram->gfx ram Important: The amount of gfx needed to be renderd in the repair part is in most cases much smaller than the buffers dealed with when using smartrefresh. .. As you can see, simplerefresh involves much less data-moving, and is therefore generally the preferred method, but as you've experienced yourself, it's not always the case. Why? Because the repair part of the simplerefresh operations involves much more "thinking" than simply figureing out what to copy, like in a smartrefresh case. .. So it all comes down to a balance between the ability to move gfxdata, the amount of gfxdata (depth, resolution), and the raw cpu power. .. A very typical resolution, 1024*768*16, involves a lot of gfx data, and therefor simplerefresh is the superior choice, unless your cpu is so slow it is better off copying data. (a little more technical: when copying the cpu only does a small loop to copy memory, while with repair the cpu needs to execute a lot of code). .. I could do a lot more explaining, but I guess this is enough.. just a note: I could have speeded up smartrefresh operations A LOT with superlayers, but it is impossible because of how the old CBM guys defined the cliprect used by gfx.library. It's a shame really.. .. Last note: if you have a lot of windows open and/or uses OpaqueMove/Size, then the smartrefresh becomes even slower compared to simple. - Trond Q: AA & penless Draw() A: SetRPAttrs(rastport, RPTAG_PenMode, FALSE, RPTAG_FgColor, 0xFF00FF00, RPTAG_AlphaMode, TRUE, TAG_DONE); ******* * * * SDL * * * ******* Q: Where is the SDK for MorphOS SDL ? A: http://www.lehtoranta.net/powersdl/ *********** * * * Maltese * * * *********** Q: Why is this FAQ not finished ? A: This document was created per request of a specific person. This same person later claimed no programmer documentation was being worked on. :-( Sometimes, dreams come true.