eXec.plMAGAZYN UŻYTKOWNIKÓW KOMPUTERÓW AMIGA
MAGAZYN UŻYTKOWNIKÓW KOMPUTERÓW AMIGA

środa, 21. listopada, 2018, 20:50

Dodano: 2014-01-12, Autor: Spot (tłumaczenie - Konrad Rojek), Kategoria: Publicystyka, Liczba wyświetleń: 2845

A A A

Spota kurs programowania dla początkujących, cz. 3

Część 1

  1. Po co mam to czytać? Przecież nie potrafię programować!
  2. Co portować?
  3. Dostęp do aktualnego SDK
  4. Podstawy
  5. Konfigurowanie środowiska
  6. Konfigurowanie cross-kompilatora
  7. Błędy konfigurowania środowiska
  8. Wyjaśnienie komunikatów o błędach

Część 2

  1. Naprawianie błędów
  2. Błędy linkowania?
  3. Konwersja ścieżek unixowych do amigowych
  4. Problemy 'LValue'
  5. Obsługa właściwej kolejności bajtów (ENDIAN)
  6. Definicje
  7. Sztuczki i kruczki

Część 3

  1. Konwersja windowsowego makefile na amigowy
  2. Naprawianie źródeł
  3. Sprawdzanie obecności bibliotek
  4. Tworzenie GUI w oparciu o Emperor (ALPHA!)
  5. Kompilowanie aplikacji SDL/GL
  6. Dodawanie muzyki do aplikacji SDL
  7. POMÓŻ MI!
  8. Kontakt
  9. Podziękowania
  10. SPOTa Wyzwanie Portowania
  11. WIP

Konwersja windowsowego makefile na amigowy

Gra którą chcesz skompilować, np. napisaną pod bibliotekę Allegro, często dostarczana jest z plikiem makefile opracowanym dla systemu Windows. Oczywiście wersja AmigOS nie jest dostępna. Utworzenie go jest zadaniem dla osoby portującej program.

Poprowadzę was teraz, krok po kroku, w procesie przekształcania windowsowego pliku 'makefile'. Na potrzeby przykładu wykorzystana została gra o nazwie 'Pikzels'. Chętni mogą ją pobrać z: http://www.allegro.cc/files/depot/505/PikselzFinal.zip. Po rozpakowaniu należy otworzyć w edytorze tekstu plik: 'pikselzfinal/source/makefile.win'.

Warto zwrócić uwagę, że wykorzystuje on windowsowy sposób oznaczania końca linii. W efekcie co druga linia jest pusta, a plik mniej czytelny. Stan ten można łatwo naprawić za pomocą CED, poprzez zaznaczenie wszystkiego i funkcję 'Strip CR marked' w menu 'Cut/Paste'. Teraz obróbka pliku powinna być o wiele prostsza.

Na początku warto zwrócić uwagę na dwie linie:

 CPP  = g++.exe
 CC   = gcc.exe

Konieczne jest usunięcie windows'owych rozszerzeń nazw, w ten sposób:

 CPP  = g++ 
 CC   = gcc 

Skrypt odnajdzie już GCC. W kolejnych dwóch liniach:

 WINDRES = windres.exe
 RES  = ../Obj/ErkleLnD_private.res

Nie wiem za co odpowiada windres, prawdopodobnie jest związany z windowsowym środowiskiem. Nie jest tu potrzebny. Obie linie są do usunięcia.

W kolejnej linii:

 OBJ  = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o $(RES)

Zwróćcie uwagę na symbol $(RES) na końcu. Próbuje dodać parametry z linii "RES = ../Obj/ErkleLnD_private.res", którą usunęliśmy. To niezbyt dobrze. Trzeba teraz usunąć $(RES) z tej linii oraz każdej innej, w której występuje. W tym przypadku będą to linie: 6 I 7.

Kolejne dwie linie przyjmą więc następującą postać:

OBJ  = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o
 LINKOBJ  = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o

W kolejnej:

LIBS =  -L"lib" -lalleg -mwindows –lalleg

W tym miejscu wymienione są wykorzystywane biblioteki. Część z nich nie jest potrzebna. Do usunięcia są '-mwindows' oraz "lib". By uprościć sobie życie, zazwyczaj automatycznie wykorzystuję deklarację, którą wkleiłem poniżej ten poradnik. Zawiera one wszystkie biblioteki zawarte w allegro. Te niepotrzebne nie będą po prostu wykorzystywane. Oto ta linia:

 LIBS = -lalmp3 -laldumb -lalfont -lfblend -lalagup -lallegro -lpthread -lstdc++ -lauto –lunix

