Aros/开发者/软件移植
在尝试移植程序之前,请确保其API依赖项在AROS上得到满足。(AmigaOS (TM) 3.x C API被认为是AROS原生)
- 可接受:ANSI-C/C++,[SDL v1但v2正在开发中],通过gtk-mui使用GTK,Cairo(旧版移植),通过Gallium3D加速使用OpenGL,…
- 非常困难:PyGame,Boost,Allegro,无SDL,Gnome,KDE和/或QT4等。
- 不可能:Java,C#,任何仅限Windows的源代码等。
打开shell - 它是Wanderer(桌面)左上角的菜单选项。或者在包含makefile的目录中使用右侧Win键和w(或F12和w)。输入
sh
将Amiga shell更改为Unix shell。然后可以输入ls(unix等效于amiga dir)。请查看此处以获取命令。
对于单个文件program-name.c或program-name.cpp
gcc -o program-name program-name.c
或
g++ -o program-name program-name.cpp
要关闭shell,请单击左上角以关闭(两次)。
其他缺少的符号是由于需要链接库才能链接不在标准C库中的函数。例如,某些源代码需要添加
-lz -lm -lpng
进行编译,甚至-lmui开关以将程序与MUI gui链接。
在unix命令行模式下使用此命令在许多.c文件中搜索“search-item”(.cpp用于c++等)。
grep -l 'search-item' *.c
打开shell - 它是Wanderer(桌面)左上角的菜单选项。或者在包含configure和make文件的目录中使用右侧Win键和w。输入
sh
将Amiga shell更改为Unix shell。
configure—help
以查看可用选项。您需要时间来检查选项并选择正确的选项。稍后将提供提示。当您使用“configure”脚本配置GCC时,它将从模板文件“Makefile.in”构建文件“Makefile”。当它这样做时,它将合并来自“config”目录的makefile片段文件,命名为“t-TARGET”和“x-HOST”。如果这些文件不存在,则表示对于给定的目标或主机不需要添加任何内容。
例子…
configure prefix=/PROGDIR --build=i686 --host=i686 --disable-nls configure prefix=/PROGDIR --build=i386 --host=i386 --disable-nls --without-opengl --without-star --disable-sdltest configure LDFLAGS="-nix" --prefix=/PROGDIR --build=i386 --disable-nls --without-x --without-pic --disable-shared GREP=bin: --enable-client=sdl --disable-server --disable-sdltest --with-sdl-prefix=development:include/SDL
创建Makefile,但如果它不起作用,请查看下面的提示部分
首先查看Fishy的教程first
dir ../ 向上移动一个或两个目录
dir / Amiga等效项
创建Makefile后,在unix shell中,输入
make -f Makefile
创建程序…
这需要多个.c .o文件的副本
CC = gcc #CC = g++ #AS = nasm -f coff #AR = ar LDFLAGS = -s FLAGS = -I. -Icpu -Iaros -Wall -march=pentium -fomit-frame-pointer LIBS = -lz -lm -LDevelopment:lib #LIBS = -lSDL_net lSDL_ttf -lSDL_mixer -lSDL_image -lpng -ljpeg -lz -lvorbisfile -logg -lSDL #LIBS = -lz -lm -LDevelopment:lib -lglu -lglut -lgl -lSDL_mixer -lSDL_image -lpng -ljpeg -lz -lSDL EXE = name OPTS = -O2 # @echo "Building source files..." $(CC) $(FLAGS) $(OPTS) -c src/.c -o obj/.o $(CC) $(FLAGS) $(OPTS) -c src/.c -o obj/.o #$(CC) $(FLAGS) $(OPTS) -c src/.cpp -o obj/.o #$(CC) $(FLAGS) $(OPTS) -c src/.cpp -o obj/.o @echo "Making executable..." $(CC) $(LDFLAGS) $(FLAGS) -o $(EXE) obj/.o $(LIBS) @echo "Done!"
如果需要g++编译器,请从CC = g++中删除#。记住在CC = gcc前面加上#。开头的#充当注释行,不会被处理。类似地,分别删除/添加LIBS部分中的#以激活简单的命令行编译、简单的SDL编译或openGL编译。
在EXE部分中将名称替换为程序标题。
然后添加您要编译的各种.c(使用gcc编译)或.cpp(使用g++编译)源代码以及.o
$(CC) $(FLAGS) $(OPTS) -c src/main.c -o obj/main.o
最后,收集所有.o用于最后一行
$(CC) $(LDFLAGS) $(FLAGS) -o $(EXE) obj/main.o main2.o etc.o $(LIBS)
也应该查看MakeTools。
CC = gcc CFLAGS = -O LDFLAGS = -lSDL_image -lpng -ljpeg -lSDL_ttf -lfreetype2 -lSDL_mixer -lvorbisfile -lvorbis -logg -lSDL -lgl -lglu -lz -lstdc++ -lm OBJS = part1.o part2.o main.o # $(OBJS) will look above for list of .o and then use the statements below to see what to do with them myprogram: ${OBJS} ${CC} -o myprogram ${CFLAGS} ${OBJS} $(LDFLAGS) #-------------------------------------------------------- part1.o: part1.c part1.h header.h ${CC} ${CFLAGS} -c part1.c part2.o: part2.c header.h ${CC} ${CFLAGS} -c part2.c main.o: main.c header.h ${CC} ${CFLAGS} -c main.c clean: rm -f myprogram ${OBJS} @echo "all cleaned up!"
只需使用适合您的那个。
#Simpler version suffices for most small-scale projects #DEPS is needed to recompile hellomake.c with changed hellomake.h CC=gcc CFLAGS=-I. DEPS = hellomake.h # gcc, $(CC) and rm need to be TABbed to work with make # macro DEPS, which is the set of .h files on which the .c files depend %.o: %.c $(DEPS) # -o $@ compiler output into file named on the left side of hellomake: below ie hellomake # the $< is the first item in the dependencies list #DEPS $(CC) -c -o $@ $< $(CFLAGS) #putting the object files--hellomake.o and hellofunc.o in dependency list #make knows it must first compile the .c versions individually, and then build the executable hellomake hellomake: hellomake.o hellofunc.o gcc -o hellomake hellomake.o hellofunc.o -I
CC = gcc CFLAGS = -O2 -I/include LDFLAGS = -lSDL_image -lpng -ljpeg -lSDL_ttf -lfreetype2 -lSDL_mixer -lvorbisfile -lvorbis -logg -lSDL -lgl -lglu -lz -lstdc++ -lm #----------------------------------------------------------------------------- OBJS = part1.o main.o program: $(OBJS) $(CC) $(OBJS) -o $@ $(LDFLAGS) $(STRIP) --strip-unneeded --remove-section=.comment $@ #----------------------------------------------------------------------------- part1.o: part1.c part1.h @echo " Compiling $*..." @$(CC) $(CFLAGS) $*.c main.o: main.c header.h @echo " Compiling $*..." @${CC} ${CFLAGS} $*.c clean: rm -f myprogram ${OBJS} @echo "all cleaned up!"
# Template for a simple generic Makefile # CC = i386-aros-gcc # CPP = i386-aros-gcc -E # CXX = # CPPFLAGS = # CXXFLAGS = CFLAGS = (cflags) LDFLAGS = (ldflags) TARGET = (final-file-name) OBJECTS = file1.o file2.o file3.o LINKS = file1.c file2.c file3.c # XTRAOBJ = # # rules # all: $(TARGET) $(TARGET): $(OBJECTS) $(XTRAOBJ) $(CC) $(OBJECTS) $(XTRAOBJ) $(LDFLAGS) -o $(TARGET) %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ # # eof # Cycloid Makefile Example # OBJ = window2.o # # w.exe: $(OBJ) # $(CC) $(CFLAGS) -o $@ $^ $(ARCHIVE) $(LIB) # # window.o: window2.c # # $(CC) $(INCL) -c window2.c
# .h files in an include directory IDIR =../include CC=gcc CFLAGS=-I$(IDIR) # .o files into a obj subdirectory and some local libraries in lib directory ODIR=obj LDIR =../lib macro defined for any libraries you want to include, like mui library -lMUI LIBS=-lMUI _DEPS = hellomake.h DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) _OBJ = hellomake.o hellofunc.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ) gcc -o $@ $^ $(CFLAGS) $(LIBS) # .PHONY rule keeps make from doing something with a file named clean .PHONY: clean # cleaning up your source and object directories clean: rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
#simple makefile CC=gcc CFLAGS=-O2 -s -DNO_INLINE_STDARG -I./api/ -I../api/ -I../modules/api/ -I../amide/modules/api/amide/ LDFLAGS=$(CFLAGS) -nostartfiles -nodefaultlibs -lamiga -lstdc.static -lgcc EXE=plugins/test.plugin # Objects OBJS = StartUp.o \ LibInit.o \ sasc_module.o all: $(EXE) clean: rm -f *.o $(EXE) $(EXE): $(OBJS) echo Making $@.. $(CC) -o $(EXE) $(OBJS) $(LDFLAGS)
- 关于std::和运算符的undefs意味着您需要使用或g++,或者如果您使用gcc,则添加到-lstdc++
- 关于sdl_wav的undefs表示-lsdl_mixer,
- 关于AROSMesa的undefs表示-lgl,
链接顺序很重要,因此例如,您不能首先执行-lgl,然后执行-lsdl。由于sdl需要gl,您需要执行-lsdl -lgl,以及所有其他库:在出现undefs时一个接一个地包含。
-lSDL_image -lpng -ljpeg -lSDL_ttf -lfreetype2 -lSDL_mixer -lvorbisfile -lvorbis -logg -lSDL -lgl -lglu -lz -lstdc++ -lm
在“sasc.module”中存在未定义的符号:__PROGRAM_ENTRIES__symbol_set_handler_missing __LIBS__symbol_set_handler_missing
从命令行中移除 -nostartfiles 参数,丢失的符号是 AROS 自动启动处理的一部分。可能手动添加 -llibinit 可以修复丢失的符号。
添加 -nodefaultlibs 如下所示
LINK := $(OPTIMIZE) -s -nostartfiles -nodefaultlibs
应该会移除所有自动添加的库,现在您需要手动添加它们。
$(CC) $(LINK) -o $@ $(O_FILES) -lamiga -lstdc.static -lgcc
#simple makefile CC=gcc CFLAGS=-O2 -s -DNO_INLINE_STDARG -I./api/ -I../api/ -I../modules/api/ -I../amide/modules/api/amide/ LDFLAGS=$(CFLAGS) -nostartfiles -nodefaultlibs -lamiga -lstdc.static -lgcc EXE=plugins/test.plugin # Objects OBJS = StartUp.o \ LibInit.o \ sasc_module.o all: $(EXE) clean: rm -f *.o $(EXE) $(EXE): $(OBJS) echo Making $@.. $(CC) -o $(EXE) $(OBJS) $(LDFLAGS)
以及 LoadModules 函数从 main.c 中调用该函数,在 AROS 的情况下,最好使用可移植的宏来进行这些调用。
mod_class =AROS_LC0(void *, AmIDE_API_GetClass, struct Library *, (AmIDE_API_Base), 5, AmIDE_API );
- include <aros/libcall.h>
此外,大多数 AROS 代码依赖于库基自动打开,因此您可能需要添加一个链接库 libauto (-lauto)。某些系统(因此取决于编译器提供)没有可用的 libauto,在这种情况下,您需要手动打开库基。
此处可以找到提示 请注意,这些链接适用于使用 Linux 编译代码而不是原生代码,但可能有用。
CONFIGURE ERRORS Error : no acceptable C compiler found in $PATH Solution : add CC=gcc or CC=g++ after configure Error : no acceptable grep could be found in /Development/bin: Solution : add GREP=bin: to configure line Error : gtk-mui library sequence Solution : gcc -o test addbutton.c\ -lglib-2.0 -lgtlayout -lgthread-2.0 -lgmodule-2.0 -lgobject-2.0 -lgtk-mui -lglib-2.o -liconv -lmui -lthread Error : VARIABLE not within scope Solution : add headers like... #include <libraries/mui.h> #include <proto/muimaster.h> or #include <string.h> etc Error : malloc.h no such file or directory Solution : malloc is contained within <aros/stdlib.h> Error : SDL.h no such file or directory Solution : #include SDL/SDL.h needed at top of .c file or -IDevelopment:include/SDL to the command line Error : Solution : Error : IMG_Load in -lSDL_image ... cannot find libSDL_image Solution : ?? Error : pow in -lm - 'case' unmatched - math.library (-lm) appears broken Solution : ?? Error : Solution : Error : Solution : MAKE ERRORS Error : *** missing separator. Stop. Solution : Make commands like gcc $(CC) or rm need to be TABbed in and not use spaces Error : Solution : Error : Solution : Error : Solution : COMPILING ERRORS Error : expected '=' ';' "asm" or '__attribute__' before '{' Solution : look at previous lines for missing/extra ; (like in defines) or missing } or forgot to #include something.h. Use gcc -E to check Error : request for member 'something' in function not a structure or union Solution : using b.x = 12 (usually arrays); when it should be b->x (usually structs) or (*b).x, .h needed, Error : 'something' undeclared (first use in this function) Solution : 'something' been declared at start of function, .h needed or link library needed -lmui etc., Error : there are undefined symbols in program Solution : /* around these symbols' */ until you work out if they are needed or can be deleted Error : there are undefined symbols in <program-name> or memcpy strndup first Solution : linker library not included -lz -lSDL or -lGL etc or <string.h> Error : expected specifier-qualifier list before 'USHORT' Solution : change all references of USHORT into UWORD (SHORT into WORD) Error : expected declaration specifiers or '...' before 'USHORT' Solution : replace USHORT with UWORD (SHORT into WORD) Error : field 'name' has incomplete type Solution : Error : expected ')' before 'type' Solution : Error : invalid conversion from 'ULONG*' to 'IPTR*' Solution : most amiga like OS's return ULONG values or use ULONG TAGS but 64bit AROS needs IPTR used for compatibility Error : dereferencing pointer to incomplete type Solution : Error : If crackly break-up noise found in SDL sound Solution : try to find where the number of samples for the buffer is set in the source and increase it (double it at least). This solves many sound issues with SDL programs. The buffer was set to 1024, now set it to 4096. Error : initializer element is not constant around TAG_DONE); Solution : header(s) <utility.h> and <proto/utility.h> need to be added Error : no i386-sdl-config Solution : use --build=i686 instead of --build=i386 Error : functions not found at final linking: SDL_CondWait, SDL_CondSignal, SDL_CreateCond Solution : find them in the SDL_cond_aros.c file in the cdxlplay-sdl source http://www.a500.org/downloads/video/ Error : crash glutGet((GLenum)GLUT_ELAPSED_TIME); Solution : The glutInit function is needed, replace with by SDL_GetTicks() Error : undefined symbols: recv, connect, inet_pton, socket, select, send, inet_ntoa Solution : LDFLAGS : -lSDL_net -lSDL with #include <proto/bsdsocket.h> (or <proto/socket.h>) in all files using SDL_net Error : SDL is not built with CDROM support. Solution : Look for SDL_INIT. It can look something like this: if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) change it to: if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK ) == -1 ) That includes all the init routines available in SDL, minus the CD one. Error : Video mode set failed: OpenGL support not configured Solution : 'sdl-config --libs' is fine for most SDL uses, but with GL it needs to be replaced with "-lgl" Error : Solution : Error : Solution : RUN TIME ERRORS Error : Solution : Error : Solution : Error : Solution : Error : Solution : Error : Solution : Delinting (removing warning messages) 64bit compatibility - MUIA_Application_Copyright, _(MSG_AppCopyright), + MUIA_Application_Copyright, (IPTR)_(MSG_AppCopyright), - io->io_Unit = (struct Unit *)unitnum; + io->io_Unit = (struct Unit *)(IPTR)unitnum; Clean up - ULONG signals; + ULONG signals = 0; - while((t = LibNextTagItem(&tagList))) + while((t = LibNextTagItem((struct TagItem **)&tagList))) - while ((tag = LibNextTagItem(&msg))) + while ((tag = LibNextTagItem((struct TagItem **)&msg))) - const struct TagItem *tstate = msg->ops_AttrList; - struct TagItem *tag; + struct TagItem *tag, *tstate = msg->ops_AttrList; - sprintf(buf, "SYS/printer%d.prefs", unit); + sprintf(buf, "SYS/printer%d.prefs", (int)unit); - STRPTR _return = NULL; + CONST_STRPTR _return = NULL; - return (CONST_STRPTR)_return; + return _return;
main() 函数的正确形式是
int main(void) { ... return retval; } or int main(int argc, char **argv) { ... return retval; }
(旧代码通常为 "void main()" 或根本没有返回类型)
对于 retval,您可以使用 0、EXIT_SUCCESS 或 EXIT_FAILURE (ANSI-C),或者 ADOS 返回代码,我不太清楚。
首先将所有以 _proto.h 结尾的文件
#include <dos/dos_proto.h> to #include <proto/dos.h>
如果您希望它更具可移植性,那么请尝试
#ifdef AROS #include <proto/dos.h> #else #include <dos/dos_proto.h> #endif
从 proto 包含共享库的函数原型,例如 #include <proto/graphics.h> 而不是 #include <clib/graphics_protos.h>
如果编译器在类似以下的代码行中抱怨类型错误
struct Library *GfxBase
您需要在头文件中查找正确的类型,例如在 includes/proto/graphics.h 中
#include <proto/library_name.h>
(替换为正确的名称) 应该引入必要的信息,以便自动打开/关闭 CORE 库,以与编写为 DOS 和 Workbench/Wanderer 启动进程的基本应用程序一起工作。其他程序(如 mui)必须指定(在 gcc 命令行中使用 -lmui)。
看起来您仍在从 clib 包含文件。您要么必须从 proto 包含文件,要么必须链接 -lexec -lgadtools 等。
在 'inctst' 中存在未定义的符号:U AllocMem U FreeMem
添加 -lexec 解决了错误。
There are undefined symbols in 'a.out': SetFont CloseFont OpenFont
尝试 -lgraphics 或 #include <proto/graphics.h> 或 #include <defines/graphics.h> 或 #include <clib/graphics_protos.h>
Include sys/types.h before netinet/ip.h Include <netdb.h> first before rest of your network includes
大多数 AROS C/C++ 编译器可以作为启动代码的一部分为您打开和关闭库。只要您在头文件中包含了 protos 并在编译器选项中指定了适当的选项,编译器就会为您处理打开任何使用的库。
库头文件源代码原则上也类似于 AOS 68k,包含 Resident 结构、functable 等。除了 AROS 有一套自己的宏用于在寄存器中获取参数的函数。AROS_LH#? 和 AROS_UFH#? 这些东西。您可以使用 AROS contrib 源代码中的 contrib/mui/classes/nlist/commonaros/mccheader.c 作为提示。
但始终记住,为 AROS 编码与为 m68k Amiga 编码不同。这里有很多不同之处,并且使用 C 编写 AROS 代码意味着搜索数百个包含文件以查找宏。AROS 源代码对于外部新手开发人员来说部分是无用的,因为 AROS 具有深度集成的构建系统,该系统隐藏了实现开发人员的重要部分,例如,共享库仅由其方法组成,其余部分(Romtag、Jumptable 等)隐藏在 AROS 构建系统中。
wbstart.library 确实没有移植,但其用法已弃用,建议您将其调用转换为使用 workbench.library/OpenWorkbenchObject()(这应该很容易)。
一个临时的快速技巧是在 C 中使用 CLI 调用:Open,它将使用 Workbench 启动程序(使用此功能)。它甚至可以与作为工作台参数传递的参数一起使用(即像多单击的文件)。
只要程序中未使用汇编代码,就可以在 AROS 上编译为普通 AmigaOS(直至版本 3.1)编写的 C 程序,而无需对源代码进行任何更改。(这假设您的 AROS 使用 32 位大端 CPU,例如原始的 Amiga 计算机。)(请注意,AROS 仍处于测试阶段且不完整,并且可能缺少 AmigaOS API 中的一些功能。有关更多信息,请参阅AROS 实现状态。)
首先要考虑的一些事项是 C 数据类型的实际大小,以及在使用二进制文件(例如 IFF)时,要注意使用可移植性到 64 位和小端 CPU 以及 Amiga OS 使用的经典 mc680x0 或 powerpc cpu 进行读取和写入。
- 警告标志是在 char * 和 WORD/LONG/short/int 等之间进行类型转换,或任何类型的指针算术,以及任何读取/写入二进制文件格式的函数(如果它们逐个字符读取和/或执行类似于我上面提到的操作,它们很可能没问题,如果它们读取一段内存并立即将其视为结构,那么它几乎肯定会失败)。
- 需要修复大小端问题,而且有很多(读取/写入二进制文件,将数据写入图形帧缓冲区)。还有网络堆栈、文件系统、硬件。几乎在任何时候,只要您必须处理外部数据,就必须担心大小端问题。有一些 C #define 宏可以处理写入/读取正确的大小端,并在必要时翻转顺序。
- 所有 LONG/ULONG/APTR 需要检查是否需要替换为 IPTR(例如依赖于 TagLists)
[我们可能应该在这里提供一个图表,显示 Manx/sas/dice C 在 mc68000/68030 上使用的大小/大小端与当今的 PPC/i386/x86_64 AROS 选项,以及一些 GCC 源代码,以展示如何在不同的大小端 CPU 上运行的 AROS 下正确读取/写入二进制文件]
基于 Amiga 芯片组图形的屏幕通常以平面格式完成,对于 ECS 高分辨率/低分辨率模式分别最多为 16/32 色,对于 AGA 为 256 色。
[此处应提供常见 Amiga 屏幕模式的图表]
对于相对低分辨率的平面 Amiga 显示器效果很好的方法,对于当今常见的块状和真彩色屏幕来说可能不是最佳的。
[此处应提供指向示例的指针]
Amiga 屏幕可以具有不同的分辨率,可以上下拖动以显示另一个屏幕,因此某些应用程序是用不同的分辨率屏幕编写的,例如一个用于控制面板,另一个用于同时垂直堆叠的可见“显示”。这对于当今的芯片组或宽屏显示器可能没有意义。打开扫描率不同的多个屏幕可能会使显示器(监视器或投影仪)感到困惑,每次用户决定更改要查看的公共或私有应用程序屏幕时,它可能需要几秒钟才能“校准”。默认为用户对 Wanderer(工作台)的屏幕模式偏好可能比在应用程序中硬编码预定义模式更好。
AmigaOS 3.1 还附带了一些在 AROS 下当前不可用的不错的磁盘字体,因此您应该注意不要将任何磁盘字体硬编码为程序中的默认字体。ROM 字体“topaz”应该没问题。
AROS 字体(截至 2010-03-10)
- arial.font
- dejavusansbold.font
- dejavusansboldoblique.font
- dejavusansbook.font
- dejavusanscondensedbold.font
- dejavusanscondensedboldobl.font
- dejavusanscondensedcondens.font
- dejavusanscondensedoblique.font
- dejavusansextralight.font
- dejavusansmonobold.font
- dejavusansmonoboldoblique.font
- dejavusansmonobook.font
- dejavusansmonooblique.font
- dejavusansoblique.font
- dejavuserifbold.font
- dejavuserifboldoblique.font
- dejavuserifbook.font
- dejavuserifcondensedbold.font
- dejavuserifcondensedboldob.font
- dejavuserifcondensedconden.font
- dejavuserifcondensedobliqu.font
- dejavuserifoblique.font
- fixed.font
- stop.font
- ttcourier.font
- Vera Mono Bold.font
- Vera Mono Bold Italic.font
- Vera Mono.font
- Vera Mono Italic.font
- Vera Sans Bold.font
- Vera Sans Bold Italic.font
- Vera Sans.font
- Vera Sans Italic.font
- Vera Serif Bold.font
- Vera Serif.font
- XEN.font
struct Node 中字段的顺序目前与 AOS 上的不同(将在 ABI V1 中更改)。
struct Node 目前具有以下顺序
struct Node { struct Node * ln_Succ, * ln_Pred; char * ln_Name; UBYTE ln_Type; BYTE ln_Pri; };
MUI - AROS 首选的 GUI 工具包是 Zune,它是 MUI 3.x 的重新实现,因此 MUI 3.x 代码可以在 AROS 下无变化地运行。MUI 4.x 需要进行适配,或者等待以下悬赏启动。
ReAction/ClassAct,AmigaOS 的一个 GUI 工具包,在 AROS 中不可用。它已成为 AmigaOS 3.5 及更高版本的一部分。使用 ReAction 的程序可能需要大量修改,最好是使用 Zune(或 MUI),AROS 的 GUI 工具包。
bgui 作为 "contrib" 存档的一部分提供,因此包含在所有当前的 AROS 二进制发行版中。
[此处可以添加一个图表,比较开发人员的 GUI 选项。]
GCC/G++ 是 AROS 提供的主要 C 编译器。使用其他编译器(SAS/C、Maxon C 等)特定功能的 Amiga 程序可能需要一些修改。您可能需要编写可在托管或原生环境下运行的 Makefile,以便任何 AROS 用户都能在自己的机器上编译和运行它们。在托管环境中,shell 很可能使用 UNIX 语义,例如 cp==COPY ../==父目录,并且所有文件名对于您的 Makefile 和 C 源代码文件都是区分大小写的(例如:#include "myFile.h" != #include "MyFile.H")。在 AROS 下,Makefile 可以使用 Amiga shell 命令语义(copy #? progdir:prefs),或者它可能使用移植到 AROS 的 UNIX shell 和 AROS 环境,并且像 AmigaOS 3.1 一样可能不关心文件名的区分大小写。
我们不能使用 SLOWSTACKTAGS 宏从可变参数列表中获取 ULONG 值。
SAS/C 是 AmigaOS 3.1 发布时更流行的编译器软件包之一,它支持各种关键字,例如 __chip 用于使用芯片 RAM,以及当前 AROS GCC 不支持的与 CPU 相关的寄存器参数。
Makefile 需要从 SMAKE 转换为 GNU Make,并且一些头文件需要从 SC 转换为 GCC。
Pragma 用于 SASC 等旧版 C 编译器。从 "proto" 中包含,例如 #include <proto/workbench.h>。查看是否有从 "clib" 中包含的头文件。将它们也更改为 "proto"。
您可以忽略诸如 "建议使用括号..." 或不兼容的指针类型之类的警告。
某些类型和定义的名称已更改(SHORT/USHORT -> WORD/UWORD)。
-linput -lutility -lintuition -lrexxsyslib -lconsole -lgraphics -ldos -lexec
strmfp、stcgfe、stcgfp、stcgfn 和 stci_d 是 SAS/C/Lattice 函数,在 gcc 下不存在。它们需要重新实现。
在源代码中包含 ctype.h 后,发现了 tolower 和 toupper。有时缺少的符号来自缺少的包含文件。这些是像 toupper 这样的宏——而不是真正的函数,C 预处理器需要包含宏的定义。
如果希望字符为无符号类型,则需要在变量类型中添加 unsigned。如果希望它们为有符号类型,则在变量类型中添加 signed。如果不添加任何一个,可能会得到意外的结果。
有时需要为不属于 ANSI C 的函数编写包装器。
SAS/C 允许在定义类型之前使用它 => 更改顺序或使用前向声明。
使用 AROS 宏进行 Hook 函数,如下所述:http://aros.sourceforge.net/documentation/developers/app-dev/portable.php#hooks
如果您正在移植系统软件(库、中断等),可能会有更多问题。只需开始并尝试查找警告和错误的原因。
通常在移植源代码时,如果 AROS 中不存在某个头文件,请使用 #if 或 #ifndef 语句将其包装起来,并查看找不到哪些符号、结构定义等。然后,您可以查看 AROS 包含文件,看看缺少的符号等是否在其他地方实现,或者是否需要创建自己的兼容包含文件来定义这些符号。
对于库,您可能需要查看 AROS 源代码树,了解其他人如何使用 sfdc、genmodule 等工具来实现。
- SAS/C 在其 C 库中包含了大量非标准函数。这些函数的替代版本通常可以在网上找到,例如 YAM 在其源代码中包含了一些函数,具体取决于许可证,解决此问题很容易(如果需要,这些函数都不大/不容易重新实现)。
- SAS/C 在某些方面非常宽松。这会导致问题,特别是对于 vbcc(与 AROS 关系不大),但也有一些问题对于 gcc,尤其是在类型强制和(缺乏)前向声明方面。
- SAS/C 具有大量针对 AmigaOS 的扩展,例如非标准的以 68k 为中心的寄存器声明。这些必须删除或通过定义预处理器宏来解决,这些宏扩展为空或合适的替换。
- SAS/C 的 smakefile 使用完全非标准的语法。
- AmigaOS 与 AROS 包含文件的通用注意事项适用——许多路径预计会不同。
- 可能存在字节序问题。
- 您会收到很多编译器警告。其中一些是无害的(例如 "建议使用括号...")。另一些则很危险(例如 "变量 xxx 可能未定义")。
- 对于回调 Hook 等一些特殊情况,您需要使用 AROS 宏。
- 使用文本编辑器或某些工具将源代码中的所有 "ULONG" 替换为 "IPTR",并将 "LONG" 替换为 "SIPTR"。
- 修复(将 IPTR/SIPTR 更改回 ULONG/LONG)确实依赖于 ULONG/LONG 恰好为 32 位的少数几个地方。这适用于像素(ARGB)缓冲区、写入/读取到磁盘的结构、调色板,但可能很少其他。
这是我在 diskimage.device 中用于将 BSTR 转换为 CSTR 的代码
LONG CopyStringBSTRToC (BSTR src, STRPTR dst, ULONG dst_size) { #ifdef __AROS__ STRPTR ptr = AROS_BSTR_ADDR(src); ULONG ln = AROS_BSTR_strlen(src); #else UBYTE *ptr = BADDR(src); ULONG ln = *ptr++; #endif if (ln > (dst_size-1)) ln = dst_size-1; memcpy(dst, ptr, ln); dst[ln] = 0; return ln; }
一些 blankers[检查拼写] 缺少符号 "custom"。它们(如 OS3.9 RKM 中所述)具有 "extern struct Custom custom;"。'Custom' 是一个结构,用于映射 m68k Amiga AGA/OCS/ECS 寄存器。仅为 amiga-m68k 构建这些,您将一切顺利。
- RAWKEY:替换为 IDCMP_RAWKEY
- ModifyIDCMP(win,FLAGSON) 替换为?
ADis,它将二进制文件逐块读取到内存中以反汇编它们,然后将其视为一个短整型数组。正确的做法是将其视为 char *,并执行 (arr[0] << 8) + arr[1]。我想用它来交叉反汇编 M68k 程序,但放弃了,转而使用 Ira,因为它非常普遍。
在 AmigaOS 上,这是由 libc 在每次 I/O 操作时完成的。只有 AROS 库缺少此功能。由 libc 分配的资源(malloc() 分配的内存、fopen() 打开的文件等)在退出时会被安全地回收。libc 在内部跟踪此过程。如果您的程序另外使用一些 AmigaOS API,它通常会安装退出处理程序(我不记得是如何安装的),或者通过重新定义 __chkabort() 函数来禁用 Ctrl-C 检查。
您必须在 AROS(和 AmigaOS)上显式检查它。这样做的原因是,在 AmigaOS 及其派生系统上,没有安全的方法让操作系统杀死应用程序并回收所有资源(因为应用程序可以将内存和其他资源“移交给”其他任务)。
这是 SetSignal 自动文档中的一个示例。
#include <libraries/dos.h> /* Check & clear CTRL_C signal */ if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) { printf("CTRL-C pressed!n"); }
它依赖于编译器。最好只执行基于 SetSignal() 的检查。
如果您需要共享库,建议获取 linux-hosted AROS 构建(使用 gimmearos.sh 脚本),然后查看 AROS/workbench/libs 中的其他库源代码,了解如何实现。
如果它只是一个链接库,你可以用 -fno-stack-protector 编译 .c 文件(在 Linux 下的 aros-sdk 交叉编译器下需要,原生 aros gcc 可能不需要),等等,然后用 ar 将 .o 文件合并到 lib-yournamehere.a 文件中,并用 ranlib 处理它们。
SDL_image 可能需要 -ljpeg -lpng -lz
SDL_mixer 需要 -lSDL_mixer -lvorbisfile -lvorbis -logg(按此顺序)
在 AROS 下测试 SDL 声音的第一件事是增加缓冲区。所有应用程序都需要这样做才能获得良好的声音输出。
在大多数情况下,这肯定意味着您必须增加 SYSSND_MIXSAMPLES 的值。通常将此值乘以 2 或 4 会得到良好的结果。
您还应该检查获得的结构的值。无法确定 AROS 是否支持 AUDIO_U8,您可能已恢复为 AUDIO_U16。在这种情况下,声音当然会失真。
来自 这里
使用来自 这里 的代码进行进一步的缓冲区测试,这是我记录的结果
"快速测试使用 1024、2048 或 4096 编译得到了有趣的结果:1024 - 声音对按键事件的响应更快,但如果您快速移动屏幕上的“游戏窗口”,您会听到声音故障。2048 - 没有注意到响应性的很大差异,现在没有移动窗口时的故障,无论如何 fx-声音样本播放时有一些嘶嘶声-咔哒声故障。4096 - 没有嘶嘶声-咔哒声和移动窗口时的故障,但您可以看到响应性降低了。
然后使用原始的 xRick 8 位样本尝试此代码可以获得良好的声音效果,即使使用 1024 字节缓冲区,在移动窗口时声音也不会出现故障"
在我看来,缓冲区很大程度上取决于您需要的响应性、整体游戏负载以及您使用的音频样本类型(当然,位编码和频率越低,缓冲区可以使用越小)。
SDL_GetTicks 只需禁用
m_fLastTime = float(SDL_GetTicks())/1000;
在 sdlapp.cpp 的两个地方并添加您自己的代码在末尾
Ellapsed_Time = SDL_GetTicks() - Last_Time; if (Ellapsed_Time < 20) /* 20 ms target => 50FPS */ { SDL_Delay(20 - Ellapsed_Time); }
也许 SDL_GetTicks 在 aros 的 SDL 中由于某些原因工作方式略有错误?(因为如果相同的代码在 os4/mos/win32/其他任何东西上运行速度很快),那么这意味着 SDL_GetTicks 有问题,然后.. PS:SDL_GetTicks() 没有造成任何麻烦,它是一个基本 SDL 函数,几乎所有 SDL 应用程序都使用它。
int CSDLApplication::Run() in sdlapp.cpp
和
bool CMySDLApplication::FrameMove() in Armygaem.cpp
在初始代码中,Render3DEnvironment 持续被调用,并且只有 FrameMove 以 50fps 更新,即使没有任何移动,也会调用 Render() 和 SDL_GL_SwapBuffers()。在我看来,过频繁地调用 render() 函数和 SDL_GL_SwapBuffers() 是根本原因。对 OpenGL 实现的更正仅仅是为了防止愚蠢的应用程序崩溃或减慢系统速度。
退出时崩溃肯定是由于应用程序在退出之前没有释放任何资源造成的。
AROS 模块中的代码应该以一种使其适合嵌入到 ROM、FlashRAM 或其他类型的只读存储器中的方式编写。以下编码风格规则旨在使之成为可能。当然,它们适用于所有 Kickstart 模块以及可能驻留、共享或链接到其他模块的代码。
ROM 模块不得具有 .data 和 .bss 部分。基本上,我们需要摆脱所有非 const 全局数据。真正的 Amiga Kickstart 证明了实现这一点既可能又容易。如果您遇到一个由代码修改的外部变量(静态或非静态),请尝试摆脱它或将其移动到库/设备的基础(或处理程序的设备节点或类的用户数据中)。
以上内容也适用于库基础。如果您正在编写库,请将其他库的基础放入您自己的库基础结构中。Boopsi 类可以在其类私有数据中存储库基础。
尝试为所有全局数据设置 static 和 const 属性。您还可以使用在 <exec/types.h> 中定义的 CONST_STRPTR 和 CONST_APTR 类型。使用 static const 允许编译器将数据移动到 .text(又名代码)段。如果您需要将这些全局变量传递给另一个函数,请尝试将其原型更改为也使用 const。
钩子是您编写的自定义函数,以便能够处理从拦截主代码中产生的特定情况(例如处理消息)。该函数必须设计为接受三个参数,其顺序和类型已给出。
- 第一个参数 (A0) 包含指向您的钩子的指针,而不是指向您的窗口
- 第二个参数指向导致此操作的对象,这不是您的窗口,而是被按下对象(始终是连接到钩子 (=DoMethod 的第一个参数) 的对象)
- 然后为 MUIM_CallHook 提供 5 作为参数数量,但为 4 (=Count 参数后 DoMethod 中所有参数的数量)
AROS_UFH3S ( void, MyHookFunction, AROS_UFHA(struct Hook * , hook, A0), AROS_UFHA(Object * , obj, A2), AROS_UFHA(ULONG * , params, A1) )
params 是一个数组,但 IPTR 应该是正确的。然后您可以访问您的参数...
app = (Object *) *params++; window2 = (Object *) params++;
The important thing about hook functions is that the parameters must be given in the order A0, A2, A1. And not to leave out parameters even if they are unused by the hook function. For initial quick&dirty ports one can even simply defines things like "__saveds", "__asm", "__regargs", "__stdargs", "register ..." to nothing. For library functions it's the same (with library base as last param). InitLib: libbase(d0), seglist(a0), sysbase(a6) OpenLib: version(d0), libbase(a6) CloseLib: libbase(a6) ExpungeLib: libbase(d0), libbase(a6) OpenDev: ioreq(A1), unitnum(d0), flags(d1), devbase(a6) CloseDev: ioreq(a1), devbase(a6)
参见 这里
AROS 的 asm 调用和 lib 调用宏需要将参数类型(如“struct Hook *”)和参数(如“myhook”)传递到两个不同的参数中。而不是单个参数中。
转换很容易。添加一些“AROS_”前缀以及一些逗号。此外,在钩子函数和调度程序函数中必须使用“HOOK_INIT”/“HOOK_EXIT”/“DISPATCHER_INIT”/“DISPATCHER_EXIT”(如果 AROS 映射到 AROS_USERFUNC_INIT/AROS_USERFUNC_EXIT)。
强制过程参数在 GCC 中使用寄存器(如 a0)
由于某些机器(如 68k 或 x86)上的 C 调用约定意味着参数通过堆栈传递,因此您的 C 函数必须按正确的顺序(Hook、object、msg)排列参数,并且如果函数未使用参数,则不要省略参数,尤其是在它是中间参数 (object) 时。
ULONG hook_function(REG(a0, struct Hook *hook), REG(a2, APTR object), REG(a1, APTR message))
简而言之,当使用 HookEntry 时,您会像这样初始化钩子
STATIC ULONG hookfunc(struct Hook *hook, APTR obj, APTR msg) { /* ... *// } #if defined(__amigaos4__) hook->h_Entry = hookfunc; #else hook->h_Entry = &HookEntry; hook->h_SubEntry = hookfunc #endif
如果您不使用 SDI 头文件,这是适用于 OS3、OS4、AROS 和 MorphOS 以及每个编译器和架构的最通用的方法。
这些调度程序通常作为 MUI_CreateCustomClass() 的参数传递,它具有
#if defined(__MAXON__) || defined(__amigaos4__) cl->cl_Dispatcher.h_Entry = (HOOKFUNC)dispatcher; #else cl->cl_Dispatcher.h_Entry = (HOOKFUNC)metaDispatcher; cl->cl_Dispatcher.h_SubEntry = (HOOKFUNC)dispatcher; #endif
metaDispatcher
#ifdef __AROS__ AROS_UFH3(IPTR, metaDispatcher, AROS_UFHA(struct IClass *, cl, A0), AROS_UFHA(Object *, obj, A2), AROS_UFHA(Msg , msg, A1)) { AROS_USERFUNC_INIT return AROS_UFC4(IPTR, cl->cl_Dispatcher.h_SubEntry, AROS_UFPA(Class *, cl, A0), AROS_UFPA(Object *, obj, A2), AROS_UFPA(Msg , msg, A1), AROS_UFPA(APTR , cl->cl_Dispatcher.h_Data, A6) ); AROS_USERFUNC_EXIT }
让我困惑的是,我们自己的宏有寄存器
#define BOOPSI_DISPATCHER(rettype,name,cl,obj,msg) \ AROS_UFH3(SAVEDS rettype, name,\ AROS_UFHA(Class *, cl, A0),\ AROS_UFHA(Object *, obj, A2),\ AROS_UFHA(Msg , msg, A1)) {AROS_USERFUNC_INIT
在涉及调度程序时,MUI 和 BOOPSI 之间可能存在差异,并且 SDI DISPATCHER 只能用于 MUI。
AROS 的 MUI_CreateCustomClass() 将调度程序移动到 h_SubEntry 并使用类似于 HookEntry 的东西作为 h_Entry。在那里,我们不必关心寄存器。
顺便说一句:SDI 的钩子宏对于 AROS 来说是错误的。
HOOKPROTONHNO(TestFunc, void, int *param) { puts("Foobar"); } MakeHook(TestHook, TestFunc);
扩展到
static void TestFunc(__attribute__((unused)) struct Hook *_hook, __attribute__((unused)) APTR _obj, int *param) { puts("Foobar"); } struct Hook TestHook = {{0L, 0L}, (HOOKFUNC)TestFunc, NULL, 0L};
这只在 i386-AROS 上偶然起作用(因为堆栈参数)。但我知道如何修复它,并将很快向您发送更新。
#elif __AROS__ #define MakeHook(hookname, funcname) struct Hook hookname = {{NULL, NULL}, \ (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, NULL} #define MakeHookWithData(hookname, funcname, data) struct Hook hookname = \ {{NULL, NULL}, (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, (APTR)data} #define MakeStaticHook(hookname, funcname) static struct Hook hookname = \ {{NULL, NULL}, (HOOKFUNC)HookEntry, (HOOKFUNC)funcname, NULL} #define ENTRY(func) (APTR)func #define DISPATCHERPROTO(name) SAVEDS ASM IPTR name(REG(a0, \ struct IClass * cl), REG(a2, Object * obj), REG(a1, Msg msg)) #define DISPATCHER(name) DISPATCHERPROTO(name) #define SDISPATCHER(name) static DISPATCHERPROTO(name)
不同之处在于 funcname 被移动到 h_SubEntry。问题是调度程序宏。它们目前只能与 MUI_CreateCustomClass() 一起使用。如果我像我们的 BOOPSI 宏一样定义它们,我就会遇到一个新问题:如果我使用寄存器宏定义一个函数会发生什么
- 并*在 h_Entry 中使用 HookEntry,在 h_SubEntry 中使用函数?
顺便说一句:在 SDI_compiler.h 中有
/* we have to distinguish between AmigaOS4 and MorphOS */ #if defined(_M68000) || defined(__M68000) || defined(__mc68000) #define REG(reg,arg) arg __asm(#reg) #define LREG(reg,arg) register REG(reg,arg) #else #define REG(reg,arg) arg #define SAVEDS
C++ 在类型方面比 C 严格得多,这是问题的根源。绝对所有内容都应该进行强制转换,根本不允许隐式转换。PS 而且强制转换被认为是一种非常糟糕的编码风格,据我所知……
那些希望用 C++ 开发 AROS API 的人应该从当前的 SDK 更新他们的头文件。
HOOKFUNC 现在在 include/utility/hooks.h 中是这样的
typedef IPTR (*HOOKFUNC)();
原型已包含在“extern C”块中,因此此类问题应该消失了
简单地说……通过指针进行强制转换,不好……通过联合进行强制转换,好*。(*例外情况适用)希望有人能纠正我是否错了,但避免这些问题的经验法则是,在同一个函数中不要有两个指向同一内存但类型不同的指针变量。
实际上,这比这要微妙一些。它们可以指向不同的类型,但不能在类型不包含其他类型的子集时。
例如
struct Foo { struct MinNode Node; };
- 从 struct Foo * 到 struct MinNode * 的任何强制转换都可以……但是
struct Foo { struct Foo *next; struct Foo *prev; };
- 现在从“foo”到“minnode”的强制转换是不行的……更糟糕的是,可以静默丢弃(我不知道这怎么会被认为是礼貌的行为)。(并且由此,从 List 到 Node 的强制转换完全不行)。
我认为这实际上是一种不同的语言——它不再是“C”,因此,尽管规范(据我所知)确实指定了这一点,但直到现在它才以这种方式实现。它旨在提供额外的优化机会……尽管整个“我们将静默丢弃原本非常明显的代码”的做法相当糟糕。
CellPerformance 的内容确实概括了所有内容。尽管我发现它有点荒谬,您可以通过联合强制转换几乎任何东西,而且它“可以”,但使用语言“强制转换”完全相同的物理操作就变得“非法”了。
绝不要触碰用户作为“输入”参数传入的缓冲区。输入参数的概念通常隐含在函数描述中。例如,传递给 Open() 的文件名显然是一个输入变量,Open() 绝不能修改它,即使它稍后要修复它。请记住,缓冲区可能位于只读存储器中或在驻留程序或多线程程序的多个实例之间共享。
如果可以的话,尽量避免使用像 malloc() 和 free() 这样的主机操作系统调用,而使用 AllocMem() 和 FreeMem()。这是因为指针检查调试宏依赖于通过 TypeOfMem() 在 Exec 内存块中找到指针。
SA_BackFill, (ULONG) &sbackfillhook,
请不要在代码中使用 ULONG 来存储/转换指针。在适当的地方使用 APTR/IPTR。
make stub make make install
并且需要从这里内部获取 genmodule。
尝试使用普通的 Makefile 构建Ignition的支持模块
如何消除这些链接器警告?U __includelibrarieshandling 和 U __this_program_requires_symbol_sets_handling
以这种方式创建模块时,是否需要注意什么?(过去我一直使用构建系统)生成的模块中是否必须有第一个函数?
您是否直接使用 ld?如果是这样,请不要这样做,而是使用编译器的驱动程序(即 gcc)来执行所有步骤,包括最终链接。出现问题的原因是链接器需要通过一个包装器调用,在我们的例子中,该包装器称为 collect-aros(在其他系统上将是 collect2)。您可以用 collect-aros 代替 ld(我不建议这样做),或者如上所述使用编译器的驱动程序(gcc)。嗯,在我第一次回复时没有注意到 Makefile,并且我忘记了这些符号实际上是由 collect-aros 本身生成的。
出现问题的原因是您使用了 -nostartfiles,这避免了与启动文件链接,但启动文件包含处理自动库打开/关闭和通用符号集处理的代码。通过使用 DFLAGS=-lgraphics -lintuition -lutility,您实际上正在链接需要实现共享库自动处理的存根库。要么避免使用这些存根,要么自己实现所需的代码。您可以从正常的启动代码中获得灵感。
重新启用类似以下的行之后
#define UtilityBase cb->UtilityBase
我能够在没有存根库的情况下构建模块。
请参阅此处的教程
SDL/MesaGL/OpenGL 游戏框架。 Jumpcore Minimal