broken seed computer is the same as invisible one
[spelunky_yasmk8.git] / tools / yasmdatdecode.d
blobde65c80d69ed321ebea9ab4ed8e9b57addcdd658
1 module yasmdatdecode is aliced;
3 import std.stdio;
5 string scrCipher (string textStr1, usize key, bool encrypt=false) {
6 //while (textStr1.length > 0 && textStr1[0] <= ' ') textStr1 = textStr1[1..$];
7 //while (textStr1.length > 0 && textStr1[$-1] <= ' ') textStr1 = textStr1[0..$-1];
8 string keyStr1;
9 // each score slot uses a unique encryption key (ONLY USE ASCII CHARACTERS 32-125)
10 final switch (key%10) {
11 case 0: keyStr1 = r"F&-RlbkW{,1]DY|)8>b|FNMh@q]nnV.3"; break; //"
12 case 1: keyStr1 = r"U=O=+>=BXNswc=%TJY;3tI^|&2kot7UG"; break; //"
13 case 2: keyStr1 = r"&kdJ(ga^\c&PTNRJ?eNlVQD|VOMiX}s+"; break; //"
14 case 3: keyStr1 = r"|!n4@OQ.<&Q/K\kEo-:o+>?qsK1t7N&O"; break; //"
15 case 4: keyStr1 = r"3rRZ!<<]8r=<X2:Q$)&=f_%o`\h-c,7i"; break; //`
16 case 5: keyStr1 = r"y{BKQJE+()<?{jmD+.Owek{Hk;BN[OP)"; break; //"
17 case 6: keyStr1 = r"v|L2GV;yl{90_I(e?cHX3^0a}I(kU(dR"; break; //"
18 case 7: keyStr1 = r"TkuG%K}?l{r_tZ=,fJ`s=r6;nm-HMLa!"; break; //`
19 case 8: keyStr1 = r"Y0?zp?B{N|4Jy<PGJ>Az%,6wvU=bW?:["; break; //"
20 case 9: keyStr1 = r"I3}-tUBiuPM`_5l&kG!|>}S@.>Ch&Q<$"; break; //`
23 int newCharCode = 0; // ascii code for newChar
24 int keyPos = 0;
25 string res;
26 foreach (char ch; textStr1) {
27 if (ch < ' ' || ch >= '\x7f') continue;
28 // get current character
29 int charCode = ch-32;
30 // get current key character
31 int keyCharCode = keyStr1[keyPos++]-32;
32 if (keyPos >= keyStr1.length) keyPos = 0; // loop key
33 // cipher
34 if (encrypt) {
35 // encrypt
36 newCharCode = ((charCode+keyCharCode)%93)+32;
37 } else {
38 // decrypt
39 newCharCode = charCode-keyCharCode;
40 if (newCharCode < 0) newCharCode += 93;
41 newCharCode = (newCharCode%93)+32;
43 if (newCharCode < 32 || newCharCode > 125) assert(0, "Invalid character in encryption/decryption.");
44 res ~= cast(char)newCharCode;
46 return res;
50 static immutable string[114] VarNames = [
51 "Money", // 0
52 "Time", // 1
53 "Kills", // 2
54 "Saves", // 3
55 "Plays", // 4
56 "Wins", // 5
57 "Deaths", // 6
58 "Tunnel 1", // 7 // This is how much you 'owe' the tunnel man before he builds the first shortcut
59 "Tunnel 2", // 8
60 "Mini games", // 9
61 "YASM 1.8 extra save data", // 10
63 "TOTALS VERSION",
65 "CRATES OPENED",
66 "CHESTS OPENED",
67 "IDOLS GRABBED",
68 "IDOLS CONVERTED",
69 "DAMSELS GRABBED",
70 "KISSES BOUGHT",
71 "DAMSELS BOUGHT",
72 "DAMSELS SAVED",
73 "DAMSELS KILLED",
74 "ITEMS BOUGHT",
75 "ITEMS STOLEN",
76 "MONEY EARNED",
77 "MONEY SPENT",
78 "DICE GAMES PLAYED",
79 "DICE GAMES WON",
80 "DICE GAMES LOST",
81 "SACRIFICES",
82 "DEATHS ON LEVEL 1",
83 "DEATHS ON LEVEL 2",
84 "DEATHS ON LEVEL 3",
85 "DEATHS ON LEVEL 4",
86 "DEATHS ON LEVEL 5",
87 "DEATHS ON LEVEL 6",
88 "DEATHS ON LEVEL 7",
89 "DEATHS ON LEVEL 8",
90 "DEATHS ON LEVEL 9",
91 "DEATHS ON LEVEL 10",
92 "DEATHS ON LEVEL 11",
93 "DEATHS ON LEVEL 12",
94 "DEATHS ON LEVEL 13",
95 "DEATHS ON LEVEL 14",
96 "DEATHS ON LEVEL 15",
97 "DEATHS ON LEVEL 16",
99 "DEATHES FROM BATS",
100 "DEATHES FROM SNAKES",
101 "DEATHES FROM SPIDERS",
102 "DEATHES FROM G. SPIDERS",
103 "DEATHES FROM CAVEMANS",
104 "DEATHES FROM SKELETONS",
105 "DEATHES FROM ZOMBIES",
106 "DEATHES FROM VAMPIRES",
107 "DEATHES FROM FROGS",
108 "DEATHES FROM FIRE FROGS",
109 "DEATHES FROM MANTRAPS",
110 "DEATHES FROM PIRANHAS",
111 "DEATHES FROM MEGAMOUTHS",
112 "DEATHES FROM YETIS",
113 "DEATHES FROM YETI KINGS",
114 "DEATHES FROM ALIENS",
115 "DEATHES FROM UFOS",
116 "DEATHES FROM ALIEN BOSSS",
117 "DEATHES FROM HAWKMANS",
118 "DEATHES FROM SHOPKEEPERS",
119 "DEATHES FROM TOMB LORDS",
120 "DEATHES FROM MAGMA MANS",
121 "DEATHES FROM OLMECS",
122 "DEATHES FROM GHOST",
123 "1:DEATHES FROM COBRAS",
124 "1:DEATHES FROM GREEN SPIDERS",
125 "1:DEATHES FROM GREEN FROGS",
127 "DEATHES BY ROCKS",
128 "DEATHES BY EXPLOSIONS",
129 "DEATHES BY CRUSHEDS",
130 "DEATHES BY LONG FALLS",
131 "DEATHES BY SPIKESS",
132 "DEATHES BY BOULDERS",
133 "DEATHES BY ARROW TRAPS",
134 "DEATHES BY SPEAR TRAPS",
135 "DEATHES BY SMASH TRAPS",
136 "DEATHES BY CEILING TRAPS",
137 "DEATHES BY PITS",
138 "DEATHES BY LAVAS",
139 "DEATHES BY SUICIDES",
140 "DEATHES BY OTHERS",
142 "BATS KILLED",
143 "SNAKES KILLED",
144 "SPIDERS KILLED",
145 "G. SPIDERS KILLED",
146 "CAVEMANS KILLED",
147 "SKELETONS KILLED",
148 "ZOMBIES KILLED",
149 "VAMPIRES KILLED",
150 "FROGS KILLED",
151 "FIRE FROGS KILLED",
152 "MANTRAPS KILLED",
153 "PIRANHAS KILLED",
154 "MEGAMOUTHS KILLED",
155 "YETIS KILLED",
156 "YETI KINGS KILLED",
157 "ALIENS KILLED",
158 "UFOS KILLED",
159 "ALIEN BOSS' KILLED",
160 "HAWKMANS KILLED",
161 "SHOPKEEPERS KILLED",
162 "TOMB LORDS KILLED",
163 "OLMECS KILLED",
164 "OTHERS KILLED",
165 "1:COBRAS KILLED",
166 "1:GREEN SPIDERS KILLED",
167 "1:GREEN FROGS KILLED",
168 "MONKEYS KILLED",
172 void main (string[] args) {
173 auto fl = File(args.length > 1 ? args[1] : "yasm.dat");
174 usize idx = 0, lineidx = 0, lnum = 0;
175 uint ver = 0;
176 foreach (string s; fl.byLineCopy) {
177 if (ver == 0) {
178 // skip v1 fields
179 import std.algorithm : startsWith;
180 while (idx < VarNames.length && VarNames[idx].startsWith("1:")) {
181 //writeln("SKIPPED: ", VarNames[idx][2..$]);
182 ++idx;
185 s = scrCipher(s, (lineidx <= 10 ? lineidx : lineidx-11));
186 ++lineidx;
187 //{ ++lnum; writeln(lnum, ": < ", s, " >"); }
188 // get the real value in square brackets from a string like: "laskjf982jq flkjasf[935]alskdjf8a3j88aj"
189 bool wasValue = false;
190 auto sorig = s;
191 while (s.length > 0) {
192 import std.string : indexOf;
193 auto p0 = s.indexOf('[');
194 if (p0 < 0) break;
195 auto p1 = s.indexOf(']', p0+1);
196 if (p1 < 0) break;
197 auto v = s[p0+1..p1];
198 s = s[p1+1..$];
199 if (v.length == 0) continue;
200 usize pos = 0;
201 if (v[0] == '-' || v[0] == '+') pos = 1;
202 if (pos >= v.length) continue;
203 while (pos < v.length && v[pos] >= '0' && v[pos] <= '9') ++pos;
204 if (pos < v.length) continue;
205 import std.conv : to;
206 auto val = to!int(v);
207 wasValue = true;
208 if (idx == 9) {
209 // decode minigames
210 int stars = val%100; val = val/100;
211 int moon = val%100; val = val/100;
212 int sun = val;
213 writeln("StarsRoom = ", stars);
214 writeln("MoonRoom = ", moon);
215 writeln("SunRoom = ", sun);
216 } else if (idx < VarNames.length) {
217 import std.algorithm : startsWith;
218 string n = VarNames[idx];
219 if (n == "TOTALS VERSION") ver = val;
220 if (n.startsWith("1:")) n = n[2..$];
221 writeln(n, " = ", val);
222 } else {
223 writeln("DUNNO #", idx, " = ", val);
225 break;
227 if (!wasValue) writeln("FUCKED STTRING: [", sorig, "]");
228 ++idx;