Tak jak napisałem powyżej, większość z nich nie jest potrzebna. Nie ma to jednak znaczenia, GCC zignoruje je.

W kolejnych dwóch liniach:

 INCS =  -I"include"  -I"../include" 
 CXXINCS =  -I"lib/gcc-lib/mingw32/3.3.1/include"  -I"include/c++/3.3.1/backward"  -I"include/c++/3.3.1/mingw32"  -I"include/c++/3.3.1"  -I"include"  -I"H:/Common/Include"  -I"H:/Libs/Lua/include"  -I"../include" 

Powyższe deklaracje mówią GCC gdzie szukać plików nagłówkowych, potrzebnych dla bibliotek wpisanych w 'LIBS'. Nagłówki w 'INCS =' są związane z projektem i są potrzebne. Te kolejne są związane z systemem Windows, nie są potrzebne.
Gra jest projektem allegro, trzeba więc wskazać pliki nagłówkowe tej biblioteki:

INCS    = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include"  -I"../include" 
 CXXINCS = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include"  -I"../include" 

Ścieżkę 'include' umieszczam zazwyczaj w obu liniach, by mieć pewność, że kompilator ich nie zignoruje.

W kolejnej linii:

 BIN      = ../ErkleLnD.exe

Windowsowa ścieżka zostanie zamieniona na amigową:

BIN      = ErkleLnD.exe 

Tak samo jak tutaj:

 all: all-before ../ErkleLnD.exe all-after
	 $(CPP) $(LINKOBJ) -o "ErkleLnD.exe" $(LIBS)

powinny wyglądać następująco:

 (Line 16) all: all-before ErkleLnD.exe all-after
 (Line 23)	$(CPP) $(LINKOBJ) -o ErkleLnD.exe $(LIBS)

Flagi wyglądają teraz poprawnie. Na tym etapie zazwyczaj wyszukuję w 'makefile' wystąpienia 'RES' by upewnić się, że któreś nie zostało pominięte. Przeszukajcie sami. Na końcu pliku znajdują się jeszcze dwie takie linie:

 ../Obj/ErkleLnD_private.res: ErkleLnD_private.rc 
	 $(WINDRES) -i ErkleLnD_private.rc --input-format=rc -o ../Obj/ErkleLnD_private.res -O coff 

Związane są one tylko i wyłącznie z WINDRES, można je kompletnie usunąć. Po zmianach plik można zapisać jako 'makefile.aos4'. Moją wersję oczyściłem dodatkowo pod kątem czytelności, powinniście jednak uzyskać efekt zbliżony do:

 # Project: ErkleLnD
 # Makefile created by Dev-C++ 4.9.9.2

 CPP      = g++ 
 CC       = gcc 
 OBJ      = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o 
 LINKOBJ  = ../Obj/Main.o ../Obj/erkMap.o ../Obj/erkTile.o ../Obj/erkTileType.o ../Obj/erkBmpGen.o ../Obj/erkUnit.o ../Obj/erkTTHive.o ../Obj/erkTTTrainer.o ../Obj/erkCommand.o ../Obj/erkCmdGo.o ../Obj/erkCmdClear.o ../Obj/erkCmdTrainer.o ../Obj/erkCmdHive.o ../Obj/erkTTThorns.o ../Obj/erkCmdThorns.o ../Obj/erkAI.o 
 LIBS     = -lalmp3 -laldumb -lalfont -lalfblend -lalagup -lallegro -lpthread -lstdc++ -lauto -lunix
 INCS     = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include"  -I"../include" 
 CXXINCS  = -I/sdk/local/newlib/include/allegro -I/sdk/local/newlib/include/ -I/sdk/local/common/include/ -I"include"  -I"../include" 
 BIN      = /ErkleLnD.exe
 CXXFLAGS = $(CXXINCS) -DALLEGRO_GUESS_INTTYPES_OK -fexpensive-optimizations -O3
 CFLAGS   = $(INCS) -DALLEGRO_GUESS_INTTYPES_OK -fexpensive-optimizations -O3
 RM       = rm -f

 .PHONY: all all-before all-after clean clean-custom

 all: all-before ErkleLnD.exe all-after


 clean: clean-custom
	 ${RM} $(OBJ) $(BIN)

 $(BIN): $(OBJ)
 	$(CPP) $(LINKOBJ) -o ErkleLnD.exe $(LIBS)

 ../Obj/Main.o: Main.cpp ../include/erkTypes.h ../include/erkMap.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h ../include/erkBmpGen.h
 	$(CPP) -c Main.cpp -o ../Obj/Main.o $(CXXFLAGS)

 ../Obj/erkMap.o: erkMap.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
 	$(CPP) -c erkMap.cpp -o ../Obj/erkMap.o $(CXXFLAGS)

 ../Obj/erkTile.o: erkTile.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
 	$(CPP) -c erkTile.cpp -o ../Obj/erkTile.o $(CXXFLAGS)

 ../Obj/erkTileType.o: erkTileType.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h ../include/erkBmpGen.h
	$(CPP) -c erkTileType.cpp -o ../Obj/erkTileType.o $(CXXFLAGS)

 ../Obj/erkBmpGen.o: erkBmpGen.cpp ../include/erkBmpGen.h ../include/erkTypes.h
	$(CPP) -c erkBmpGen.cpp -o ../Obj/erkBmpGen.o $(CXXFLAGS)

 ../Obj/erkUnit.o: erkUnit.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkUnit.cpp -o ../Obj/erkUnit.o $(CXXFLAGS)

 ../Obj/erkTTHive.o: erkTTHive.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkTTHive.cpp -o ../Obj/erkTTHive.o $(CXXFLAGS)

 ../Obj/erkTTTrainer.o: erkTTTrainer.cpp ../include/erkMap.h   ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h   ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkTTTrainer.cpp -o ../Obj/erkTTTrainer.o $(CXXFLAGS)

 ../Obj/erkCommand.o: erkCommand.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkCommand.cpp -o ../Obj/erkCommand.o $(CXXFLAGS)

 ../Obj/erkCmdGo.o: erkCmdGo.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkCmdGo.cpp -o ../Obj/erkCmdGo.o $(CXXFLAGS)

 ../Obj/erkCmdClear.o: erkCmdClear.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkCmdClear.cpp -o ../Obj/erkCmdClear.o $(CXXFLAGS)

 ../Obj/erkCmdTrainer.o: erkCmdTrainer.cpp ../include/erkMap.h   ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h   ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkCmdTrainer.cpp -o ../Obj/erkCmdTrainer.o $(CXXFLAGS)

 ../Obj/erkCmdHive.o: erkCmdHive.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkCmdHive.cpp -o ../Obj/erkCmdHive.o $(CXXFLAGS)

 ../Obj/erkTTThorns.o: erkTTThorns.cpp ../include/erkMap.h ../include/erkTypes.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkTTThorns.cpp -o ../Obj/erkTTThorns.o $(CXXFLAGS)

 ../Obj/erkCmdThorns.o: erkCmdThorns.cpp ../include/erkMap.h   ../include/erkTypes.h ../include/erkUnit.h ../include/erkCommand.h   ../include/erkTile.h ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h
	$(CPP) -c erkCmdThorns.cpp -o ../Obj/erkCmdThorns.o $(CXXFLAGS)

 ../Obj/erkAI.o: erkAI.cpp ../include/erkTypes.h ../include/erkMap.h   ../include/erkUnit.h ../include/erkCommand.h ../include/erkTile.h   ../include/erkTTHive.h ../include/erkTTTrainer.h   ../include/erkTTThorns.h ../include/erkBmpGen.h
	$(CPP) -c erkAI.cpp -o ../Obj/erkAI.o $(CXXFLAGS)

Naprawianie źródeł

Najwyższa pora zbudować grę. Niestety kod źródłowy wymaga pewnych zmian i z marszu nie da się przejść tego procesu bez wprowadzenia zmian. Wiecie już jednak jak przekonwertować windowsowy 'makefile' w amigowy, warto więc wypróbować na innych aplikacjach Allegro/grach SDL/narzędziach. Po nabraniu wprawy cały ten proces zajmuje co najwyżej minutę. Nie jest czasochłonny i wygląda właśnie tak, jak został przedstawiony w tym samouczku.

Jeśli wciąż chcecie zbudować tę grę, oto rozwiązania problemów. Użyłem Google dla błędu, który od razu wystąpił (error: '::main' must return 'int') i znalazłem następująca stronę: http://www.linuxforums.org/forum/linux-programming-scripting/33421-main-must-return-int.html

Jedna z odpowiedzi mówi:
Don't write 'void main' write 'int main'.

Wspaniale! W linii 29 pliku main.cpp zamieniłem 'void main()' na 'int main()' i to pomogło. Pozostał mi teraz prosty błąd:

 error: winalleg.h: No such file or directory

Ta gra została napisana z myślą o Windows, przez co próbuje wykorzystać specyficzny dla windowsowej wersji nagłówek. Należy tę dyrektywę usunąć ze wszystkich plików .cpp. Pliki te dołączają już allegro.h, więcej nie potrzeba.

Po tych operacjach gra się skompiluje i zlinkuje. Skopiujcie plik 'ErkleLnD.exe' do 'pikselzfinal/' i uruchomcie.

I klops. Gra zawiesiła się po wywołaniu. Zablokowała również kursor myszy. Snoopy nie przekazał żadnej użytecznej informacji, a z zablokowaną myszą nie ma jak sprawdzić ślad stosu z addr2line. Niestety tu kończy się moja wiedza. Będę próbował skompilować inny program, a wy?

Sprawdzanie obecności bibliotek

Przedstawiony kod to funkcja, która otwiera wskazaną bibliotekę, sprawdza wersję/rewizję, a następnie ją zamyka. Przez sprawdzenie zwracanej wartości weryfikowane jest czy biblioteka spełnia wymagane kryteria. Ten test powinien być włączony do kodu tak wcześnie, jak tylko możliwe, by zminimalizować ryzyko dostępu do niezweryfikowanej biblioteki. Najlepszym podejściem jest włączyć poniższy kod do źródeł i wywołać na początku 'main()'. Jeśli zwrócone zostanie 'FALSE', program powinien się zakończyć poprzez 'RETURN FAIL'.

 #ifdef __amigaos4__
 #include <dos/dos.h>
 #include <proto/exec.h>
 BOOL LibraryOK( STRPTR libname, ULONG version, ULONG revision )
  {
      struct Library *libBase;
      BOOL ok = FALSE;
      if( libBase = (struct Library *)IExec->OpenLibrary( libname, version ))
      {
      if (libBase->lib_Version > version || (libBase->lib_Version == version && libBase->lib_Revision >=revision))
        {
              ok =  TRUE;
          }
          IExec->CloseLibrary( libBase );
      }
      return ok;
  }
 #endif

Statyczne biblioteki wywołują współdzielone, systemowe samodzielnie. Powyższy test powinien być zastosowany w main() następująco:

 #ifdef __amigaos4__
      /* checking for MiniGL 2.0 */
 
      if(!LibraryOK( "minigl.library", 2, 0 ))
         {
         printf("I need MiniGL 2.0 Beta or newer. Please upgrade!\n");
          return RETURN_FAIL;
         }
#endif

Tworzenie GUI w oparciu o Emperor (ALPHA!)

Te sekcję samouczka należy traktować jako bardzo wczesną wersję (alpha). Jest nieprzetestowana i przekazał mi ją Ami603 poprzez #amigadev.

Otwórz projekt i przejdź do sekcji Variables (zmienne - przyp.) Otwórz okno 'edit' za pomocą przyciska o tej samej nazwie. Dodaj wskaźnik string (stringpointer) do pliku poleceń. Nie dodawaj żadnych wartości. Krok po kroku:


Przejdź do 'request page'

sekcja 'zmienne'

kliknij na 'edit'

wybierz 'stringpointer'

nazwij 'commandfile'

kliknij 'add'

Przejdź do strony 'reaction'.

Przejdź do strony 'requester'

Otwórz ponownie okno edycji, jeśli nie jest otwarte.

Wybierz 'errorrequest'.

Wpisz "Plik wykonywalny emulatora nie itnieje" (albo coś w tym stylu) jako BodyText i dodaj

Wybierz ponownie 'errorrequest'.

Wpisz "Wskazany plik nie istnieje." jako BodyText i dodaj.

Przejdź do strony 'reaction'.

Kliknij dwa razy na gadżecie 'getfile' (po lewej).

