跳轉至內容

Aros/開發者/軟體移植

來自Wikibooks,開放世界中的開放書籍
Aros維基百科的導航欄
Aros使用者
Aros使用者文件
Aros使用者常見問題解答
Aros使用者應用程式
Aros使用者DOS Shell
Aros/使用者/AmigaLegacy
Aros開發文件
Aros開發者文件
從AmigaOS/SDL移植軟體
Zune初學者
Zune .MUI類
SDL初學者
Aros開發者構建系統
特定平臺
Aros x86完整系統HCL
Aros x86音訊/影片支援
Aros x86網路支援
Aros Intel AMD x86安裝
Aros儲存支援IDE SATA等
Aros Poseidon USB支援
x86-64支援
摩托羅拉68k Amiga支援
Linux和FreeBSD支援
Windows Mingw和MacOSX支援
Android支援
Arm Raspberry Pi支援
PPC Power Architecture
其他
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

使用CONFIGURE建立Makefile

[編輯 | 編輯原始碼]

開啟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,但如果它不起作用,請檢視下面的提示部分

編輯CONFIGURE以適應AROS

[編輯 | 編輯原始碼]

首先檢視Fishy的教程first

dir ../ 向上移動一個或兩個目錄

dir / Amiga等效項

建立Makefile後,在unix shell中,輸入

make -f Makefile

建立程式…

從空白文字檔案建立MAKEFILE

[編輯 | 編輯原始碼]

通用模板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!"

更好的Makefile

[編輯 | 編輯原始碼]

只需使用適合您的那個。

#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    );
  1. 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

GUI 工具包

[編輯 | 編輯原始碼]

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 選項。]

C/C++ 編譯器

[編輯 | 編輯原始碼]

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 Lattice C 編譯器
[編輯 | 編輯原始碼]

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 構建這些,您將一切順利。

Maxon Hisoft C
[編輯 | 編輯原始碼]
  • RAWKEY:替換為 IDCMP_RAWKEY
  • ModifyIDCMP(win,FLAGSON) 替換為?

彙編程式/反彙編程式

[編輯 | 編輯原始碼]

ADis,它將二進位制檔案逐塊讀取到記憶體中以反彙編它們,然後將其視為一個短整型陣列。正確的做法是將其視為 char *,並執行 (arr[0] << 8) + arr[1]。我想用它來交叉反彙編 M68k 程式,但放棄了,轉而使用 Ira,因為它非常普遍。

Linux 控制檯應用程式

[編輯 | 編輯原始碼]

在 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 實現的更正僅僅是為了防止愚蠢的應用程式崩潰或減慢系統速度。

退出時崩潰肯定是由於應用程式在退出之前沒有釋放任何資源造成的。

編寫可 ROM 化的程式碼

[編輯 | 編輯原始碼]

AROS 模組中的程式碼應該以一種使其適合嵌入到 ROM、FlashRAM 或其他型別的只讀儲存器中的方式編寫。以下編碼風格規則旨在使之成為可能。當然,它們適用於所有 Kickstart 模組以及可能駐留、共享或連結到其他模組的程式碼。

ROM 模組不得具有 .data 和 .bss 部分。基本上,我們需要擺脫所有非 const 全域性資料。真正的 Amiga Kickstart 證明了實現這一點既可能又容易。如果您遇到一個由程式碼修改的外部變數(靜態或非靜態),請嘗試擺脫它或將其移動到庫/裝置的基礎(或處理程式的裝置節點或類的使用者資料中)。

以上內容也適用於庫基礎。如果您正在編寫庫,請將其他庫的基礎放入您自己的庫基礎結構中。Boopsi 類可以在其類私有資料中儲存庫基礎。

嘗試為所有全域性資料設定 static 和 const 屬性。您還可以使用在 <exec/types.h> 中定義的 CONST_STRPTR 和 CONST_APTR 型別。使用 static const 允許編譯器將資料移動到 .text(又名程式碼)段。如果您需要將這些全域性變數傳遞給另一個函式,請嘗試將其原型更改為也使用 const。

鉤子和 SDI

[編輯 | 編輯原始碼]

鉤子是您編寫的自定義函式,以便能夠處理從攔截主程式碼中產生的特定情況(例如處理訊息)。該函式必須設計為接受三個引數,其順序和型別已給出。

  • 第一個引數 (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。

無需使用構建系統編譯 AROS 原始碼的部分內容

[編輯 | 編輯原始碼]

來自

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

教程

Amiga俄羅斯方塊

Irrlicht 3D 引擎

華夏公益教科書