Post 0x02

Door Tommasso op donderdag 29 september 2011 10:40 - Reacties (1)
Categorie: -, Views: 1.730

Hallo allemaal,
Door mijn studie heb ik helaas minder tijd gehad om aan mijn project te werken, maar toch heb ik wat vooruitgang geboekt:
http://img208.imageshack.us/img208/7130/aoe012011093023170475.png
Deze post gaat grotendeels over hex editing, dat je het weet...

Zoals ik in mijn vorige blogpost zei wilde ik af van de velen afbeeldingen die in mijn project rondzweven. Ik wilde zelf de .drs bestanden kunnen uitlezen en zelf de .slp bestanden kunnen tekenen.
Daarvoor moet ik natuurlijk wel het bestandsformaat kennen. Na een tijdje zoeken op het Internet heb ik een beschrijving gevonden. Laten we beginnen bij de .drs bestanden. In de .drs bestanden worden onder andere alle afbeeldingen (.slp bestanden) opgeslagen. Waarschijnlijk worden ze in deze bestanden opgeslagen om te voorkomen dat er rond de 10.000 losse bestanden rondvliegen. Er zijn vijf .drs bestanden:
- interfac.drs
- graphics.drs
- gamedata.drs
- terrain.drs
- sounds.drs
Omdat ik voornamelijk bezig ben met het tekenen van terrein, besloot ik om terrain.drs te gaan analyseren.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Offset hex. 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
000000000:  43 6F 70 79 72 69 67 68 74 20 28 63 29 20 31 39 Copyright (c) 19
000000010:  39 37 20 45 6E 73 65 6D 62 6C 65 20 53 74 75 64 97 Ensemble Stud
000000020:  69 6F 73 2E 1A 00 00 00 31 2E 30 30 74 72 69 62 ios.....1.00trib
000000030:  65 00 00 00 00 00 00 00 01 00 00 00 90 01 00 00 e..............
000000040:  20 70 6C 73 4C 00 00 00 1B 00 00 00 98 3A 00 00  plsL.......˜:..
000000050:  90 01 00 00 D0 69 04 00 99 3A 00 00 60 6B 04 00 ...i..™:..`k..
000000060:  D0 69 04 00 9A 3A 00 00 30 D5 08 00 D0 69 04 00 i..:..0..i..
000000070:  9C 3A 00 00 00 3F 0D 00 D0 96 01 00 9D 3A 00 00 :...?..–..:..
000000080:  D0 D5 0E 00 D0 96 01 00 9E 3A 00 00 A0 6C 10 00 ..–..:.. l..
000000090:  D0 69 04 00 9F 3A 00 00 70 D6 14 00 D0 69 04 00 i..:..p..i..
0000000A0:  A0 3A 00 00 40 40 19 00 D0 69 04 00 A1 3A 00 00  :..@@..i..:..
0000000B0:  10 AA 1D 00 D0 69 04 00 A2 3A 00 00 E0 13 22 00 ...i..:...".
0000000C0:  D0 69 04 00 A3 3A 00 00 B0 7D 26 00 D0 69 04 00 i..:..}&.i..
0000000D0:  A6 3A 00 00 80 E7 2A 00 D0 69 04 00 A7 3A 00 00 :..*.i..:..
0000000E0:  50 51 2F 00 D0 69 04 00 A8 3A 00 00 20 BB 33 00 PQ/.i..:.. 3.
0000000F0:  D0 69 04 00 A9 3A 00 00 F0 24 38 00 D0 69 04 00 i..:..$8.i..
000000100:  AA 3A 00 00 C0 8E 3C 00 D0 69 04 00 AB 3A 00 00 :..<.i..:..
000000110:  90 F8 40 00 D0 69 04 00 AD 3A 00 00 60 62 45 00 @.i..-:..`bE.
000000120:  CC 65 00 00 AE 3A 00 00 2C C8 45 00 CC 65 00 00 e..:..,E.e..
000000130:  AF 3A 00 00 F8 2D 46 00 CC 65 00 00 B0 3A 00 00 :..-F.e..:..
000000140:  C4 93 46 00 D0 69 04 00 B2 3A 00 00 94 FD 4A 00 &#8220;F.i..:..&#8221;J.
000000150:  D0 69 04 00 B3 3A 00 00 64 67 4F 00 D0 69 04 00 i..:..dgO.i..
000000160:  B4 3A 00 00 34 D1 53 00 D0 69 04 00 B5 3A 00 00 :..4S.i..:..
000000170:  04 3B 58 00 D0 69 04 00 B6 3A 00 00 D4 A4 5C 00 .;X.i..:..Ԥ\.
000000180:  D0 69 04 00 B7 3A 00 00 A4 0E 61 00 D0 69 04 00 i..:...a.i..
000000190:  32 2E 30 4E 64 00 00 00 41 72 74 44 65 73 6B 20 2.0Nd...ArtDesk 
0000001A0:  31 2E 30 30 20 53 4C 50 20 57 72 69 74 65 72 00 1.00 SLP Writer.


aan het einde van de code kan je zien dat er een .slp bestand begint. Oftewel de data van de .drs bestand zit waarschijnlijk tussen 0x00 en 0x190. De eerste 40 bytes is een string waarin de copyright staat. Deze kan dus worden genegeerd. Daar komt nog een string van 4 bytes lang welke de versie aangeeft en deze string wordt gevolgd door een andere string welke 12 bytes lang is en aangeeft voor welk spel het .drs bestand is gemaakt (AoE heette eerst tribe). Oftewel, allemaal onzinnige data.
Nu komt de zinnige data: de volgende 4 bytes is een long die het aantal tabellen aangeeft. In terrain.drs is dit n maar bij interfac.drs is het drie.
Hierna volgt een long welke de absolute offset van de data van het eerste bestand in de eerste tabel aangeeft. Deze offset is helemaal niet nuttig tenzij je de bestanden sequentieel kan uitlezen (en dat raad ik niet aan).

Nu zijn we klaar met het uitlezen van de header van het .drs bestand. Nu moeten we de headers van de tabellen uitlezen. Deze komen direct na de header van het .drs bestand. Maar helemaal snap ik de headers niet...
De eerste byte is een losstaande byte die altijd het zelfde lijkt (0x20) en zou niet weten wat deze is (de beschrijving die ik vond weet het ook niet). Dus skippen maar...
De volgende 3 bytes is een string die het type tabel aangeeft. Dit is niet zomaar een string, maar een string achterstevoren! (wie heeft dat bedacht...). In mijn geval geeft hij pls aan wat dus slp is.
Hierna volgt een long die de contentEntryOffset aangeeft.Oftewel, de absolute offset van het stuk waar de tableContent wordt gegeven.
Als laatste hebben we nog de fileAmount welke in een long is gegeven.

Nu moet de tableContent worden uitgelezen... En deze komen allemaal achter elkaar na de tableHeaders. Elke tableContent bestaat uit een long die de fileId aangeef, een long die de fileOffset aangeeft en een long die de fileSize aangeeft.

En als we dit allemaal gehad hebben kunnen we de bestanden gaan uitlezen. Mijn code ziet er ongeveer zo uit:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
br.ReadBytes(40); // skip useless data
br.ReadBytes(4); // skip useless data
br.ReadBytes(12); // skip useless data

int tableAmount = br.ReadInt32();
int[][] data = new int[tableAmount][];
br.ReadBytes(4); // skip useless data

DrsTable[] tables = new DrsTable[tableAmount];
// read out all the table headers (which are all just after each other)
for (int i = 0; i < tableAmount; i++)
{
    br.ReadBytes(1); // skip useless data
    // we need to reverse the filetype
    char[] tmp = br.ReadChars(3);
    Array.Reverse(tmp);

    int tableContentOffset = br.ReadInt32();
    int fileAmount = br.ReadInt32();

    tables[i] = new DrsTable(new string(tmp), tableContentOffset, fileAmount);
}

for (int i = 0; i < tableAmount; i++)
{
    DrsFile[] files = new DrsFile[tables[i].fileAmount];
    // read out all the table entries
    for (int ii = 0; ii < tables[i].fileAmount; ii++)
    {
        int fileId = br.ReadInt32();
        int fileOffset = br.ReadInt32();
        int fileSize = br.ReadInt32();

        tables[i].files[ii] = new DrsFile(fileId, fileOffset, fileSize);
    }
}

for (int i = 0; i < tableAmount; i++)
{
    // read out all the files
    for (int ii = 0; ii < tables[i].fileAmount; ii++)
    {
        tables[i].files[ii].content = br.ReadBytes(tables[i].files[ii].size);
    }
}


Niet al te moeilijk, vond ik zelf. Alleen vond ik het eigenaardig dat er zoveel data was welke niet absoluut nodig is als je de hele tabel uitleest. Ik denk dat ze dat dus niet deden en daarom alle offsets hebben ingebakken. Dan kan je namelijk om bestand 5 uit tabel 2 uit te lezen slechts met de volgende stappen volstaan:
- lees drs header uit
- lees tableHeaders uit
- neem tableContentOffset en ga tableContent uitlezen
- Neem fileOffset en lees fileSize aantal bytes uit.
- done!
Toch kan ik niet bedenken waarom er een offset is die aangeeft waar het eerste bestandje zit. Waarom zou je dit zo direct willen uitlezen??

Ok, de drs bestanden kan ik uitlezen. Maar hier kan ik nog niks mee. Ik wil namelijk terrain kunnen afbeelden.
De terrain tiles zitten dus in die slp bestanden en deze moet ik dan ook gaan uitlezen. Ook hier vond ik een beschrijving. Alleen was deze erg lastig te begrijpen en duurde het lang voordat ik het doorhad. En ding weet ik wel: men heeft destijds geprobeerd de bestanden erg compact te maken.
Laten we beginnen met ze uitlezen, daarna pas tekenen.
http://img64.imageshack.us/img64/5607/g0002101.png

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
Offset hex. 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
000000000:  32 2E 30 4E 01 00 00 00 41 72 74 44 65 73 6B 20 2.0N....ArtDesk 
000000010:  31 2E 30 30 20 53 4C 50 20 57 72 69 74 65 72 00 1.00 SLP Writer.
000000020:  34 04 00 00 40 00 00 00 00 00 00 00 10 00 00 00 4...@...........
000000030:  33 01 00 00 FD 00 00 00 99 00 00 00 B3 00 00 00 3......&#8482;......
000000040:  8C 00 A0 00 89 00 9E 00 87 00 9C 00 86 00 9A 00 . .&#8240;..&#8225;..&#8224;..
000000050:  84 00 98 00 81 00 97 00 80 00 96 00 7E 00 93 00 &#8222;.&#732;..&#8212;..&#8211;.~.&#8220;.
000000060:  7C 00 92 00 7B 00 8F 00 79 00 8D 00 77 00 8B 00 |.&#8217;.{..y..w.&#8249;.
000000070:  75 00 89 00 73 00 87 00 71 00 85 00 6F 00 83 00 u.&#8240;.s.&#8225;.q.&#8230;.o.&#402;.
000000080:  6E 00 82 00 6D 00 7F 00 6B 00 7E 00 68 00 7D 00 n.&#8218;.m..k.~.h.}.
000000090:  65 00 7B 00 64 00 7B 00 64 00 78 00 63 00 77 00 e.{.d.{.d.x.c.w.
0000000A0:  61 00 77 00 62 00 76 00 62 00 75 00 61 00 74 00 a.w.b.v.b.u.a.t.
0000000B0:  61 00 75 00 61 00 76 00 60 00 77 00 60 00 77 00 a.u.a.v.`.w.`.w.
0000000C0:  62 00 77 00 62 00 77 00 62 00 77 00 62 00 77 00 b.w.b.w.b.w.b.w.
0000000D0:  62 00 76 00 61 00 75 00 62 00 76 00 63 00 77 00 b.v.a.u.b.v.c.w.
0000000E0:  63 00 78 00 63 00 79 00 62 00 79 00 61 00 79 00 c.x.c.y.b.y.a.y.
0000000F0:  61 00 79 00 60 00 79 00 60 00 7A 00 5F 00 7A 00 a.y.`.y.`.z._.z.
000000100:  5F 00 7B 00 5E 00 7B 00 5C 00 7B 00 5B 00 7B 00 _.{.^.{.\.{.[.{.
000000110:  5B 00 7B 00 5B 00 7B 00 5B 00 7B 00 5B 00 7B 00 [.{.[.{.[.{.[.{.
000000120:  5B 00 7B 00 5A 00 7A 00 59 00 79 00 59 00 79 00 [.{.Z.z.Y.y.Y.y.
000000130:  58 00 79 00 58 00 7A 00 57 00 7F 00 57 00 7F 00 X.y.X.z.W..W..
000000140:  56 00 80 00 56 00 80 00 55 00 80 00 55 00 81 00 V..V..U..U..
000000150:  54 00 83 00 54 00 84 00 53 00 84 00 53 00 85 00 T.&#402;.T.&#8222;.S.&#8222;.S.&#8230;.
000000160:  52 00 86 00 51 00 86 00 51 00 85 00 50 00 83 00 R.&#8224;.Q.&#8224;.Q.&#8230;.P.&#402;.
000000170:  50 00 81 00 4F 00 7F 00 4F 00 7E 00 4D 00 7B 00 P..O..O.~.M.{.
000000180:  4C 00 78 00 4A 00 77 00 48 00 75 00 46 00 73 00 L.x.J.w.H.u.F.s.
000000190:  44 00 71 00 42 00 6F 00 3E 00 6D 00 3E 00 6B 00 D.q.B.o.>.m.>.k.
0000001A0:  3E 00 68 00 3E 00 67 00 3E 00 65 00 3E 00 63 00 >.h.>.g.>.e.>.c.
0000001B0:  3E 00 61 00 3E 00 5E 00 3E 00 5C 00 3E 00 5A 00 >.a.>.^.>.\.>.Z.
0000001C0:  3E 00 58 00 3E 00 55 00 3E 00 54 00 3E 00 52 00 >.X.>.U.>.T.>.R.
0000001D0:  3E 00 50 00 3E 00 4E 00 3E 00 4A 00 3E 00 47 00 >.P.>.N.>.J.>.G.
0000001E0:  3E 00 46 00 3E 00 45 00 3E 00 43 00 3E 00 42 00 >.F.>.E.>.C.>.B.
0000001F0:  3E 00 3E 00 3E 00 3D 00 3E 00 3B 00 3E 00 38 00 >.>.>.=.>.;.>.8.
000000200:  3E 00 37 00 3E 00 35 00 3E 00 33 00 3E 00 31 00 >.7.>.5.>.3.>.1.
000000210:  3E 00 2F 00 3E 00 2D 00 3E 00 2A 00 3E 00 28 00 >./.>.-.>.*.>.(.
000000220:  3E 00 26 00 3E 00 24 00 3E 00 22 00 3E 00 20 00 >.&.>.$.>.".>. .
000000230:  3E 00 1E 00 3D 00 1A 00 3B 00 19 00 39 00 19 00 >...=...;...9...
000000240:  37 00 17 00 35 00 16 00 32 00 15 00 30 00 13 00 7...5...2...0...
000000250:  2E 00 12 00 2C 00 10 00 2A 00 0F 00 28 00 0E 00 ....,...*...(...
000000260:  26 00 0C 00 24 00 0B 00 22 00 0A 00 20 00 0A 00 &...$..."... ...
000000270:  1E 00 08 00 1C 00 06 00 1A 00 05 00 18 00 04 00 ................
000000280:  16 00 02 00 14 00 00 00 12 00 0A 00 10 00 0A 00 ................
000000290:  0E 00 0A 00 0C 00 0A 00 0A 00 0A 00 08 00 0A 00 ................
0000002A0:  07 00 0A 00 08 00 0A 00 08 00 0A 00 08 00 0A 00 ................
0000002B0:  08 00 0A 00 08 00 0A 00 08 00 0A 00 08 00 0A 00 ................
0000002C0:  08 00 0A 00 08 00 0A 00 08 00 0A 00 08 00 0A 00 ................
0000002D0:  08 00 0A 00 08 00 0A 00 08 00 0A 00 08 00 0A 00 ................
0000002E0:  08 00 0A 00 07 00 0A 00 05 00 0A 00 02 00 0A 00 ................
0000002F0:  00 00 0A 00 00 00 0A 00 02 00 0A 00 03 00 0A 00 ................
000000300:  04 00 0A 00 06 00 0A 00 07 00 0A 00 06 00 0A 00 ................
000000310:  05 00 0A 00 06 00 0A 00 07 00 0A 00 08 00 0B 00 ................
000000320:  09 00 0E 00 0C 00 10 00 0E 00 12 00 0F 00 14 00 ................
000000330:  18 00 16 00 28 00 18 00 71 00 1A 00 72 00 1C 00 ....(...q...r...
000000340:  73 00 1E 00 74 00 20 00 75 00 22 00 76 00 24 00 s...t. .u.".v.$.
000000350:  77 00 25 00 77 00 26 00 77 00 26 00 78 00 25 00 w.%.w.&.w.&.x.%.
000000360:  78 00 25 00 78 00 26 00 78 00 27 00 78 00 28 00 x.%.x.&.x.'.x.(.
000000370:  78 00 29 00 78 00 2B 00 78 00 2F 00 78 00 30 00 x.).x.+.x./.x.0.
000000380:  78 00 36 00 78 00 39 00 68 00 45 00 67 00 44 00 x.6.x.9.h.E.g.D.
000000390:  67 00 44 00 67 00 45 00 68 00 46 00 68 00 48 00 g.D.g.E.h.F.h.H.
0000003A0:  68 00 49 00 68 00 4A 00 68 00 4C 00 68 00 50 00 h.I.h.J.h.L.h.P.
0000003B0:  68 00 51 00 67 00 59 00 67 00 61 00 66 00 63 00 h.Q.g.Y.g.a.f.c.
0000003C0:  63 00 65 00 60 00 65 00 60 00 69 00 62 00 6B 00 c.e.`.e.`.i.b.k.
0000003D0:  61 00 6D 00 62 00 6F 00 64 00 71 00 66 00 73 00 a.m.b.o.d.q.f.s.
0000003E0:  68 00 75 00 6D 00 77 00 6F 00 79 00 71 00 7B 00 h.u.m.w.o.y.q.{.
0000003F0:  73 00 7D 00 75 00 7E 00 77 00 80 00 79 00 81 00 s.}.u.~.w..y..
000000400:  7B 00 83 00 7C 00 86 00 7E 00 89 00 80 00 8B 00 {.&#402;.|.&#8224;.~.&#8240;..&#8249;.
000000410:  84 00 8D 00 85 00 8F 00 86 00 91 00 88 00 93 00 &#8222;..&#8230;..&#8224;.&#8216;.&#710;.&#8220;.
000000420:  89 00 95 00 8B 00 97 00 8C 00 99 00 93 00 9B 00 &#8240;.&#8226;.&#8249;.&#8212;..&#8482;.&#8220;.&#8250;.
000000430:  94 00 9C 00 28 08 00 00 31 08 00 00 3F 08 00 00 &#8221;..(...1...?...
000000440:  51 08 00 00 66 08 00 00 7F 08 00 00 9C 08 00 00 Q...f.........
000000450:  BB 08 00 00 DF 08 00 00 06 09 00 00 30 09 00 00 ..........0...
000000460:  5E 09 00 00 91 09 00 00 C8 09 00 00 03 0A 00 00 ^...&#8216;..........
000000470:  42 0A 00 00 86 0A 00 00 CC 0A 00 00 11 0B 00 00 B...&#8224;..........
000000480:  5E 0B 00 00 AF 0B 00 00 03 0C 00 00 5A 0C 00 00 ^..........Z...
000000490:  B4 0C 00 00 10 0D 00 00 6E 0D 00 00 C9 0D 00 00 .......n......
0000004A0:  24 0E 00 00 85 0E 00 00 E4 0E 00 00 43 0F 00 00 $...&#8230;......C...
0000004B0:  A2 0F 00 00 01 10 00 00 5B 10 00 00 B7 10 00 00 .......[......
0000004C0:  14 11 00 00 6E 11 00 00 CC 11 00 00 2C 12 00 00 ....n......,...
0000004D0:  8A 12 00 00 E3 12 00 00 3F 13 00 00 99 13 00 00 ......?...&#8482;...
0000004E0:  F3 13 00 00 4F 14 00 00 A8 14 00 00 05 15 00 00 ...O..........
0000004F0:  5D 15 00 00 B4 15 00 00 05 16 00 00 59 16 00 00 ]..........Y...
000000500:  AF 16 00 00 08 17 00 00 5F 17 00 00 B8 17 00 00 ......._......
000000510:  06 18 00 00 56 18 00 00 A4 18 00 00 F8 18 00 00 ....V.........
000000520:  50 19 00 00 A7 19 00 00 07 1A 00 00 68 1A 00 00 P..........h...
000000530:  BC 1A 00 00 13 1B 00 00 6C 1B 00 00 C1 1B 00 00 .......l......
000000540:  1D 1C 00 00 72 1C 00 00 C6 1C 00 00 20 1D 00 00 ....r...... ...
000000550:  6D 1D 00 00 C2 1D 00 00 11 1E 00 00 61 1E 00 00 m..........a...
000000560:  B0 1E 00 00 05 1F 00 00 56 1F 00 00 AC 1F 00 00 .......V......
000000570:  04 20 00 00 63 20 00 00 CA 20 00 00 3A 21 00 00 . ..c .. ..:!..
000000580:  AC 21 00 00 18 22 00 00 82 22 00 00 FA 22 00 00 !..."..&#8218;".."..
000000590:  75 23 00 00 F4 23 00 00 78 24 00 00 FC 24 00 00 u#..#..x$..$..
0000005A0:  81 25 00 00 05 26 00 00 8F 26 00 00 18 27 00 00 %...&..&...'..
0000005B0:  A4 27 00 00 35 28 00 00 CD 28 00 00 66 29 00 00 '..5(..(..f)..
0000005C0:  01 2A 00 00 9F 2A 00 00 3F 2B 00 00 DF 2B 00 00 .*..*..?+..+..
0000005D0:  86 2C 00 00 32 2D 00 00 E3 2D 00 00 91 2E 00 00 &#8224;,..2-..-..&#8216;...
0000005E0:  41 2F 00 00 F4 2F 00 00 A6 30 00 00 5D 31 00 00 A/../..0..]1..
0000005F0:  13 32 00 00 CE 32 00 00 89 33 00 00 4A 34 00 00 .2..2..&#8240;3..J4..
000000600:  0D 35 00 00 D3 35 00 00 9C 36 00 00 65 37 00 00 .5..5..6..e7..
000000610:  2E 38 00 00 F9 38 00 00 C5 39 00 00 94 3A 00 00 .8..8..9..&#8221;:..
000000620:  6B 3B 00 00 42 3C 00 00 1E 3D 00 00 FF 3D 00 00 k;..B<...=..=..
000000630:  E2 3E 00 00 C7 3F 00 00 B0 40 00 00 9A 41 00 00 >..?..@..A..
000000640:  8A 42 00 00 78 43 00 00 6B 44 00 00 5E 45 00 00 B..xC..kD..^E..
000000650:  58 46 00 00 58 47 00 00 5C 48 00 00 64 49 00 00 XF..XG..\H..dI..
000000660:  63 4A 00 00 60 4B 00 00 6C 4C 00 00 77 4D 00 00 cJ..`K..lL..wM..
000000670:  87 4E 00 00 90 4F 00 00 A8 50 00 00 C2 51 00 00 &#8225;N..O..P..Q..
000000680:  DF 52 00 00 FC 53 00 00 1C 55 00 00 3F 56 00 00 R..S...U..?V..
000000690:  60 57 00 00 81 58 00 00 A0 59 00 00 BA 5A 00 00 `W..X.. Y..Z..
0000006A0:  DB 5B 00 00 00 5D 00 00 1F 5E 00 00 3C 5F 00 00 [...]...^..<_..
0000006B0:  5E 60 00 00 7A 61 00 00 90 62 00 00 93 63 00 00 ^`..za..b..&#8220;c..
0000006C0:  96 64 00 00 97 65 00 00 97 66 00 00 92 67 00 00 &#8211;d..&#8212;e..&#8212;f..&#8217;g..
0000006D0:  8A 68 00 00 80 69 00 00 71 6A 00 00 67 6B 00 00 h..i..qj..gk..
0000006E0:  59 6C 00 00 3F 6D 00 00 1F 6E 00 00 01 6F 00 00 Yl..?m...n...o..
0000006F0:  E3 6F 00 00 C0 70 00 00 9C 71 00 00 76 72 00 00 o..p..q..vr..
000000700:  4F 73 00 00 27 74 00 00 F9 74 00 00 CC 75 00 00 Os..'t..t..u..
000000710:  9B 76 00 00 68 77 00 00 3A 78 00 00 02 79 00 00 &#8250;v..hw..:x...y..
000000720:  CC 79 00 00 8D 7A 00 00 45 7B 00 00 F8 7B 00 00 y..z..E{..{..
000000730:  A3 7C 00 00 4A 7D 00 00 EB 7D 00 00 8C 7E 00 00 |..J}..}..~..
000000740:  27 7F 00 00 BE 7F 00 00 4F 80 00 00 E2 80 00 00 '....O....
000000750:  76 81 00 00 0D 82 00 00 9F 82 00 00 36 83 00 00 v...&#8218;..&#8218;..6&#402;..
000000760:  C6 83 00 00 56 84 00 00 E7 84 00 00 6C 85 00 00 &#402;..V&#8222;..&#8222;..l&#8230;..
000000770:  EE 85 00 00 66 86 00 00 E3 86 00 00 5A 87 00 00 &#8230;..f&#8224;..&#8224;..Z&#8225;..
000000780:  D2 87 00 00 4F 88 00 00 CA 88 00 00 43 89 00 00 &#8225;..O&#710;..&#710;..C&#8240;..
000000790:  BA 89 00 00 2C 8A 00 00 A2 8A 00 00 17 8B 00 00 &#8240;..,.....&#8249;..
0000007A0:  8E 8B 00 00 03 8C 00 00 72 8C 00 00 DC 8C 00 00 &#8249;.....r..ܼ..
0000007B0:  3A 8D 00 00 97 8D 00 00 FC 8D 00 00 5B 8E 00 00 :..&#8212;....[..
0000007C0:  BE 8E 00 00 1E 8F 00 00 7B 8F 00 00 D5 8F 00 00 .....{....
0000007D0:  28 90 00 00 84 90 00 00 D5 90 00 00 1D 91 00 00 (..&#8222;.....&#8216;..
0000007E0:  65 91 00 00 AA 91 00 00 EE 91 00 00 2E 92 00 00 e&#8216;..&#8216;..&#8216;...&#8217;..
0000007F0:  60 92 00 00 89 92 00 00 B5 92 00 00 DB 92 00 00 `&#8217;..&#8240;&#8217;..&#8217;..&#8217;..
000000800:  F8 92 00 00 21 93 00 00 44 93 00 00 64 93 00 00 &#8217;..!&#8220;..D&#8220;..d&#8220;..
000000810:  7B 93 00 00 93 93 00 00 A9 93 00 00 BB 93 00 00 {&#8220;..&#8220;&#8220;..&#8220;..&#8220;..
000000820:  CA 93 00 00 D1 93 00 00 1C 38 38 38 2C 2F 99 2F &#8220;..&#8220;...888,/&#8482;/
000000830:  0F 30 0D 28 B6 95 38 2F 2F 2F 2C 2F 2C 2C 0F 40 .0.(&#8226;8///,/,,.@
000000840:  0B 81 95 99 2C 2F 2F 81 2C 38 38 2F 2C 2F 2C 2C .&#8226;&#8482;,//,88/,/,,
000000850:  0F 4C 0D 28 95 99 2C 38 2F 99 99 99 3C 3C 2F 99 .L.(&#8226;&#8482;,8/&#8482;&#8482;&#8482;<</&#8482;
000000860:  99 99 2F 2F 2C 0F 5C 28 81 95 95 28 99 2F 38 99 &#8482;&#8482;//,.\(&#8226;&#8226;(&#8482;/8&#8482;
000000870:  2C 99 A2 28 2F A1 38 2C 99 99 2C 2F 38 38 0F 6C ,&#8482;(/8,&#8482;&#8482;,/88.l
000000880:  2C 97 97 28 95 81 28 2C 99 2F 3C 95 2F 99 A8 2F ,&#8212;&#8212;(&#8226;(,&#8482;/<&#8226;/&#8482;/
000000890:  2C 2F A0 3C 99 99 99 2C 2F 2C A2 0F 74 97 99 0D ,/ <&#8482;&#8482;&#8482;,/,.t&#8212;&#8482;.
0000008A0:  81 95 2C 2C 99 28 28 2F 2F 95 3C 38 3C 2F 2F 28 &#8226;,,&#8482;((//&#8226;<8<//(
0000008B0:  2C 3C A2 2F 28 2C 9C 3C 3C 9C 0F 88 81 28 0B 0B ,</(,<<.&#710;(..
0000008C0:  81 B6 81 B6 99 99 95 2F A1 2F 99 2F A8 A2 2F 2F &#8482;&#8482;&#8226;//&#8482;///
0000008D0:  99 81 0D 3C 4B 3C 2C 2C 2C A0 3C 2C 2C 2C 0F 94 &#8482;.<K<,,, <,,,.&#8221;
0000008E0:  0D 95 B6 80 0B 1B 1B 97 99 2C 95 99 99 A1 A1 99 .&#8226;...&#8212;&#8482;,&#8226;&#8482;&#8482;&#8482;
0000008F0:  81 28 A2 4B 3C 2C 28 99 95 0D 38 4D A2 2F 2C 2C (K<,(&#8482;&#8226;.8M/,,
000000900:  2F A1 2F 2F 38 0F 0C 95 28 99 47 95 88 99 0D 2C ///8..&#8226;(&#8482;G&#8226;&#710;&#8482;.,
000000910:  2C 99 99 2C A2 3C 99 81 B6 2F 4B A2 2F 4B 2F 2F ,&#8482;&#8482;,<&#8482;/K/K//
000000920:  81 B6 2C A1 A2 2F 2C 2C 9C 3C 2F A0 2C 2C 2F 0F ,/,,</ ,,/.
000000930:  9C 0D 2C 0D B6 97 99 99 28 2F 28 2F 28 28 99 28 .,.&#8212;&#8482;&#8482;(/(/((&#8482;(
000000940:  2F A2 2F 2C 81 95 99 A2 4D 2F 2F 28 2C 2C 81 80 //,&#8226;&#8482;M//(,,
000000950:  28 38 3C 28 81 0D 2F 99 47 2C 08 2F 3C 0F C4 81 (8<(./&#8482;G,./<.
000000960:  2C 99 99 1B 95 99 2C 2C 0D 81 3C A1 3C 38 99 28 ,&#8482;&#8482;.&#8226;&#8482;,,.<<8&#8482;(
000000970:  2F A1 2C 2C 95 99 81 A1 A8 4B 9C 2C A0 2F 2F 0D /,,&#8226;&#8482;K, //.
000000980:  81 B6 95 2F 2C 28 81 99 A0 2C 38 83 2C 2F 3C 2F &#8226;/,(&#8482; ,8&#402;,/</
000000990:  0F D4 28 2C 0D 99 97 99 95 95 0D 99 82 99 2C 0D .(,.&#8482;&#8212;&#8482;&#8226;&#8226;.&#8482;&#8218;&#8482;,.
0000009A0:  2F 38 2C 2F 2C 38 2F 2F 2F A0 95 B6 2F A8 A8 2F /8,/,8/// &#8226;//
0000009B0:  2F 3C 2C 82 A1 2C 2F 4D 2F 3C 4B 2F 2C 2F 2C 2F /<,&#8218;,/M/<K/,/,/
0000009C0:  A8 2F 2C 2F 3C 2F 38 0F E4 81 95 81 2C 2C 99 99 /,/</8.&#8226;,,&#8482;&#8482;
0000009D0:  97 95 2C 38 38 2C 3C 38 38 2F 2F 2F 99 B6 B6 0B &#8212;&#8226;,88,<88///&#8482;.
0000009E0:  0B 2F 2F 2F 99 0B 4B AC A1 2F 2F 4D 2C 4B 38 0D .///&#8482;.K//M,K8.
0000009F0:  A1 A2 2C 2C 4D A2 3C 2F 3C A2 49 49 2C 2F 2C 2C ,,M</<II,/,,
000000A00:  99 2C 0F F4 2F 0D 0B 0B 99 99 95 95 95 28 0D 2F &#8482;,./...&#8482;&#8482;&#8226;&#8226;&#8226;(./
000000A10:  99 99 9C 3C 2C 99 2F 81 38 99 3C 9C 99 95 A1 A0 &#8482;&#8482;<,&#8482;/8&#8482;<&#8482;&#8226; 
000000A20:  2F 2C 0B 2F A8 4D 3C 3C A8 4B 38 A6 A2 0D 99 2F /,./M<<K8.&#8482;/
000000A30:  81 2F 4D A1 3C 3C 38 A2 2F 2C 2F 2C 2F 38 38 38 /M<<8/,/,/888
000000A40:  3C 0F 02 41 2D 2C 2C 0D 97 81 99 95 97 99 0D 81 <..A-,,.&#8212;&#8482;&#8226;&#8212;&#8482;.
000000A50:  B6 3C 2F 2C 2F 2F 99 0D 2F 38 99 99 2F 2C 2C 99 </,//&#8482;./8&#8482;&#8482;/,,&#8482;
000000A60:  A1 A0 2F 2C 2C B6 A2 A8 A1 3C A2 2C 2F 2C 38 4D  /,,<,/,8M
000000A70:  4B 3C 49 81 2F A2 2C 38 38 A2 A8 2F 83 83 2C 3C K<I/,88/&#402;&#402;,<
000000A80:  A1 A2 A2 38 4C 0F 02 43 2C 2C 2C 28 0D 97 B6 95 8L..C,,,(.&#8212;&#8226;
000000A90:  0D 0D 81 0B 95 2F 2F 38 2C 3C 2C 2C 2F 2C 99 2F ...&#8226;//8,<,,/,&#8482;/
000000AA0:  99 81 2C 3C 99 0D 99 2C A2 2F 81 2C 38 95 28 83 &#8482;,<&#8482;.&#8482;,/,8&#8226;(&#402;
000000AB0:  A2 38 3C 49 38 82 49 4D 2F B6 DA 38 AC A2 2C 38 8<I8&#8218;IM/8,8
000000AC0:  A2 A1 2F 2C 2C 2C 2F 83 A2 4C 38 0F F4 81 2C 28 /,,,/&#402;L8.,(
000000AD0:  1B 95 99 99 95 B6 81 81 A2 A2 2F 28 2F 2F 3C A1 .&#8226;&#8482;&#8482;&#8226;/(//<
000000AE0:  99 99 A6 4D 2F 0D 99 38 3C 3C 2C 99 3C A8 A1 2F &#8482;&#8482;M/.&#8482;8<<,&#8482;</
000000AF0:  2F 81 2C 2F 2F A2 38 A2 2F 38 AC 4D 2C A1 A1 49 /,//8/8M,I
000000B00:  A2 83 A2 2C A8 A2 38 A1 3C 99 77 2F 0C 2C 99 82 &#402;,8<&#8482;w/.,&#8482;&#8218;
000000B10:  0F 02 4A 2C 28 81 95 99 2C 2C 2C 99 28 97 2F A2 ..J,(&#8226;&#8482;,,,&#8482;(&#8212;/
000000B20:  0D 2F 49 38 81 99 A2 2F 2C 3C 4D 3C 3C 3C 2F 9C ./I8&#8482;/,<M<<</
000000B30:  3C 2C 2C A2 2F 4D 49 2F 2F 4D 4B 2F 2F 3C 99 A1 <,,/MI//MK//<&#8482;
000000B40:  A1 2F A8 AC 3C 2C A1 4B 2F A8 4D A8 A6 4D 4D A2 /<,K/MMM
000000B50:  38 2C 2C 99 9C 3C 2F 2C 9C 99 0D 0D 38 0F 02 4E 8,,&#8482;</,&#8482;..8..N
000000B60:  0D 99 0D 95 1B 99 99 2C 0D 81 0D 2C 95 38 38 99 .&#8482;.&#8226;.&#8482;&#8482;,..,&#8226;88&#8482;


Allereest krijgen we weer te maken met allerlei onnozele data (waarom die niet wegfilteren?) zoals versie (4 bytes), frameAmount (een long, deze is wel nuttig!) en een string van 24 bytes zonder zinnige data erin.
Dat ook weer gehad en dus is het tijd voor de frameHeaders. Deze komen meteen achter de slpHeader en bestaan weer uit allerlei longs. De longs zijn: commandOffset, outlineOffset, palletteOffset, properties, width, height, anchorPosX, anchorPosY.
De commandOffset en outlineOffset kom ik later nog op terug. De palletteOffset en properties snap ik nog niet helemaal, maar heeft denk ik te maken met pallettes. Width en height is obvious en dan hebben we nog anchorPosX en anchorPosY. Deze twee longs bepalen het fixed point van de image. Elke image is van andere hoogte (om data te besparen) en om te voorkomen dat units 'op en neer stuiteren' is er een fixed point. Als er dus een unit op positie 5,5 staat zal deze pixel waar anchorPosX en anchorPosY naar verwijzen daar exact staan.

Elk frame bestaat uit meerdere rijen (obvious). En bij slp heeft men besloten (om ruimte te besparen) om daar iets speciaals mee te doen: Elke rij heeft een eigen lengte en begint op een bepaald stuk. Na het uitlezen van alle frameHeaders komt de frameContent. Daarin staan dus die 'rijlengten'. Ze worden opgegeven als offsetLeft (short) en offsetRight (short). Hiermee is beginpunt offsetLeft en lengte frameWidth - offsetLeft - offsetRight. OutlineOffset verwijst dus naar dit stuk aan data (de data geeft immers de outline aan)
Na deze offsets komt nog de commandOffset. Dit is echter een verwijzing naar een lijst aan longs (lengte van de lijst is gelijk aan de frameHeight) welke aangeven waar de data voor elke rij begint.
Hierna volgt nog een bulk aan frameData waar ik het straks over ga hebben.

Ik gebruik hiervoor de volgende code:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
br.ReadBytes(4); // skip useless data
int frameAmount = br.ReadInt32();
br.ReadBytes(24); // skip useless data

SlpFile slpFile = new SlpFile(frameAmount);        

// read out all the frame headers (which are all just after each other)
for (int i = 0; i < frameAmount; i++)
{
    uint commandOffset = br.ReadUInt32();
    uint outlineOffset = br.ReadUInt32();
    uint paletteOffset = br.ReadUInt32();
    uint properties = br.ReadUInt32();
    uint width = br.ReadUInt32();
    uint height = br.ReadUInt32();
    uint ancherPosX = br.ReadUInt32();
    uint ancherPosY = br.ReadUInt32();

    slpFile.frames[i] = new SlpFrame(commandOffset, outlineOffset, paletteOffset, properties, width, height, ancherPosX, ancherPosY);
}
// read out each frame
for (int i = 0; i < frameAmount; i++)
{
    // read out all the row lengths (which are all just after each other)
    for (int ii = 0; ii < slpFile.frames[i].height; ii++)
    {
        slpFile.frames[i].rowedges[ii] = new uint[2] {br.ReadUInt16(), br.ReadUInt16()};
    }
    // read out for each row the commandTableOffset
    int[] commandTableOffsets = new int[slpFile.frames[i].height];
    for (int ii = 0; ii < slpFile.frames[i].height; ii++)
    {
        commandTableOffsets[ii] = br.ReadInt32();
    }


    if (i == slpFile.frames.Length - 1)
    {
        slpFile.frames[i].commands = br.ReadBytes((int) (br.BaseStream.Length - (slpFile.frames[i].commandOffset + 4 * slpFile.frames[i].height)));
    }
    else
    {
        slpFile.frames[i].commands = br.ReadBytes((int) (slpFile.frames[i + 1].outlineOffset - (slpFile.frames[i].commandOffset + 4 * slpFile.frames[i].height)));
    }
}



Heel leuk en aardig allemaal, maar nog steeds geen terrain :(. Dus tijd om te gaan tekenen... En dit vond ik dus heel lastig.
Slp bestanden zijn geen animated gifs ofzo, het zijn ook geen bitmaps. Nee, om ruimte te besparen hebben ze een hele nieuwe soort image bedacht.
Bij slp wordt , voor het tekenen, gewerkt met commands. Deze commands bestaan uit drie delen: commandType, commandLength/Value, commandData. Niet alle commands hebben commandData. De commands dienen voor o.a. het inkleuren van pixels, maken van masks (als een unit achter een gebouw staat), shadows maar ook transparantie. Bij terrain wordt echter alleen ingekleurd en dus hoefde ik die andere commands nog niet helemaal door te werken...
Zoals ik zei wordt er zuinig gedaan met data. Dit is vooral hier duidelijk te zien:
In het voorbeeld beginnen de commands op positie 0x828. Op de eerste regel van de afbeelding is te zien dat er 7 pixels moeten worden getekend. Verder kon ik uit de beschrijving halen dat er twee commando's waren voor het tekenen van pixels. De eerste is 0x00 en de tweede is 0x02. Echter, de eerste byte is 0x1C en is dus niet zo'n command.
Wat blijkt (om ruimte te besparen), heeft men besloten dat de twee laatste bits in dat geval aangeven wat het commando is en de andere bits geven aan wat de commandLength is. Oftewel een command 0x00byte is in feite xxxxxx00. (ja dit duurde effe voordat ik dit doorhad...) In het geval van mij moest dit dus zijn 00011100 en jawel, dat is 0x1C.
Men dit commando kan dus maximaal 2^6 = 64 pixels worden ingekleurd. Tiles zijn 97 pixels breed, dus er was nog een commando nodig. Ik wist dat er nog een commando was welke dus hier waarschijnlijk voor bedoeld was. Hier is waarschijnlijk de commandLength opgeslagen in de volgende byte.
De commandLength geeft dus aan hoeveel pixels er moeten worden gekleurd. Nu moet de kleur van de pixel ook ergens staan opgeslagen. Omdat AoE een 256 color game is ging ik er van uit dat dit dus pallette entries zijn welke n byte groot zijn.
Ik wist van de beschrijving dat er aan het einde van elke regel een end of row command staat (0x0F) en jawel na 7 bytes stond deze er. Dat klopte dus en ik wist welke pallette entries de pixels waren. Helaas niet de kleur:
http://img845.imageshack.us/img845/7661/aoe012011093023125557.png

Daarvoor moest ik opzoek naar een ander bestand en deze vond ik in interfac.drs:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Offset hex. 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
000000000:  4A 41 53 43 2D 50 41 4C 0D 0A 30 31 30 30 0D 0A JASC-PAL..0100..
000000010:  32 35 36 0D 0A 30 20 30 20 30 0D 0A 30 20 37 34 256..0 0 0..0 74
000000020:  20 31 36 31 0D 0A 30 20 39 37 20 31 35 35 0D 0A  161..0 97 155..
000000030:  30 20 37 34 20 31 38 37 0D 0A 30 20 38 34 20 31 0 74 187..0 84 1
000000040:  37 36 0D 0A 30 20 39 30 20 31 38 34 0D 0A 30 20 76..0 90 184..0 
000000050:  31 31 30 20 31 37 36 0D 0A 30 20 31 31 30 20 31 110 176..0 110 1
000000060:  38 37 0D 0A 31 38 30 20 32 35 35 20 31 38 30 0D 87..180 255 180.
000000070:  0A 30 20 39 38 20 32 31 30 0D 0A 30 20 30 20 30 .0 98 210..0 0 0
000000080:  0D 0A 34 37 20 34 37 20 34 37 0D 0A 32 30 30 20 ..47 47 47..200 
000000090:  32 31 36 20 32 35 35 0D 0A 38 37 20 38 37 20 38 216 255..87 87 8
0000000A0:  37 0D 0A 33 37 20 31 36 20 36 0D 0A 34 37 20 32 7..37 16 6..47 2
0000000B0:  36 20 31 37 0D 0A 30 20 30 20 38 32 0D 0A 30 20 6 17..0 0 82..0 
0000000C0:  32 31 20 31 33 30 0D 0A 31 39 20 34 39 20 31 36 21 130..19 49 16
0000000D0:  31 0D 0A 34 38 20 39 33 20 31 38 32 0D 0A 37 34 1..48 93 182..74
0000000E0:  20 31 32 31 20 32 30 38 0D 0A 31 31 30 20 31 36  121 208..110 16
0000000F0:  36 20 32 33 35 0D 0A 31 35 31 20 32 30 36 20 32 6 235..151 206 2
000000100:  35 35 0D 0A 32 30 35 20 32 35 30 20 32 35 35 0D 55..205 250 255.
000000110:  0A 36 34 20 34 33 20 32 33 0D 0A 36 37 20 35 31 .64 43 23..67 51
000000120:  20 32 37 0D 0A 37 30 20 33 32 20 36 0D 0A 37 35  27..70 32 6..75
000000130:  20 35 37 20 34 32 0D 0A 38 34 20 36 34 20 34 33  57 42..84 64 43
000000140:  0D 0A 38 37 20 36 39 20 33 37 0D 0A 38 37 20 35 ..87 69 37..87 5
000000150:  37 20 32 37 0D 0A 39 34 20 37 34 20 34 38 0D 0A 7 27..94 74 48..
000000160:  36 35 20 30 20 30 0D 0A 31 30 35 20 31 31 20 30 65 0 0..105 11 0
000000170:  0D 0A 31 36 30 20 32 31 20 30 0D 0A 32 33 30 20 ..160 21 0..230 
000000180:  31 31 20 30 0D 0A 32 35 35 20 30 20 30 0D 0A 32 11 0..255 0 0..2
000000190:  35 35 20 31 30 30 20 31 30 30 0D 0A 32 35 35 20 55 100 100..255 
0000001A0:  31 36 30 20 31 36 30 0D 0A 32 35 35 20 32 32 30 160 160..255 220
0000001B0:  20 32 32 30 0D 0A 39 37 20 37 37 20 36 37 0D 0A  220..97 77 67..
0000001C0:  31 30 33 20 35 38 20 32 31 0D 0A 31 31 33 20 37 103 58 21..113 7
0000001D0:  35 20 35 31 0D 0A 31 31 33 20 37 35 20 31 33 0D 5 51..113 75 13.
0000001E0:  0A 31 31 35 20 31 30 35 20 38 34 0D 0A 31 32 35 .115 105 84..125
0000001F0:  20 39 37 20 37 32 0D 0A 31 32 35 20 37 34 20 30  97 72..125 74 0
000000200:  0D 0A 31 32 39 20 31 31 36 20 39 35 0D 0A 30 20 ..129 116 95..0 
000000210:  30 20 30 0D 0A 30 20 37 20 30 0D 0A 30 20 33 32 0 0..0 7 0..0 32
000000220:  20 30 0D 0A 30 20 35 39 20 30 0D 0A 30 20 38 37  0..0 59 0..0 87
000000230:  20 30 0D 0A 30 20 31 31 34 20 30 0D 0A 30 20 31  0..0 114 0..0 1
000000240:  34 31 20 30 0D 0A 30 20 31 36 39 20 30 0D 0A 31 41 0..0 169 0..1
000000250:  33 34 20 31 32 36 20 31 31 38 0D 0A 31 33 35 20 34 126 118..135 
000000260:  36 34 20 30 0D 0A 31 33 36 20 31 30 38 20 37 39 64 0..136 108 79
000000270:  0D 0A 31 34 34 20 31 30 30 20 31 32 0D 0A 31 34 ..144 100 12..14
000000280:  36 20 31 32 35 20 31 30 35 0D 0A 31 35 33 20 31 6 125 105..153 1
000000290:  30 36 20 35 35 0D 0A 31 35 39 20 31 32 31 20 38 06 55..159 121 8
0000002A0:  38 0D 0A 31 36 36 20 37 34 20 30 0D 0A 38 30 20 8..166 74 0..80 
0000002B0:  35 31 20 32 36 0D 0A 31 34 30 20 37 38 20 39 0D 51 26..140 78 9.
0000002C0:  0A 31 39 31 20 31 32 33 20 30 0D 0A 32 35 35 20 .191 123 0..255 
0000002D0:  31 39 39 20 30 0D 0A 32 35 35 20 32 34 37 20 33 199 0..255 247 3
0000002E0:  37 0D 0A 32 35 35 20 32 35 35 20 39 37 0D 0A 32 7..255 255 97..2
0000002F0:  35 35 20 32 35 35 20 31 36 36 0D 0A 32 35 35 20 55 255 166..255 
000000300:  32 35 35 20 32 32 37 0D 0A 31 36 37 20 31 33 35 255 227..167 135
000000310:  20 31 30 32 0D 0A 31 37 32 20 31 34 34 20 31 31  102..172 144 11
000000320:  35 0D 0A 31 37 35 20 31 32 36 20 33 36 0D 0A 31 5..175 126 36..1
000000330:  37 35 20 31 35 31 20 31 32 38 0D 0A 31 38 35 20 75 151 128..185 
000000340:  31 35 31 20 31 34 36 0D 0A 31 38 36 20 31 36 36 151 146..186 166
000000350:  20 31 33 35 0D 0A 31 38 37 20 38 34 20 30 0D 0A  135..187 84 0..
000000360:  31 38 37 20 31 35 36 20 31 32 35 0D 0A 31 31 30 187 156 125..110
000000370:  20 32 33 20 30 0D 0A 31 35 30 20 33 36 20 30 0D  23 0..150 36 0.
000000380:  0A 32 31 30 20 35 35 20 30 0D 0A 32 35 35 20 38 .210 55 0..255 8
000000390:  30 20 30 0D 0A 32 35 35 20 31 33 30 20 31 0D 0A 0 0..255 130 1..
0000003A0:  32 35 35 20 31 38 30 20 32 31 0D 0A 32 35 35 20 255 180 21..255 
0000003B0:  32 31 30 20 37 35 0D 0A 32 35 35 20 32 33 35 20 210 75..255 235 
0000003C0:  31 36 30 0D 0A 31 38 39 20 31 35 30 20 31 31 31 160..189 150 111


In het .drs bestand staat dat in de tabel bin files moeten staan. Maar al snel kan je zien dat dat dus niet het geval is (wie dit bestandsformaat heeft bedacht... :S). Men heeft in alle wijsheid besloten om er een textbestand in te zetten. Ok, even goede vrienden...
Iig, begint het bestand met een beschrijving, gevolgd door onbekende data en dan weer gevolgd door het aantal kleuren. Hierna volgen elke keer RGB waarden. Spreekt voor zich toch?

Nu ik ook deze data had kon ik eindelijk een SLP image tekenen:
http://img809.imageshack.us/img809/9449/aoe012011093023155756.png

Nu is het tijd om te gaan blenden. Zoals ik eerder al had gezegd loopt terrain in elkaar over en als dat gebeurd wordt door middel van masks gealphablend. Hoe dit precies werkte had ik geloof ik al in post 0x00 uitgelegd. Dus dat laat ik achterwege...
Iig, het werkt niet:
http://img716.imageshack.us/img716/1381/aoemaskfailure.png
Zonder blending:
http://img823.imageshack.us/img823/4785/aoenomask.png

XNA blend de image terug naar de kleur die ik gebruik voor het tekenen van de image (Color(256, 256, 256, 256)). Ik weet niet hoe ik dit oplos. Elke keer als ik ernaar zoek op internet zegt men dat het 'vanzelf' gaat (niet dus!).
Ik kan mijn code niet posten ivm met: [TweakBlogs] Postlengtelimiet

Ik laat het denk ik maar hierbij laat. Ben met nog meer bezig (zoals masks) maar dat komt een andere keer wel weer... Was dit (enigszins) interessant?

Volgende: Post 0x01 09-'11 Post 0x01

Reacties


Door Tweakers user Tommasso, zondag 2 oktober 2011 10:03

Code (screw you postlimit!):

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
int col, row;
int scrX, scrY, mapX, mapY;
int terrainTypeFrameIndex;


// start drawing!
scrX = draw_startScrX;
scrY = draw_startScrY;
mapX = draw_startMapX;
mapY = draw_startMapY;
int i;
for (i = 0; i < 2; i++)
{
    for (col = 0; scrX < screenWidth; col++)
    {
        for (row = 0; scrY < screenHeight; row++)
        {
            if (mapX >= 0 && mapX < map.GetLength(0) && mapY >= 0 && mapY < map.GetLength(1))
            {
                terrainTypeFrameIndex = mapY % 10 * 10 + mapX % 10;
                spriteBatch.Draw(textures[terrainTypes[map[mapX, mapY]].slp].frames[terrainTypeFrameIndex], new Vector2(scrX, scrY), Color.White);

                // check for neighbours
                List<int> prioritiesList = new List<int>();
                List<int> neighbourTypesList = new List<int>();
                int[,] neighbours = new int[3, 3];

                for (int j = 0; j < 3; j++)
                {
                    for (int jj = 0; jj < 3; jj++)
                    {
                        if (j + mapX - 1 >= 0 && j + mapX - 1 < map.GetLength(0) && jj + mapY - 1 >= 0 && jj + mapY - 1 < map.GetLength(1))
                        {
                            if (terrainTypes[map[j + mapX - 1, jj + mapY - 1]].priority > terrainTypes[map[mapX, mapY]].priority)
                            {
                                prioritiesList.Add(terrainTypes[map[j + mapX - 1, jj + mapY - 1]].priority);
                                neighbourTypesList.Add(map[j + mapX - 1, jj + mapY - 1]);
                            }
                            neighbours[j, jj] = map[j + mapX - 1, jj + mapY - 1];
                        }
                        else{
                            neighbours[j, jj] = map[mapX, mapY];
                        }
                    }
                }

                int[] priorities = prioritiesList.ToArray();
                int[] neighbourTypes = neighbourTypesList.ToArray();
                Array.Sort(neighbourTypes, priorities);
                for (int ii = 0; ii < neighbourTypes.Length; ii++)
                {
                    int direction = getDirection(neighbours, neighbourTypes[ii], new int[2] { mapX, mapY });
                    int[] mask = blendMasks[terrainTypes[map[mapX, mapY]].blendmode][direction];
                    Color[] colors = drawSlpFile(terrainTypes[neighbourTypes[ii]].slp, terrainTypeFrameIndex, 0);

                    // start blending
                    int rowWidth = 1;
                    int pos = 0;
                    bool half = false;
                    for (int imageRow = 0; imageRow < 49; imageRow++)
                    {

                        int xOffset = 48 - rowWidth / 2;
                        for (int imageCol = xOffset; imageCol < xOffset + rowWidth; imageCol++)
                        {
                            colors[imageRow * 97 + imageCol].A = (byte)((127 - mask[pos] / 128f * 127) * 2);
                            pos++;
                        }
                        if (rowWidth == 97)
                        {
                            half = true;
                        }
                        if (half == false) rowWidth += 4;
                        else rowWidth -= 4;
                    }

                    Texture2D texture = new Texture2D(device, 97, 49, false, SurfaceFormat.Color);
                    texture.SetData(colors);
                    spriteBatch.Draw(texture, new Vector2(scrX, scrY), new Color(256, 256, 256, 256));
                }
                spriteBatch.DrawString(font, mapX + " " + mapY, new Vector2(scrX + 30, scrY + 15), Color.Red);
                spriteBatch.DrawString(font, terrainTypeFrameIndex + "", new Vector2(scrX + 30, scrY + 25), Color.Red);
            }
            scrY += imageHeight;
            mapX--;
            mapY++;
        }
        scrX += imageWidth;
        scrY -= imageHeight * row;
        mapX += row + 1;
        mapY -= row - 1;
    }
    scrX = draw_startScrX + imageWidth / 2;
    scrY = draw_startScrY - imageHeight / 2;
    mapX = draw_startMapX + 1;
    mapY = draw_startMapY;
}
spriteBatch.End();


Reageren is niet meer mogelijk