Zostanie otwarty editor tekstowy z funkcją o nazwie 'GetFileX_GadgetUP_evt.'

Wpisz kod pomiędzy nawiasy:

IIntuition->IDoMethod((Object *)gad[GID_Getfile1],GFILE_REQUEST,NULL,win[WID_Window1],NULL,TAG_DONE);
  	IIntuition->GetAttrs(gad[GID_Getfile1],GETFILE_FullFile,&commandfile,TAG_DONE);
 	IIntuition->RefreshGadgets(gad[GID_Getfile1],win[WID_Window1],NULL);

(Założenie: gadżet został nazwany GetFile1).

Zamknij edytor, kliknij dwa razy na przycisk 'launch'. Kolejna funkcja zostanie wyświetlona w tekstowym edytorze:'Button1_GadgetUP_Evt'. Wpisz kod:
BPTR executable,file;
 	STRPTR commandbuffer;
 	if (!(executable = IDOS->Lock("here_goes_The_emulator_cli_executable_name",ACCESS_READ)))
 	{
		// First requester below here
 	}
 	if (!(file = IDOS->Lock(commandfile,ACCESS_READ)))
 	{
		// Second requester below here
 	}
 	else if ((executable)&&(file))
 	{
 		commandbuffer = IUtility->ASPrintf("here_goes_the_emulator_cli_executable_name \"%s\"",commandfile);
 		if (IDOS->SystemTags(commandbuffer,
 					SYS_Input,	NULL,
 					SYS_Output,	NULL,
 					SYS_Asynch,	TRUE,
 					TAG_END)==-1)
 		{
 			IDOS->Printf("Commandline: %s failed\n",commandbuffer);
		}
 		IExec->FreeVec(commandbuffer);
 	}
	IDOS->UnLock(executable);
 	IDOS->UnLock(file);

Teraz, nie zamykając edytora tekstowego, należy przejść ponownie do strony 'requester', umieścić kursor poniżej "//first requester below here" i kliknąć dwa razy na ErrorRequester1. Tak samo z "//Second requester below here" i ErrorRequester2. Zamykamy editor, zapisujemy wszystko, wywołujemy: shell ->make.

Spróbuj zmienić 'your_command_cli_executable' na nazwę na nazwę własnego pliku exe w obydwu tej funkcji.

Możesz dodać trzeci komunikat z informacjami o programie, kolejny guzik i tak jak poprzednio: kliknąć dwa razy przycisk, wybrać funkcję, przejść do strony 'requesters' i ponownie kliknąć dwa razy.

Kompilowanie aplikacji SDL/GL

Dodaj flagi -lGL -lGLU -lglut do LDFLAGS .Ważne żeby były wymienione jako ostatnie.

W wersji AmigaOS 4.0 biblioteki SDL występuje pewien błąd. Otworzy ona zawsze tryb pełnoekranowy, mimo że część aplikacji deklaruje pracę w okienku. Jest to powszechne źródło problemów z aplikacjami GL rekompilowanymi dla OS4. Z tego powodu kod źródłowy wymaga pewnych zmian. Znajdź w źródłach 'SDL_SetVideoMode' i ustaw tam 'fullscreen'. Przykład:

Oryginał:

screen = SDL_SetVideoMode( 800, 600,24, SDL_OPENGL | SDL_HWSURFACE ); 

Po zmianie:

screen = SDL_SetVideoMode( 800, 600,24, SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN ); 

Dodawanie muzyki do aplikacji SDL

Wpisz PRZED funkcją main()

#include <SDL/SDL.h>
#include "SDL/SDL_mixer.h"

 Mix_Music *music = NULL;
 void musicDone();

Umieść na samym początku deklaracji funkcji main()

 //int main() {

  if(Mix_OpenAudio(44100, AUDIO_S16, 1, 4096)) { printf("Unable to open audio!\n"); exit(1); }

Wpisz w miejscu gdzie dźwięk powinien zacząć się odtwarzać:

 music = Mix_LoadMUS("mod.module");
 Mix_PlayMusic(music, -1);
 Mix_HookMusicFinished(musicDone);

Wpisz w miejscu, gdzie dźwięk powinien przestać grać:

 Mix_HaltMusic();
 Mix_FreeMusic(music);
 music = NULL;

Umieść na końcu pliku:

 void musicDone()
 {
   Mix_HaltMusic();
   Mix_FreeMusic(music);
   music = NULL;
 }

POMÓŻ MI!

Utworzyłem ten dokument głównie jako pomoc dla mnie w początkach nauki programowania. Ostatecznie okazał się być całkiem użyteczny, dlatego postanowiłem go oczyścić i udostępnić. Naprawdę liczę na pomoc w rozszerzeniu treści! Jeśli dostrzegłeś błąd, chciałbyś doprecyzować sekcję, albo dodać nową - dołącz do mojej misji. Kto wie co może się stać? Zalejemy os4depot wieloma nowymi plikami! Nie byłoby to złe, co nie?

Kontakt

Wyślij wiadomość na: spotup AT gmail DOT com Możesz też mnie znaleźć, tak jak i innych programistów, na kanale #amigadev w irc.amigaworld.net.

Podziękowania

Nie byłoby to możliwe bez pomocy

HNL_DK, NICOMEN, ITIX, ZEROHERO, VARTHALL, BLACKY_STARDUST, AMI603, RAZIEL, LIO AMIGAGUY, SSOLIE, RIGO, JOERG, MARQ/FIT, ORGIN I innych z #amigadev!

WIELKIE DZIĘKI LUDZISKA!

Specjalne dzieki dla:

Chrisa za napisanie specjalnego narzędzia wykorzystywanego przez installer I zaadaptowanie instalerra.
Rigo za dodanie wsparcia AmiUpdate i wykoanie skryptu instalacyjnego.
Masona za wykonanie ikon.
Slut Nancy / bAH za sekcję 'Dodanie muzyki do SDL App'
Blacky / Stardust za genialne i złożone rozwiązania.

      .___________________________________________________________.
      |                                                           |
      |              G U I D E   W R I T TE N   B Y               |
     ._______                                        .______.     |
     |  ____/________________________________________|      |__   .
   ._|____._         |      ._       |      ._       |       _/______.
   |      |/         |      |/       |      |/       |      |/       |
   |                 |      _________|               |               |
   |_________________|______|spt/up  |_______________|_______________| 
      .                                                           .
      |                                                           | 
      |      Jestem w kiepskiej sytuacji ekonomicznej,            | 
      |      jeśli uważasz, że to co robię                        |  
      |      jest warte czegokolwiek,                             | 
      |      możesz mnie wesprzeć przez paypal                    |   
      |      na mój email addy, spot AT triad DOT se, dzięki!     | 
      |                                                           | 
      |                    Spot / Up Rough 2008                   | 
      |___________________________________________________________|

SPOTa Wyzwanie Portowania

Spota Wyzwanie Portowania #1 wygrał Jabirulo! Gratulacje! Wspaniała robota! Portuj dalej!

"WIP"

bonusmanager.cpp: In constructor 'BonusManager::BonusManager(World*, unsigned int)':
bonusmanager.cpp:45: error: invalid conversion from 'int*' to 'Sint32*'
bonusmanager.cpp: In member function 'bool BonusManager::loadSettings(const char*)':
bonusmanager.cpp:124: error: invalid conversion from 'Sint32*' to 'const int*'
bonusmanager.cpp:124: error:   initializing argument 2 of 'bool WeightedRandom::setWeights(int, const int*)'

jak zdefiniowany jest ASSERT()?? Najprawdopodobniej jest w global.hpp

bool ASSERT( const bool test, const char* format, ... );

jako co jest zdefiniowany Sint32?? Może to być 'typedef'

bonusmanager.hpp:               Sint32           m_minDelay, m_maxDelay;
bonusmanager.hpp:               Sint32           m_delayCounter;
bonusmanager.hpp:               Sint32          *m_Limits;
bonusmanager.hpp:               Sint32          *m_numExisting;
bonusshield.hpp:                Sint32        m_protectionTime;

ok, spróbuję zmienić: 'Sint32 *m_Limits;' na 'int *m_Limits;' i zobaczę czy pierwszy bład zniknie

