kategorie: ANSI C, Asembler, C++
[#1] Własna biblioteka mutlimedialna dla C dla klasyka
Czy sensowne byłoby stworzenie biblioteki graficznej dla C/C++, której wydajność byłaby znośna na klasyku (od A500 w górę)? Sens miałoby to wtedy, gdyby pełnoekranowe programy jej używające były szybsze w wykonywaniu operacji niż np. pisane w AMOSIe. Sama biblioteka musiałaby być pisana pewno w assemblerze. Super jeśli byłby pełny support dla ECS/AGA/RTG. SDL niestety za bardzo się ślimaczy na klasykach. Przydałoby się coś takiego moim zdaniem. W trybie ECS/AGA powinna być obsługa blittera/coopera/sprite/boby. Mile widziana obsługa warstw/przezroczystości/scroolowania/wykrywania kolizji obiektów. Z czasem możnaby dorzucić obsługę dźwięku, sieci, myszki/joy'a, mechanizmy uniezależniające prędkość gry od mocy CPU itp. Jeśli jeszcze powstałaby wersja dla różnych wersji CPU z FPU/MMU to też miodzio. Nie każdy zna i nie każdy może nauczyć się assemblera.

Słowem - odpowiednik tego co potrafi AMOS tylko w C/C++ i 2 razy szybszy w wykonywaniu kod.

Jak myślicie drodzy koledzy ma to sens? Pomogłoby to w pojawianiu się nowych gier dla klasyka?
[#2] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@pong777, post #1

Fajnie by bylo ale szansa na realizacje takiej biblioteki wynosi 0%.
Rzeczywistosc pokazala, ze praktycznie kazdy jezyk programowania wyzszego poziomu cierpi na wolna obsluge sprajtow, bobow i skrolingu. Skoro dotad nikomu sie nie udalo stworzyc szybkiej obslugi tych obiektow tzn. ze jest to niemozliwe.


W pojawianiu sie nowych gier na Amige pomoga tylko tutoriale w asmie dotyczace prawidlowej obslugi custom chipa, ktorych w jezyku polskim calkowity brak a w angielskim tez niewiele.
[#3] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@pong777, post #1

od tego jest wlasnie graphics.library, wykorzystuje sprity, boby, blittera, kolizje... ciezko o szybsza gdyz ona i tak juz wykorzystuje w pelni hardware amigi
[#4] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@pong777, post #1

A ja jestem zupełnie odmiennego zdania, niż koledzy powyżej. Taka biblioteka jak najbardziej jest możliwa, ja od dawna planuję napisanie takiej. Nawet jeśli ma to być do programów w C, to przecież można napisać taką bibliotekę w asemblerze.

Ważne: biblioteka tak napisana powinna komunikować się z systemem na wystarczająco niskim poziomie, najlepiej bezpośrednio korzystać z przerwań systemowych oraz blitować bezpośrednio do BitMapy (ew. własne procedury blitowania do RastPortu z uwzględnieniem Layerów (blokowanie) itp.

Boby z graphics.library mają jakiś feler, że nie działają zbyt szybko, z kolei Wirtualne Sprajty (VSprites) mogą mieć max. 3 kolory (nie można ich łączyć w 15-kolorowe), warto napisać ich zamienniki.
Także, wbrew temu co napisał Juen uważam, że graphics.library jest dosyć powolny. Wystarczy zobaczyć funkcje typu ReadPixelArray8, wykonują się bardzo wolno i nawet w oficjalnej dokumentacji sugerują napisanie własnego, szybkiego zamiennika! Ogólnie system Amigi nie jest skonstruowany tak, żeby wykorzystywać Blitter w optymalny sposób. Jest tu ogromne pole do popisu dla koderów.

System Amigi jest za to bardzo elastyczny i jak się przejmie niektóre przerwania na własny użytek (niekoniecznie odbierając dostęp do nich innym taskom) można stworzyć własny sub-system, który działa z ogromną prędkością na Amidze.

W razie czego służę pomocą "techniczną". Sam będę pisać taką bibliotekę w najbliższym czasie na pewno.
[#5] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@Hexmage960, post #4

Panowie, jeżeli chcecie mieć szybką bibliotekę do tworzenia gier, to zapomnijcie o RastPortach, layerach i graphics.library. Trzeba przyjąć proste założenia: niesystemowy ekran o rozdzielczości powiedzmy 320 x 256, być może z góry założona ilość bitplanów. Wszystkie operacje graficzne wykonywane bezpośrednio przez programowanie chipsetu. I wtedy optymalizujemy... Taką bibliotekę można napisać w C bez większej straty szybkości wobec asemblera.
[#6] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@pong777, post #1

Super jeśli byłby pełny support dla ECS/AGA/RTG.


wg. mnie to niemożliwe tak po prostej. Chipsety Amigi tak bardzo różnią się w wielu kwestiach od kart graficznych, że na karcie graf. byłaby to zupełnie inna biblioteka niemal z elementami emulacji chipsetów z UAE, co kompletnie wytracałoby wydajność na tych kartach graf. .
[#7] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@sigma2pi, post #6

Zgadzam się całkowicie. Implementacja tych bibliotek w wersji RTG mogłaby co najwyżej powstać dla MorphOS-a i AmigaOS4, bo tam konieczność emulowania pewnych cech amigowego chipsetu możnaby nadrobić brutalną mocą procesora...
[#8] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@pong777, post #1

Sensowne byłoby i coś takiego powstaje, piszemy toto w C. Zademonstrujemy na RK2014.

Szybki scrolling na copperze modyfikującym rejestry blittera included ;)

Ostatnia aktualizacja: 14.10.2014 13:09:26 przez teh_KaiN
[#9] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@Krashan, post #5

Ja byłbym ostrożny w programowaniu hardware Amigi za wyjątkiem Blittera i tzw. Copperlist Użytkownika (UCopList) ze względu na możliwość utraty kompatybilności między różnymi modelami Amig. Głównie chodzi o:

  • Odczyt danych z dysku - tylko dos.library ew. trackdisk.device, żadnych sztuczek na rejestrach,
  • Odtwarzanie dźwięków - najlepiej za pomocą audio.device alokować kanały i odtwarzać dźwięki. Jeśli chodzi o odtwarzanie muzyki to można zrobić wyjątek i użyć gotowych procedur do odtwarzania modułów,
  • Wyświetlanie obrazu - najlepiej zorganizować własny pod-system takim jaki jest Intuition, czyli użyć przez siebie skonfigurowanego View i ViewPortów. View to najlepszy sposób na przejęcie wyświetlania.

Jeśli chodzi o RastPorty to zgadzam się, że wszelakie operacje na RastPorcie są obarczone dosyć dużym narzutem (ang. "overhead"), więc warto napisać własne procedury rysujące. Można również napisać szybsze odpowiedniki przykładowo BltMaskBitMapRastPort(). Najważniejsze w mojej opinii to napisać ulepszony system Bobów.

Zatem z jednej strony nie rezygnowałbym całkowicie z systemu, bo udostępnia on szereg usług, z których warto skorzystać. Można też pisać programy, które działają w wielozadaniowości bardzo dobrze. Z drugiej strony system Amigi ma parę wad, które warto poprawić pisząc ulepszone odpowiedniki.

Kompatybilność z RTG to zupełnie inna sprawa.
[#10] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@Hexmage960, post #9

Poprzedni post pisałem na szybko przed wyjściem, teraz wróciłem. Parę szczegółów o naszym ustrojstwie zdradzę, ale nie za dużo, żeby było troszkę tajemnicy do czasu RK14.

RTG nie supportujemy, bo ani ja ani Proxy takiego sprzętu nie mamy. Całość działa w zgodzie z systemem nie ubijając go. Właściwie nasza praca nie jest hermetycznym środowiskiem, lecz raczej uzupełnieniem API Amigi o funkcje, które bardzo upraszczają wykonywanie "codziennych" zadań. Jest chociażby lekki moduł do rysowania prostokątów, wyświetlania fontów bitmapowych, edytowania copperlist użytkownika w formacie UCopList. Jest też moduł input, który po podpięciu trzech instrukcji w odpowiednim miejscu melduje stany klawiatury, myszy i dżojstików, w tym tych na rozgałęźnik portu równolego.

Więcej nie zdradzam, pokażemy wszystko w listopadzie. Dostępne to będzie oczywiście za darmo wraz ze źródłami.

Ostatnia aktualizacja: 14.10.2014 15:57:31 przez teh_KaiN
[#11] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@teh_KaiN, post #10

Podsumowują fajnie by było mieć wygodę i zasób gotowych funkcji z AMOSa tylko z szybkością i możliwościami C z pełnym wsparciem dla AGAty.

Np. polecam też bibliotekę Allegro dostępną dla wielu platform w tym chyba dla AOS 4? W tym naprawdę szybko i przyjemnie się tworzy gry.

Tak czy siak bardzo się cieszę, że się dzieje coś dobrego w tym kierunku i czekam z niecierpliwością.

Temat RTG można tak załatwić, że są dostępne funkcje o tych samych nazwach osobno dla ECS/AGA osobno dla RTG w zależności od jakiegoś inkluda.

Brak sprzętu nie jest problemem - można ćwiczyć na P96 pod UAE.

Ostatnia aktualizacja: 14.10.2014 19:10:20 przez pong777
[#12] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@teh_KaiN, post #10

Czy odbyła się prezentacja biblioteki?
[#13] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@pong777, post #12

Ha, odbyła się prezentacja nowej gry, acz nie była ona zbyt konkretna, bibliotekę próbowaliśmy zaprezentować, ale nie wyszło to zbyt fajnie. Ale po kolei:

- z grą Villages walczyliśmy praktycznie do ostatniego momentu, by pokazać ją w pełni skończoną. Pisać skończyliśmy w sobotę o 4 w nocy, o 6 zaś trza było wstać żeby na RK się udać. Zabrakło nam jednego dnia by było w miarę stabilnie (nie ma zliczania punktów), paru dni by był miód. Także spodziewajcie się release'a w przyszłym tygodniu na łamach PPA i prawdopodobnie też na retrokomp.org.

- silnik chcieliśmy zaprezentować dodając na żywca rzeczy do gry, ale z racji tego, że byliśmy średnio przytomni, a sama gra była rozbebeszona po wieczornej sesji, to nic z tego nie wyszło.

Zatem uchylę teraz trochę rąbka tajemnicy. Będę przy tym zakładał, że osoby czytające poniższe znają C w podstawowym zakresie. Jeśli coś będzie niezrozumiałe (a jest to wysoce możliwe, że prawie wszystko), proszę zadawać pytania. Do rzeczy:

Nasz twór roboczo nazywa się ACE, od Amiga C Engine. Produkcje tworzone w tym ustrojstwie wyglądają mniej więcej tak, że mamy sobie plik main.c, w którym to sobie podpinamy odpowiednie moduły ACE'a i wywołujemy pierwszy gamestate, reszta się robi sama. Na przykładzie naszej obecnej gry (PPA nie wyświetla tabulatorów i nadmiernych nowych linii w [ code ], buuu!):

int main(void) {
	logOpen(); // odpal menedżer logów
	randInit(0); // odpal generator liczb losowych (seed = 0)
	
	inputOpen(); // odpal menedżer inputa (nasłuchiwanie klawy, dżojów, myszy)
	windowCreate(); // zrób mi screen oraz okno, które przesłania cały ekran, co bym mógł przechwytywać mysz i klawiaturę nie brudząc niczego w systemie działającym w tle
	
	loadCursorData(); // własna funkcja, wczytuje dane kursora z pliku
	
	gameChangeState(gsMenuCreate, gsMenuSplashSetup, gsMenuDestroy); // zacznij od gameState'a MENU
	
	// tu już gra jest otwarta i sobie leci w kółko
	while (gameIsRunning()) { // pętla gry
		timerProcess(); // pyknij timery do przodu
		inputProcess(); // odśwież stan wciśnięcia klawiszy, myszy, dżojów, itd.
		gameProcess(); // wykonaj przebieg pętli z aktualnego gamestate'a
	}
	// tu już gra się zamyka
	
	gameChangeState(0, 0, 0); // wyjdź z jakiegokolwiek gamestate'a
	windowDestroy(); // zniszcz ekran
	inputClose(); // zamknij nasłuchiwanie inputa

	logClose(); // wyłącz menedżer logów
	return EXIT_SUCCESS; // koniec programu
}


Gdzie właściwie wszystko jest prawie stałe i zmieniają się tylko argumenty funkcji changeGameState() jeżeli nasz pierwszy gamestate nie nazywa się menu.

Czym jest ten gamestate? Ano jest to stan gry, np. menu, właściwy tryb gry, plansza tytułowa, creditsy, cokolwiek. Każdy z nich składa się z 3 funkcji: create, loop, destroy. Create wywoływana jest tylko raz i w niej robimy wszystko, co jest potrzebne do wyświetlenia danego gamestate'a (odrysowanie tła, wyrysowanie menu, wczytanie grafik potrzebnych w grze). Loop jest wywoływany cały czas i jest to już kod odpowiadający za poruszanie się po pozycjach w menu, czy po chodzeniu po mapie, jeśli już jesteśmy w sednie gry. Destroy jest wywoływany przy przejściu z jednego gamestate'a do drugiego i jego zadaniem jest sprzątanie tego, co narobił create (zwalnianie bitmap, fontów, pamięci, buforów ekranu).

Znowu nie będę się produkował zbyt dużo, tylko rzucę przykład z kodu menu (nie mój tylko Proxa, więc nie ręczę za jego poprawność, acz przykład powinien coś zilustrować):

void gsMenuCreate(void) {
	logWrite("gsMenuCreate begin\n"); // wpis w logu, co by to debugować
	logPushIndent(); // wcięcie w logu, co by widzieć, że ta część loga należy do menu
	
	g_pExtView = extViewCreate( // tworzenie ekranu 320x256: pierwszy viewport na cały ekran i z pełnym bpp, drugiego viewporta nie ma (wewnątrz gry jest nim zrobiony HUD)
		WINDOW_SCREEN_WIDTH, WINDOW_SCREEN_HEIGHT,
		WINDOW_SCREEN_WIDTH, WINDOW_SCREEN_HEIGHT, WINDOW_SCREEN_BPP,
		0, 0, 0,
		0
	);
	createFilePalette("data/palettes/selur_v1.plt", g_sWindowManager.pPalette); // wczytanie palety kolorów z pliku i ustawienie jako bieżącej

	g_pSplashBitMap = bitmapCreateFromFile("data/bitmaps/splash.bm"); // bitmapa splash screena
	g_pCharactersBitMap = bitmapCreateFromFile("data/bitmaps/goblins.bm"); // bitmapa portretów postaci
	g_pGrassBitMap = bitmapCreateFromFile("data/bitmaps/grass.bm"); // bitmapa trawy w tle

	g_pFont = fontCreate("data/fonts/arpegius-15.fnt"); // wczytanie fonta z pliku

	if (!g_sGameConfig.ubPawnCount) { // logika gry, nieistotne
		g_sGameConfig.ubPawnCount = 8;
	}

	windowLoadExtView(g_pExtView); // załadowanie wcześniej utworzonego viewa z viewportami
	
	logPopIndent(); // zmniejsz wcięcie w logu
	logWrite("gsMenuCreate end\n"); // kolejny wpis w logu
}


Destroy wygląda tak:

void gsMenuDestroy(void) {
	logWrite("gsMenuDestroy begin\n"); // znowu to samo z dziennikiem
	logPushIndent();
	
	LoadView(0); // schowanie ekranu co by go spokojnie usunąć

	fontDestroy(g_pFont); // zwolnij fonta
	bitmapDestroy(g_pCharactersBitMap); // zwolnij bitmapy
	bitmapDestroy(g_pGrassBitMap);
	bitmapDestroy(g_pSplashBitMap);
	extViewDestroy(g_pExtView); // zwolnij ekran z viewportami i bufferami
	
	logPopIndent();
	logWrite("gsMenuDestroy end\n");
}


A jego loop to paskudztwo, więc nie pokażę. :) Za to pokażę kawałek kodu odpowiedzialny za nasłuchiwanie klawy/dżoja z menu CastleHacka, czyli fragment menu loopa:

void gsMenuLoop(void) {
	// Nie wywalać eskejpa, bo fajnie działa, my się przyzwyczailiśmy, to gracze też się przyzwyczają
	if (keyUse(KEY_ESCAPE)) {
		gameClose();
		return;
	}
	// steruje port 2 bo osoby grające na singla ZAWSZE mają wpiętą mychę w port 1
	else if ((joyUse(JOY1_DOWN) || keyUse(KEY_DOWN)) && (g_pMainMenuList->ubActiveOption < (g_pMainMenuList->ubLength - 1))) {
		++g_pMainMenuList->ubActiveOption;
		gsMenuDrawMenuList(g_pExtView, g_pMainMenuList, g_pFontAlagard, (WINDOW_SCREEN_WIDTH >> 1), MENULIST_Y, FONT_CENTER | FONT_COOKIE);
	}
	else if ((joyUse(JOY1_UP) || keyUse(KEY_UP)) && g_pMainMenuList->ubActiveOption) {
		--g_pMainMenuList->ubActiveOption;
		gsMenuDrawMenuList(g_pExtView, g_pMainMenuList, g_pFontAlagard, (WINDOW_SCREEN_WIDTH >> 1), MENULIST_Y, FONT_CENTER | FONT_COOKIE);
	}
	else if (joyUse(JOY1_FIRE) || keyUse(KEY_RETURN)) {
		g_pMainMenuList->pOptions[g_pMainMenuList->ubActiveOption].pAction();
	}
	
	if (timerCheck(&g_ulLogoTimer, 1)) {
		animateMenuCopperList(g_pCopList);
	}
	// Pulsowanie wybranej pozycji - kod własny
	// ...
}


Gdzie któryś pMainMenuList->pOptions[g_pMainMenuList->ubActiveOption].pAction(); wywołuje linię gameChangeState(gsCharSelectCreate, gsCharSelectLoop, gsCharSelectDestroy); a to powoduje zamknięcie menu i otwarcie gamestate'a odpowiedzialnego za wybór postaci.

Główny wniosek z tego kodu powinien być jeden - jest masa utilów, które sprowadzają wczytanie bitmapy, fonta, sprawdzanie stanu klawy/myszy/joya, zarządzanie ekranem do jednej funkcji. Kod ACE'a będzie otwarty po to, żeby gdyby ktoś chciał zobaczyć jak to ustrojstwo działa, odpali sobie odpowiedni plik .c i będzie to sobie mógł przeanalizować.

Jak ktoś chce posłuchać to mogę się wyprodukować tu jeszcze i przestawić same utile - właśnie funkcje od bitmap, fontów, prostokątów, liczb losowych, inputa, oraz pokazać co szykujemy ze scrollingiem. :)
[#14] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@teh_KaiN, post #13

Fajne.
A macie też funkcje obsługi spritów, albo BOBów? Fajna byłaby możliwość manipulacji copperlistą (bez jakiś wodotrysków - jakieś podmiany rejestrów kolorów itp.).
[#15] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@wali7, post #14

Boby będą, sprite'y też, choć najpierw to pierwsze. Mieliśmy już system do takich rzeczy rok temu przy prezentacji CH, ale był on badziewny. Jak tylko uporamy się z obecnym tytułem (a nazywa się on Villages), wracamy do CH i wtedy można się spodziewać systemu bobów. Do tego czasu pozostaje działanie na piechotę lub korzystanie z rozwiązania systemowego, bo nasze ustrojstwo w pełnej harmonii działa z systemowymi funkcjami graphics.library.

Co do copperlisty - zrobiłem funkcję, która pozwala modyfikować systemową strukturę copperlisty użytkownika, działa na modłę fseek i wygląda tak:

void windowSeekUCopList(struct UCopList *pUCopList, WORD wOffset, UBYTE ubFlags) {
	if (ubFlags & CPR_SEEK_SET) {
		pUCopList->CopList->Count = wOffset;
	} else if (ubFlags & CPR_SEEK_END) {
		pUCopList->CopList->Count = pUCopList->CopList->MaxCount+wOffset;
	} else { // CPR_SEEK_CUR
		pUCopList->CopList->Count += wOffset;
	}

	pUCopList->CopList->CopPtr = pUCopList->CopList->CopIns + (sizeof(struct CopIns) * pUCopList->CopList->Count);
}


Dzięki tej funkcji można się cofnąć na konkretną pozycję copperlisty (np. na początek lub 5 instrukcji w tył) i nadpisać obecne instrukcje za pomocą makr CWAIT, CMOVE lub przedwcześnie skończyć copperlistę makrem CEND. Potem tylko MrgCop() i zmiany naniesione :)
[#16] Re: Własna biblioteka mutlimedialna dla C dla klasyka

@teh_KaiN, post #15

No brawo zapowiada się ciekawie i może okazać się użyteczne OK
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem