kategoria: ANSI C
[#1] [C] Czy da radę coś takiego wygenerować
Zastanawiam się jak uzyskać plik binarny, który w asemblerze potrafię napisać bez żadnego problemu, za to w C nie mam pojęcia czy można takie coś osiągnąć. Sama kompilacja do pliku binarnego w C nie nastręcza problemu.

Oto przykładzik w asm


start:
dc.l l0-start
dc.l l1-start
dc.l -1

l0: dc.w 1,1,2,2
l1: dc.w 8,8,9,9

Jakieś pomysły ?

Ostatnia aktualizacja: 21.12.2022 13:15:44 przez asman

Ostatnia aktualizacja: 21.12.2022 13:15:58 przez asman
[#2] Re: [C] Czy da radę coś takiego wygenerować

@asman, post #1

też nie wiem :) ale pierwsza uwaga jaka przychodzi mi do głowy jest taka że pomimo że mógłbyś odjąć wskaźniki l0-start to tak naprawdę nie wiesz czy kompilator umieści te rzeczy jedną po drugiej? a po drugie jak system operacyjny rozmieści te obszary w pamięci?
Jak rozumiem chcesz mieć pod adresem start: offsety do danych l0 i l1 a czy nie mogły by to być po prostu wskaźniki na te lokalizacje l0 i l1?
[#3] Re: [C] Czy da radę coś takiego wygenerować

@c64portal, post #2

Tablice l0 i l1 musiałyby być chyba zadeklarowane przed start, coś takiego:

int l0[]={1,1,2,2};
int l1[]={8,8,9,9};

int start[] = {(intptr_t)&l0 - (intptr_t)&start, (intptr_t)&l1 - (intptr_t)&start};
[#4] Re: [C] Czy da radę coś takiego wygenerować

@kar78787878, post #3

Nie znam się na C ale o ile deklaracja int start[] oznacza taką samą wielkość danych co dc.l (czyli 32bity) to to ostatnie chyba bedzie w porządku. Tylko jeszcze brakuje tam tego -1 w tablicy.
[#5] Re: [C] Czy da radę coś takiego wygenerować

@kar78787878, post #3

int start[] = {(intptr_t)&l0 - (intptr_t)&start, (intptr_t)&l1 - (intptr_t)&start};


To nie zadziala - inicjalizery musza byc stalymi.
Mozna tak zrobic:
const int l0[] = { 1,1,2,2 };
const int l1[] = { 8, 8, 9,9 };

int start[] =  { l0, l1, -1 };

I pozniej w inicie :
void init_table()
{
	int cnt;
	for (cnt = 0; cnt < sizeof(start)-1 / sizeof(int); cnt++)
	{
		start[cnt] = &start[cnt] - &start;
	}
}

Zakladam, ze chciaibys to zgrac jako binarny kawalek - wtedy najlepiej ubrac to w strukture
struct table
{
	void* start[3];
	int l0[4];
	int l1[4];
};

struct table tab = {
	{&l0[0], &l0[1], -1 },
	{ 1,1,2,2 }, { 8, 8, 9,9 }
};
zainicjowac jak wyzej I zgrac fwrite
[#6] Re: [C] Czy da radę coś takiego wygenerować

@c64portal, post #2

Dziękuje wszystkim za odpowiedzi (te błędne też :) )

@c64portal
Prawdę powiadasz, bo nie wiadomo w jaki sposób zostanie to rozmieszczone, gdyż sam język C ( z tego co pamiętam) nie narzuca nic takiego.

Właśnie nie potrzebuję wskaźników, gdyż to jest struktura plansz, a one mają różny rozmiar. Mam przesunięcia do nich i marker -1, który oznacza koniec. Co prawda by dowiedzieć się ile jest plansz potrzebuje przejechać aż do -1, ale robię to tylko raz gdy ładuje plansze, co nie jest przeszkodą bo zawsze mogę dodać dodatkowe pole zawierające ilość plansz (na samym początku). Samo dobranie się do planszy wygląda tak.

ULONG* offsets = (ULONG*)gm->levels.memory.address;
const UWORD nr = gm->levelNumber;
UWORD* src =(UWORD*)((ULONG)gm->levels.memory.address + offsets[nr]);

W tym moim problemiku, chodzi raczej o coś innego. Mam plik tile.h w którym są enumy

enum Tiles
{
T_ROCK,
T_EMPTY,
T_HERO,
};
I z nich składam plansze, które wyglądają tak
x,y
tile11, tile12, ..., tileX1,
...
tile1Y, tile2Y, ..., tileXY

I teraz mam dwie opcje.
1. Jakoś uzyskać plansze w C - i stąd moje pytanie
2. Zakodować plansze w asm i w jakiś sposób przerobić plik tile.h na asm - I to chyba będzie łatwiejsze dla mnie, bo użyje Replace w edytorze (albo napisze jakieś malutkie narzędzie które odpalę z makefile), które zmieni mi powyższy enum na taki asm i
ENUM
EITEM T_ROCK
EITEM T_EMPTY
EITEM T_HERO
1
[#7] Re: [C] Czy da radę coś takiego wygenerować

@docent, post #5

@docent
Dzięki obadam.
[#8] Re: [C] Czy da radę coś takiego wygenerować

@asman, post #7

Jako, że jest to struktura o zmiennym rozmiarze i typie, ja bym rozdzielił ją w C na dwie odrębne tablice.

A następnie przygotował funkcję ze zmienną liczbą argumentów, by wygodnie ją zainicjować.

Dzięki temu w dynamiczny sposób będziesz mógł ją inicjować.

Przy czym nie robię offsetu ze start do tab, tylko podaję skumulowany indeks elementu tablicy tab.

#include <stdarg.h>
#include <stdlib.h>

void main()
{
	LONG *start = calloc(3, sizeof(LONG));
	WORD *tab = calloc(4 * 2, sizeof(WORD)), *ptr = tab;

	start[0] = initWordOffsets(&ptr, 4, 1, 1, 2, 2);
	start[1] = start[0] + initWordOffsets(&ptr, 4, 8, 8, 9, 9);
	start[2] = -1;
}

int initWordOffsets(WORD **ptab, int count, ...)
{
	int i = 0;
	WORD *tab = *ptab;
	va_list list;

	va_start(list, count);

	for (i = 0; i < count; i++)
		tab[i++] = va_arg(list, int));

	va_end(list);
	*ptab = tab + i;
	return(i); /* Zwracamy liczbę elementów */
}
1
[#9] Re: [C] Czy da radę coś takiego wygenerować

@asman, post #6

Czyli masz w tej pierwszej tablicy przesunięcia wzgledem niej do danych... A nie prościej zapisać sobie przesuniecia od początku danych po prostu?

Ostatnia aktualizacja: 21.12.2022 21:26:14 przez pisklak
[#10] Re: [C] Czy da radę coś takiego wygenerować

@pisklak, post #9

Tylko trzeba by na 2 pliki podzielić wtedy...
[#11] Re: [C] Czy da radę coś takiego wygenerować

@asman, post #1

W języku C będzie Ci dużo prościej napisać generator takich plików (co zresztą niektóre z wcześniejszych postów nieświadomie sugerowały), niż zmusić kompilator do wygenerowania takiej binarki z kodu. Przy czym nawet jeżeli by się udało, to będzie to rozwiązanie specyficzne dla danego kompilatora, a może nawet konkretnej jego wersji.
1
[#12] Re: [C] Czy da radę coś takiego wygenerować

@Krashan, post #11

Pewnie źle mi się wydaje że najprościej chyba byłoby założenie że pierwsze powiedzmy 256 elementów tablicy (tablica deklarowana jako dc.w czyli short lecz dostęp do tych elementów robimy jako dc.l czyli int) rezerwujemy na offsety a reszta to po prostu dane (albo znowu patent z -1). Trzeba by zrobić po prostu dwa wskaźniki na tą samą tablicę z rożnymi typami danych, i przesuwać sobie ten drugi wartościami odczytanymi z tego pierwszego. Może chociaż tym razem nie popisałem głupot

Ostatnia aktualizacja: 22.12.2022 09:00:10 przez pisklak
[#13] Re: [C] Czy da radę coś takiego wygenerować

@Krashan, post #11

To że chodzi o levele zorientowałem się bo mam to podobnie rozwiązane ;) (teraz piszę drugą grę w C na C64).

Tyle, że ja właśnie taki generator pliku binarnego z opisem i danymi do leveli mam w .asm. nie widzę problemu aby w Makefile'u mieć regułę do kompilowania (assemblowania) takiego pliku składającego się z dc.w i dc.l do pliku binarnego. Zresztą, ciekawostka, jak swego czasu zabrałem się za grę na Amigę w Blitz Basicu to właśnie w asm'ie miałem opis leveli i robiłem sobie plik binarny vasmem, który potem czytałem w Blitzu. Łatwiej i szybciej niż kombinować jak to z Blitzu (czy w C) zrobić.
1
[#14] Re: [C] Czy da radę coś takiego wygenerować

@c64portal, post #13

Zggadzam się, "napisanie" takich plików po prostu w asmie, używając "DC.x" jest najprostsze i spokojnie można odpalić assembler w makefile.

Z drugiej strony, generator napisany w C też może zostać odpalony w makefile. Zaletą generatora jest to, że można sobie wtedy ułatwić pracę i np. projektować poziomy jako grafikę w ASCII (przetwarzaną przez generator na dane binarne), albo nawet dopisać później edytor poziomów z GUI.
1
[#15] Re: [C] Czy da radę coś takiego wygenerować

@Krashan, post #14

Albo, skoro nie robimy gry na 8-bitowca i nie liczymy każdego bajtu pliku wykonywalnego, to możemy podać grze plik w wygodnej dla człowieka formie. Mieć kafle rozrysowane w ASCII, niech to sobie sama gra przeparsuje. A jak jeszcze trochę trzeba metadanych to można dorzucić obsługę jsona przy użyciu np biblioteki jsmn. Zaleta jest taka że nie jest potrzebny edytor map, żeby rozsądnie sobie to ręcznie porozstawiać.

ChaosArena w ogóle miała zahardkodowane tablice w ASCII i sobie to w locie dekodowała na wewnętrzną organizację danych. Po co coś więcej, jak wystarcza, mieści się w ramie i działa wystarczająco szybko? Można by to w takiej samej formie zaczytywać przy użyciu fread oczywiście.

static const char s_pMapPatternsYx[3][TILE_HEIGHT][TILE_WIDTH + 1] = {
	{
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@....@..b..c..@....@@",
		"@@.a..@........@..d.@@",
		"@@@@@.@@@@..@@@@.@@@@@",
		"@@@@@....@..@....@@@@@",
		"@@...@...@..@...@...@@",
		"@@.l.....@..@.....j.@@",
		"@@...m...@..@...k...@@",
		"@@...@...@..@...@...@@",
		"@@@@@....@..@....@@@@@",
		"@@@@@.@@@@..@@@@.@@@@@",
		"@@.e..@........@..f.@@",
		"@@....@..h..g..@....@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@"
	},
	{
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@..................@@",
		"@@.a...j....f..k..b.@@",
		"@@..................@@",
		"@@.....@@@@@@@@.....@@",
		"@@....@@@@@@@@@@..o.@@",
		"@@.g.@@@@@@@@@@@@...@@",
		"@@...@@@@@@@@@@@@.h.@@",
		"@@.n..@@@@@@@@@@....@@",
		"@@.....@@@@@@@@.....@@",
		"@@..................@@",
		"@@.d..m...e....l..c.@@",
		"@@..................@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@"
	},
	{
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@.....L......J.....@@",
		"@@.1......9.......3.@@",
		"@@....@@@....@@@....@@",
		"@@.G..@@@..5.@@@..D.@@",
		"@@....@@@....@@@....@@",
		"@@.....B...M......8.@@",
		"@@.7......N...C.....@@",
		"@@....@@@....@@@....@@",
		"@@.E..@@@.6..@@@..F.@@",
		"@@....@@@....@@@....@@",
		"@@.4.......A......2.@@",
		"@@.....H......K.....@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@",
		"@@@@@@@@@@@@@@@@@@@@@@"
	}
};


Przykład JSONa z GermZ:

{
	"name": "3 stars",
	"author": "Softiron",
	"tiles": [
		"................",
		"................",
		"................",
		"................",
		"..1...........3.",
		".111----Z----333",
		"..1.....|.....3.",
		"..|.....|.....|.",
		"..|.....|.....|.",
		"..|.....|.....|.",
		"..|.....2.....|.",
		"..X----222----Y.",
		"........2.......",
		"................",
		"................",
		"................"
	]
}


A tu trochę bardziej rozbudowane OpenFire

{
	"title": "Operation FUBAR",
	"width": 33,
	"height": 34,
	"author": "kain@piwnica.ws",
	"mode": "conquest",
	"tiles": [
		".................................",
		".                               .",
		". s---------------------------s .",
		". |    1    1     1    1      | .",
		". s    #    #     #    #      s .",
		". |    #################      | .",
		". s    #       #       #      s .",
		". |    #       #       #      | .",
		". s-s-s#s-s-s-s#s-s-s-s#s-s-s-s .",
		". |    #       #  | |  #      | .",
		". |    #       #  s s  #      | .",
		". s 1  #c   1  ###########  1 s .",
		". |    #       #  s s  c #    | .",
		". |    #       #  | |    #    | .",
		". s-s-s#s-s-s-s#s-s s-s-s#s-s-s .",
		".      #       #         #      .",
		".      #       #o        #      .",
		".      #       ###       #      .",
		".      #         #       #      .",
		". S-S-S#S-S-S S-S#S-S-S-S#S-S-S .",
		". |    #    | |  #       #    | .",
		". |    # C  S S  #       #    | .",
		". S 2  ###########  2   C#  2 S .",
		". |      #  S S  #       #    | .",
		". |      #  | |  #       #    | .",
		". S-S-S-S#S-S-S-S#S-S-S-S#S-S-S .",
		". |      #       #       #    | .",
		". S      #       #       #    S .",
		". |      #################    | .",
		". S      #    #     #    #    S .",
		". |      2    2     2    2    | .",
		". S---------------------------S .",
		".                               .",
		"................................."
	],

	"controlPoints": [
		{
			"name": "Blue west",
			"capture": [8, 11],
			"polygon": [[2,9], [18,9], [18,14], [2,14]]
		},
		{
			"name": "Blue east",
			"capture": [23,12],
			"polygon": [[20,9], [30,9], [30,14], [20,14]]
		},
		{
			"name": "Courtyard",
			"capture": [16,16],
			"polygon": [[2,15], [30,15], [30,18], [2,18]]
		},
		{
			"name": "Red west",
			"capture": [9,21],
			"polygon": [[2,19],[12,19],[12,24],[2,24]]
		},
		{
			"name": "Red east",
			"capture": [24,22],
			"polygon": [[14,19],[30,19],[30,24],[14,24]]
		}
	]
}
3
[#16] Re: [C] Czy da radę coś takiego wygenerować

@teh_KaiN, post #15

Zbiorczo. Dziękuje pięknie wszystkim za odpowiedzi. Moim podstawowym problemem jest teraz czas a w zasadzie jego notoryczne braki, więc na razie zostawiam wersje asemblerową. Aż do momentu gdy cała logika gry zostanie dokończona.

@c64portal
Jeszcze nie sprawdzałem ale widziałem przed chwilą na stronie wiadomość, z ciekawości jaki to będzie gatunek gry ?
[#17] Re: [C] Czy da radę coś takiego wygenerować

@asman, post #16

z ciekawości jaki to będzie gatunek gry ?

Jakiś preview/filmik pokażę po nowy roku, ale na razie wychodzi mi z tego mieszanka Zeldy z Chaos Engine w klimatach mojego pierwszego Robota.
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