bonusmanager.cpp: In constructor 'BonusManager::BonusManager(World*, unsigned int)':
bonusmanager.cpp:51: error: invalid conversion from 'int*' to 'Sint32*'
bonusmanager.cpp: In member function 'virtual void BonusManager::serialize(Uint8*&) const':
bonusmanager.cpp:321: error: invalid conversion from 'int* const' to 'const long int*'
bonusmanager.cpp:321: error:   initializing argument 2 of 'static void Serialize::serialize(int, const T*, Uint8*&) [with T = long int]'
bonusmanager.cpp: In member function 'virtual void BonusManager::deserialize(Uint8*&)':
bonusmanager.cpp:346: error: invalid conversion from 'int*' to 'long int*'
bonusmanager.cpp:346: error:   initializing argument 3 of 'static void Serialize::deserialize(int, Uint8*&, T*) [with T = long int]'

Próba zmiany "m_numExisting = m_Limits + Bonus::getNumTypes();" na "m_numExisting = (Sint32 *)m_Limits + Bonus::getNumTypes();"

bonusmanager.cpp: In member function 'virtual void BonusManager::serialize(Uint8*&) const':

bonusmanager.cpp:322: error: invalid conversion from 'int* const' to 'const long int*'
bonusmanager.cpp:322: error:   initializing argument 2 of 'static void Serialize::serialize(int, const T*, Uint8*&) [with T = long int]'
bonusmanager.cpp: In member function 'virtual void BonusManager::deserialize(Uint8*&)':
bonusmanager.cpp:347: error: invalid conversion from 'int*' to 'long int*'
bonusmanager.cpp:347: error:   initializing argument 3 of 'static void Serialize::deserialize(int, Uint8*&, T*) [with T = long int]'

zmiana:

Serialize::serialize( Bonus::getNumTypes(), m_Limits, bufferPointer );

na:

Serialize::serialize( Bonus::getNumTypes(), (const long int*)m_Limits, bufferPointer );
bonusmanager.cpp: In member function 'virtual void BonusManager::deserialize(Uint8*&)':

bonusmanager.cpp:348: error: invalid conversion from 'int*' to 'long int*'
bonusmanager.cpp:348: error:   initializing argument 3 of 'static void Serialize::deserialize(int, Uint8*&, T*) [with T = long int]'

zmiana:

Serialize::deserialize( Bonus::getNumTypes(), bufferPointer,  m_Limits );
Serialize::deserialize( Bonus::getNumTypes(), bufferPointer,  (long int*)m_Limits );

Wyjaśnienie błędów: kompilator oczekiwał typu long int*, ale wyrył m_Limits jako coś innego. Możemy użyć rzutowania na właściwy dołączając (long int *) przed zmienną. W drugim przypadku oczekiwanym typem był “long int*”, więc ponownie zastosowane zostało rzutowanie.

==================================================================================================

void Random::seed() {
	seed(time(NULL)+getpid());

random.cc: In member function 'void el::Random::seed()':
random.cc:12: error: 'getpid' was not declared in this scope

seed() potrzebuje po prostu losowej liczby. Tutaj wykorzystuje aktualny czas oraz ID procesu. Usuńmy getpid():
“seed(time(NULL)+getpid());” stanie się “seed( time( NULL ));”

==================================================================================================

gcc -Wl,-rpath-link,/SDK/local/newlib/lib -use-dynld -o bevel bevels.o -lcairo -lauto 

==================================================================================================

Konwertuje statyczną bibliotekę we współdzieloną. Nie zapomnij dodać –fPIC

gcc -shared -Wl,--whole-archive libtimidity.a -Wl,--no-whole-archive -Wl,-soname,libtimidity.so -o libtimidity.so

Zamiennik dla termios.h

#ifndef __amigaos4__	/* Win32 doesn't have termios.h */
  struct termios term, termsave;

  tcgetattr(fileno(stdin), &termsave);
  term = termsave;
  term.c_lflag &= ~ (ECHO | ECHOE | ECHOK | ECHONL);
  tcsetattr(fileno(stdin), TCSANOW, &term);
#endif

#ifndef __amigaos4__	/* Win32 doesn't have termios.h */
      tcsetattr(fileno(stdin), TCSANOW, &termsave);
#endif

#ifndef __amigaos4__	/* Win32 doesn't have termios.h */
  tcsetattr(fileno(stdin), TCSANOW, &termsave);
#endif

SHRT_MAX and SHRT_MIN are not defined in newlib.
They should be defined if you include .
Spot (tłumaczenie - Konrad Rojek)
zobacz inne nasze artykuły »



AmigaOS.pl

Polecamy
Najpopularniejsze
eXec blog

Świat poza Amigą: