├── .cproject
├── .gitignore
├── .project
├── .settings
├── language.settings.xml
└── org.eclipse.ltk.core.refactoring.prefs
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── decompiler
└── assemblyProcessing
│ ├── .gitignore
│ ├── Makefile
│ ├── binaryRemover.cpp
│ ├── binaryRemover.hpp
│ ├── labelProcessor.cpp
│ ├── labelProcessor.hpp
│ └── main.cpp
└── src
├── api
└── apiCoreMods.hpp
├── common
├── bml
│ ├── commonHandler.cpp
│ ├── commonHandler.hpp
│ ├── commonHandlerTable.hpp
│ ├── entry.cpp
│ └── entry.hpp
├── patcher
│ ├── patchApplier.cpp
│ ├── patchApplier.hpp
│ ├── patchConstants.hpp
│ ├── patcher.cpp
│ └── patcher.hpp
└── relauncher
│ ├── coreMods.cpp
│ ├── coreMods.hpp
│ ├── relauncher.cpp
│ └── relauncher.hpp
├── ios
└── relauncher
│ ├── iosRelaunch.cpp
│ ├── launchHandler.cpp
│ ├── stackDigger.cpp
│ └── stackDigger.hpp
└── win10
└── relauncher
├── launcher.cpp
└── winRelaunch.cpp
/.cproject:
--------------------------------------------------------------------------------
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 |
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 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.DS_Store
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | MinecraftBlacksmith
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
16 | full,incremental,
17 |
18 |
19 |
20 |
21 |
22 | org.eclipse.cdt.core.cnature
23 | org.eclipse.cdt.core.ccnature
24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.settings/language.settings.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.ltk.core.refactoring.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
3 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 | We currently do not have a developer's agreement. If you submit a pull request, we will create an agreement before merging.
3 |
4 | ## Copyright Warning
5 | While MinecraftBlacksmith is licensed under BSD-2-Clause, Minecraft is under exclusive copyright. By law, you are not allowed to publish Minecraft's source code. However, you are allowed to submit patches, as they are not major chunks of Minecraft's code.
6 |
7 | ## Windows 10 Edition Source Code
8 | If you would like to get a copy of the Windows 10 Edition source code, you will need it installed. If you do not have a PC, you can get Windows 10 Enterprise Edition [here](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines), and run Windows 10 within a virtual machine. At one point, Minecraft Windows 10 edition came with Java Edition, so if you bought Minecraft before fall 2018, all you need to do to get the game is redeem the code found on your [Mojang account page](https://account.mojang.com/me). When you have the game, navigate to the path `C:\Program Files\WindowsApps`. Find the folder that starts with `Minecraft`, then has a ton of numbers. In there, you will find a `Minecraft.Windows.exe`. Once you obtain Minecraft's binary, you can disassemble it with `objdump`, then you can run MinecraftBlacksmith's `processasm` tool to remove extra binary numbers.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2018, Hallowizer
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MinecraftBlacksmith
2 |
3 | MinecraftBlacksmith is a mod loader for the Bedrock edition of Minecraft. Bedrock edition refers to Windows 10 Edition, Pocket Edition, and all other platforms that can cross-play with these platforms. It is currently just getting started, so only a few platforms are supported. We are currently in alpha edition, but it is alpha 0.0.0.0.1. We are still working on the game engine, so if you want to try MinecraftBlacksmith you must wait. MinecraftBlacksmith is based on Minecraft Forge. Our goal is to allow Forge mods to run on MinecraftBlacksmith.
4 |
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/.gitignore:
--------------------------------------------------------------------------------
1 | /binaryRemover.o
2 | /labelProcessor.o
3 | /main.o
4 | /writeFormatter.o
5 | /AssemblyProcessor
6 |
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-g
2 | AssemblyProcessor: binaryRemover.o labelProcessor.o main.o writeFormatter.o
3 | $(CC) -o $@ $^ -lstdc++
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/binaryRemover.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * binaryRemover.cpp
3 | *
4 | * Created on: Dec 1, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #include
9 | #include
10 |
11 | #include "binaryRemover.hpp"
12 |
13 | #define LAST_LABEL 0x1426371aa
14 |
15 | string readNoBinary(istream& in) {
16 | string word;
17 | char character;
18 |
19 | long label;
20 | size_t end;
21 |
22 | string contents = "";
23 |
24 | // Skip 3 lines.
25 | in.ignore(numeric_limits::max(), '\n');
26 | in.ignore(numeric_limits::max(), '\n');
27 | in.ignore(numeric_limits::max(), '\n');
28 |
29 | while (label != LAST_LABEL) {
30 | in >> word;
31 |
32 | if (word == "Disassembly") { // Section header
33 | in.ignore(numeric_limits::max(), '\n');
34 | in >> word;
35 |
36 | // And copy it over.
37 | contents += word;
38 | contents += "\n";
39 |
40 | continue;
41 | }
42 |
43 | try {
44 | label = stol(word, NULL, 16); // Skips the colon
45 | } catch (const exception&) {
46 | contents += word;
47 | contents += "\n";
48 | continue;
49 | }
50 |
51 | try {
52 | for (;;) { // Skip binary numbers.
53 | in >> word;
54 | stoi(word, &end, 16);
55 | }
56 | } catch (const exception&) {
57 | // NOOP
58 | }
59 |
60 | contents += to_string(label);
61 | contents += ":\n";
62 |
63 | contents += word;
64 | contents += " ";
65 |
66 | string text;
67 | getline(in, text);
68 | contents += text;
69 | contents += "\n";
70 | }
71 |
72 | return contents;
73 | }
74 |
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/binaryRemover.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * binaryRemover.hpp
3 | *
4 | * Created on: Dec 1, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #ifndef BINARYREMOVER_HPP_
9 | #define BINARYREMOVER_HPP_
10 |
11 | #include
12 | #include
13 |
14 | using namespace std;
15 |
16 | string readNoBinary(istream&);
17 |
18 |
19 | #endif /* BINARYREMOVER_HPP_ */
20 |
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/labelProcessor.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * labelProcessor.cpp
3 | *
4 | * Created on: Dec 1, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #include
9 |
10 | #include "labelProcessor.hpp"
11 |
12 | string processLabels(string input) {
13 | char *text = (char *) malloc(input.size()*sizeof(char));
14 | strcpy(text, input.c_str());
15 |
16 | char *token;
17 | char *token2;
18 | char *token3;
19 |
20 | bool first = true;
21 |
22 | string result = "";
23 |
24 | while ((token = strtok(first ? text : NULL, " \n")) != NULL) {
25 | first = false;
26 |
27 | size_t len = strlen(token);
28 | if (token[len-1] != ':') { // Let all instructions through.
29 | result += token;
30 | result += ' ';
31 | continue;
32 | }
33 |
34 | result += '\n'; // At the end of an instruction, or beginning of file.
35 |
36 | if (token[0] == '.') { // Let all section labels through.
37 | result += token;
38 | result += '\n';
39 | continue;
40 | }
41 |
42 | token2 = strtok(NULL, " \n");
43 | if (strcmp(token2, "pushq") == 0) { // Let all function labels through.
44 | token3 = strtok(NULL, " \n");
45 | if (strcmp(token3, "\t%rbp") == 0) { // Functions start by pushing %rbp
46 | result += "_func_"; // First underscore indicates that this is a function. Second underscore connects the word func to the hex value.
47 | result += token;
48 |
49 | result += '\n';
50 | result += "pushq %rbp";
51 |
52 | continue;
53 | }
54 |
55 | cout << token3 << ", ";
56 |
57 | result += token2;
58 | result += token3;
59 | continue;
60 | }
61 |
62 | result += token2;
63 | }
64 |
65 | free(text);
66 | return result;
67 | }
68 |
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/labelProcessor.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * labelProcessor.hpp
3 | *
4 | * Created on: Dec 1, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #ifndef LABELPROCESSOR_HPP_
9 | #define LABELPROCESSOR_HPP_
10 |
11 | #include
12 |
13 | using namespace std;
14 |
15 | string processLabels(string);
16 |
17 |
18 | #endif /* LABELPROCESSOR_HPP_ */
19 |
--------------------------------------------------------------------------------
/decompiler/assemblyProcessing/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * main.cpp
3 | *
4 | * Created on: Dec 1, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "binaryRemover.hpp"
16 | #include "labelProcessor.hpp"
17 |
18 | using namespace std;
19 |
20 | int main(int argc, char **argv) {
21 | if (argc < 3) {
22 | cerr << "Usage: " << argv[0] << " \n";
23 | return 1;
24 | }
25 |
26 | try {
27 | cout << "Opening files.\n";
28 | ifstream src(argv[1]);
29 | ofstream target(argv[2]);
30 |
31 | cout << "Reading source file.\n";
32 | string contents = readNoBinary(src);
33 |
34 | cout << "Processing labels.\n";
35 | contents = processLabels(contents);
36 |
37 | cout << "Writing target file.\n";
38 | target << contents;
39 |
40 | cout << "Processed assembly file.\n";
41 | return 0;
42 | } catch (const exception& e) {
43 | cerr << "Something went horribly wrong.\n";
44 | cerr << e.what() << "\n";
45 | return 1;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/api/apiCoreMods.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // coreMods.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #ifndef coreMods_h
10 | #define coreMods_h
11 |
12 | #include
13 | #include
14 |
15 | struct ModBytecode {
16 | std::string modid;
17 | std::vector bytes;
18 | };
19 |
20 | typedef void (*ModTransformer)(ModBytecode&);
21 |
22 | class CoreMod {
23 | public:
24 | virtual ~CoreMod() {
25 | // NOOP
26 | }
27 |
28 | virtual ModTransformer *getTransformers() {
29 | return NULL;
30 | }
31 |
32 | virtual int getTransformerCount() {
33 | return 0;
34 | }
35 | };
36 |
37 | #endif /* coreMods_h */
38 |
--------------------------------------------------------------------------------
/src/common/bml/commonHandler.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * commonHandler.cpp
3 | *
4 | * Created on: Nov 30, 2018
5 | * Author: hallowizer
6 | */
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/common/bml/commonHandler.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * commonHandler.hpp
3 | *
4 | * Created on: Nov 30, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #ifndef COMMONHANDLER_HPP_
9 | #define COMMONHANDLER_HPP_
10 |
11 | #include "commonHandlerTable.hpp"
12 |
13 | void initFunctionTable(BmlCommonHandler);
14 |
15 | #endif /* COMMONHANDLER_HPP_ */
16 |
--------------------------------------------------------------------------------
/src/common/bml/commonHandlerTable.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * commonHandlerTable.hpp
3 | *
4 | * Created on: Nov 30, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #ifndef COMMONHANDLERTABLE_CPP_
9 | #define COMMONHANDLERTABLE_CPP_
10 |
11 |
12 | struct BmlFunctionTable {
13 |
14 | };
15 |
16 | typedef struct BmlFunctionTable *BmlCommonHandler;
17 |
18 |
19 | #endif /* COMMONHANDLERTABLE_CPP_ */
20 |
--------------------------------------------------------------------------------
/src/common/bml/entry.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * entry.cpp
3 | *
4 | * Created on: Nov 30, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #include
9 | #include
10 |
11 | #include "entry.hpp"
12 | #include "commonHandlerTable.hpp"
13 | #include
14 | #include
15 |
16 | typedef void (*HandlerInitFunc)(BmlCommonHandler);
17 |
18 | BmlCommonHandler enter(void) {
19 | FILE *fp = fopen((getRelauncherGameDir() + "blacksmith/bml").c_str(), "r");
20 |
21 | int len;
22 | fscanf(fp, "%d", &len);
23 |
24 | char *bytes = malloc(len);
25 | fread(bytes, 1, len, fp);
26 |
27 | fclose(fp);
28 |
29 | char *transformedBytes = transformMod("bml", bytes, &len);
30 |
31 | fp = fopen((getRelauncherGameDir() + "blacksmith/temp/bml").c_str(), "r+");
32 | fwrite(transformedBytes, 1, len, fp);
33 | HandlerInitFunc init = loadSym(fp, "initFunctionTable");
34 |
35 | fclose(fp);
36 | remove((getRelauncherGameDir() + "blacksmith/temp/bml").c_str());
37 |
38 | BmlCommonHandler handler = (BmlCommonHandler) malloc(sizeof(struct BmlFunctionTable));
39 | init(handler);
40 |
41 | fclose(fp);
42 | return handler;
43 | }
44 |
--------------------------------------------------------------------------------
/src/common/bml/entry.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * entry.hpp
3 | *
4 | * Created on: Nov 30, 2018
5 | * Author: hallowizer
6 | */
7 |
8 | #ifndef ENTRY_HPP_
9 | #define ENTRY_HPP_
10 |
11 | typedef int (*EnterFunc)(void);
12 |
13 | int enter(void);
14 |
15 |
16 | #endif /* ENTRY_HPP_ */
17 |
--------------------------------------------------------------------------------
/src/common/patcher/patchApplier.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // patchApplier.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/3/18.
6 | //
7 | //
8 |
9 | #include
10 | #include
11 |
12 | using namespace std;
13 |
14 | #include "patchApplier.hpp"
15 | #include "patchConstants.hpp"
16 |
17 | static void append(vector&, int, FILE *);
18 | static void copy(vector&, vector&, int *, long, int);
19 |
20 | static void skip(int *, vector&, long);
21 | static char *read(int *, vector&, long);
22 | static void write(vector&, int, const char *);
23 |
24 | struct patchMagic {
25 | char magic1;
26 | char magic2;
27 | char magic3;
28 | char magic4;
29 | };
30 |
31 | struct patchInstruction {
32 | int code;
33 |
34 | union {
35 | // Data instructions. All data instruction fields are length fields. Byte contents are after length field.
36 | unsigned short dataUshort;
37 | int dataInt;
38 |
39 | // Copy instructions. These vary in size.
40 |
41 | struct {
42 | unsigned short offset;
43 | unsigned char length;
44 | } copyUshortUbyte;
45 |
46 | struct {
47 | unsigned short offset;
48 | unsigned short length;
49 | } copyUshortUshort;
50 |
51 | struct {
52 | unsigned short offset;
53 | int length;
54 | } copyUshortInt;
55 |
56 | struct {
57 | int offset;
58 | unsigned char length;
59 | } copyIntUbyte;
60 |
61 | struct {
62 | int offset;
63 | unsigned short length;
64 | } copyIntUshort;
65 |
66 | struct {
67 | int offset;
68 | int length;
69 | } copyIntInt;
70 |
71 | struct {
72 | long offset;
73 | int length;
74 | } copyLongInt;
75 | } data;
76 | };
77 |
78 | void patch(vector& bytes, FILE *patchSource) {
79 | struct patchMagic *magic = (struct patchMagic *) malloc(sizeof(struct patchMagic));
80 | fread(magic, sizeof(struct patchMagic), 1, patchSource);
81 |
82 | if (magic->magic1 != 0x93 || magic->magic2 != 0x37 || magic->magic3 != 0x8d || magic->magic4 != 0x01) {
83 | cerr << "Invalid patch format.";
84 | return;
85 | }
86 |
87 | free(magic);
88 |
89 | int readIndex = 0;
90 | vector output;
91 |
92 | int i;
93 | for (i = 0; ; i++) {
94 | struct patchInstruction *insn = malloc(sizeof(struct patchInstruction));
95 | fread(insn, sizeof(struct patchInstruction), 1, patchSource);
96 |
97 | if (insn->code == EOF) {
98 | free(insn);
99 | break;
100 | }
101 |
102 | if (insn->code <= DATA_MAX) {
103 | write(output, 1, (char *) &(insn->code));
104 |
105 | free(insn);
106 | continue;
107 | }
108 |
109 | switch (insn->code) {
110 | case DATA_USHORT:
111 | append(output, insn->data.dataUshort, patchSource);
112 | break;
113 | case DATA_INT:
114 | append(output, insn->data.dataInt, patchSource);
115 | break;
116 | case COPY_USHORT_UBYTE:
117 | copy(bytes, output, &readIndex, insn->data.copyUshortUbyte.offset, insn->data.copyUshortUbyte.length);
118 | break;
119 | case COPY_USHORT_USHORT:
120 | copy(bytes, output, &readIndex, insn->data.copyUshortUshort.offset, insn->data.copyUshortUshort.length);
121 | break;
122 | case COPY_USHORT_INT:
123 | copy(bytes, output, &readIndex, insn->data.copyUshortInt.offset, insn->data.copyUshortInt.length);
124 | break;
125 | case COPY_INT_UBYTE:
126 | copy(bytes, output, &readIndex, insn->data.copyIntUbyte.offset, insn->data.copyIntUbyte.length);
127 | break;
128 | case COPY_INT_USHORT:
129 | copy(bytes, output, &readIndex, insn->data.copyIntUshort.offset, insn->data.copyIntUshort.length);
130 | break;
131 | case COPY_INT_INT:
132 | copy(bytes, output, &readIndex, insn->data.copyIntInt.offset, insn->data.copyIntInt.length);
133 | break;
134 | case COPY_LONG_INT:
135 | copy(bytes, output, &readIndex, insn->data.copyLongInt.offset, insn->data.copyLongInt.length);
136 | break;
137 | }
138 |
139 | free(insn);
140 | }
141 |
142 |
143 | }
144 |
145 | static void append(vector& output, int length, FILE *src) {
146 | char *data = malloc(length);
147 | fread(data, 1, length, src);
148 |
149 | write(output, length, data);
150 |
151 | free(data);
152 | }
153 |
154 | static void copy(vector& source, vector& output, int *readIndex, long offset, int length) {
155 | skip(readIndex, source, offset);
156 |
157 | char *toCopy = read(readIndex, source, length);
158 | write(output, length, toCopy);
159 | free(toCopy);
160 | }
161 |
162 | static void skip(int *index, vector& input, long length) {
163 | char *ptr = read(index, input, length);
164 | free(ptr);
165 | }
166 |
167 | static char *read(int *index, vector& input, long length) {
168 | char *data = (char *) malloc(length);
169 |
170 | long i;
171 | for (i = 0; i < length; i++)
172 | data[i] = input[i+(*index)];
173 |
174 | (*index) += length;
175 | return data;
176 | }
177 |
178 | static void write(vector& output, int length, const char *value) {
179 | int i;
180 | for (i = 0; i < length; i++)
181 | output.push_back(value[i]);
182 | }
183 |
--------------------------------------------------------------------------------
/src/common/patcher/patchApplier.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // patchApplier.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/3/18.
6 | //
7 | //
8 |
9 | #ifndef patchApplier_hpp
10 | #define patchApplier_hpp
11 |
12 | #include
13 |
14 | #include
15 |
16 | using namespace std;
17 |
18 | void patch(vector, FILE *);
19 |
20 | #endif /* patchApplier_hpp */
21 |
--------------------------------------------------------------------------------
/src/common/patcher/patchConstants.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // patchConstants.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/3/18.
6 | //
7 | //
8 |
9 | #ifndef patchConstants_h
10 | #define patchConstants_h
11 |
12 | #define CHUNK_SIZE 1024
13 |
14 | #define EOF 0
15 | #define DATA_MAX 246
16 |
17 | #define DATA_USHORT 247
18 | #define DATA_INT 248
19 |
20 | #define COPY_USHORT_UBYTE 249
21 | #define COPY_USHORT_USHORT 250
22 | #define COPY_USHORT_INT 251
23 | #define COPY_INT_UBYTE 252
24 | #define COPY_INT_USHORT 253
25 | #define COPY_INT_INT 254
26 | #define COPY_LONG_INT 255
27 |
28 | #endif /* patchConstants_h */
29 |
--------------------------------------------------------------------------------
/src/common/patcher/patcher.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // patcher.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #include
10 | #include
11 |
12 | #include
13 | #include
14 |
15 | #include "patcher.hpp"
16 | #include "patchApplier.hpp"
17 |
18 | using namespace std;
19 |
20 | static void applyPatch(vector&);
21 | static void differentBinary(void);
22 |
23 | struct patchHeader {
24 | int srcLength;
25 | int checksum;
26 | int patchLength;
27 | };
28 |
29 | static char *binpatchFile;
30 | static bool ignoreDiscrepancies;
31 |
32 | void init(char *gameDir, bool ignorePatchDiscrepancies) {
33 | ignoreDiscrepancies = ignorePatchDiscrepancies;
34 | }
35 |
36 | void patchTransform(ModBytecode& bytecode) {
37 | if (bytecode.modid != "minecraft")
38 | return;
39 |
40 | applyPatch(bytecode.bytes);
41 | }
42 |
43 | static void applyPatch(vector& bytes) {
44 | FILE *file = fopen(binpatchFile, "r");
45 |
46 | struct patchHeader *header = malloc(sizeof(struct patchHeader));
47 | fread(header, sizeof(struct patchHeader), 1, file);
48 |
49 | if (bytes.size() != header->srcLength)
50 | differentBinary();
51 |
52 | int a = 1;
53 | int b = 0;
54 | int i;
55 |
56 | for (i = 0; i < header->srcLength; i++) { // Adler 32 hash
57 | a += bytes[i];
58 | b += a;
59 | }
60 |
61 | if (header->checksum != b)
62 | differentBinary();
63 |
64 | patch(bytes, file);
65 | fclose(file);
66 | }
67 |
68 | static void differentBinary(void) {
69 | cerr << "There is a binary discrepancy between the expected and actual Minecraft binary. Did you modify Minecraft?\n";
70 |
71 | if (ignoreDiscrepancies)
72 | cerr << "BML will ignore this error. This may result in an invalid patched binary.";
73 | else {
74 | cerr << "The game will exit, because this is a severe error. Please get a clean binary.";
75 | exit(1);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/common/patcher/patcher.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // patcher.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #ifndef patcher_hpp
10 | #define patcher_hpp
11 |
12 | #include
13 |
14 | #include
15 |
16 | using namespace std;
17 |
18 | void init(char *);
19 | void patchTransform(ModBytecode&);
20 |
21 | #endif /* patcher_hpp */
22 |
--------------------------------------------------------------------------------
/src/common/relauncher/coreMods.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // coreMods.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | using namespace std;
17 |
18 | #include
19 | #include "coreMods.hpp"
20 | #include
21 |
22 | #define COREMOD_TYPE 1
23 |
24 | typedef CoreMod (*cmInitFunc)(void);
25 |
26 | static void registerTransformer(ModTransformer transformer);
27 | static void discoverCoreMods(string);
28 | static void processFile(string, string, string);
29 | static void loadCoreMod(cmInitFunc);
30 |
31 | static list transformers;
32 |
33 | void setupCoreMods(string gameDir) {
34 | registerTransformer(patchTransform);
35 |
36 | discoverCoreMods(gameDir);
37 | }
38 |
39 | static void discoverCoreMods(string gameDir) {
40 | string modDir = gameDir + "mods/";
41 |
42 | DIR *dir = opendir(modDir.c_str());
43 | struct dirent *member;
44 | struct stat *sb = (struct stat *) malloc(sizeof(struct stat));
45 |
46 | if (dir) {
47 | while ((member = readdir(dir)) != NULL)
48 | if (stat((modDir + member->d_name).c_str(), sb) == 0 && S_ISREG(sb->st_mode))
49 | processFile(gameDir, modDir + member->d_name, member->d_name);
50 | }
51 |
52 | closedir(dir);
53 |
54 | free(sb);
55 | }
56 |
57 | static void processFile(string gameDir, string name, string singleName) {
58 | FILE *fp = fopen(name.c_str(), "r");
59 |
60 | char type;
61 | fscanf(fp, "%c", &type);
62 |
63 | if (type != COREMOD_TYPE)
64 | return;
65 |
66 | int len;
67 | fscanf(fp, "%d", &len);
68 |
69 | char *bytes = malloc(len);
70 | fread(bytes, 1, len, fp);
71 |
72 | fclose(fp);
73 |
74 | string tmpModDir = gameDir + "blacksmith/temp/mods/";
75 | fp = fopen((tmpModDir + singleName).c_str(), "r+");
76 |
77 | fprintf(fp, bytes);
78 | free(bytes);
79 |
80 | fclose(fp);
81 | remove((tmpModDir + singleName).c_str());
82 |
83 | cmInitFunc init = (cmInitFunc) loadSym(fp, "blacksmith_reserved_initCoreMod");
84 | loadCoreMod(init);
85 | }
86 |
87 | static void loadCoreMod(cmInitFunc init) {
88 | CoreMod coremod = init();
89 |
90 | ModTransformer *transformers = coremod.getTransformers();
91 | int transformerCount = coremod.getTransformerCount();
92 |
93 | int i;
94 | for (i = 0; i < transformerCount; i++)
95 | registerTransformer(transformers[i]);
96 | }
97 |
98 | static void registerTransformer(ModTransformer transformer) {
99 | transformers.push_back(transformer);
100 | }
101 |
102 | void transformMod(ModBytecode& bytecode) {
103 | for (list::iterator iter = transformers.begin(); iter != transformers.end(); iter++)
104 | (*iter)(bytecode);
105 | }
106 |
--------------------------------------------------------------------------------
/src/common/relauncher/coreMods.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // coreMods.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #ifndef coreMods_hpp
10 | #define coreMods_hpp
11 |
12 | #include
13 |
14 | // API functions
15 | void setupCoreMods(string);
16 | char *transformMod(string, char *, int *);
17 |
18 | // Processor dependent functions
19 | void *loadSym(FILE *, std::string);
20 |
21 | #endif /* coreMods_hpp */
22 |
--------------------------------------------------------------------------------
/src/common/relauncher/relauncher.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // relauncher.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #include
10 |
11 | #include "relauncher.hpp"
12 | #include "coreMods.hpp"
13 |
14 | static MainFunc findMain(char *, int);
15 |
16 | static string gameDir;
17 |
18 | void relaunch(int argc, char **argv) {
19 | gameDir = findGameDir(argc, argv);
20 | setupCoreMods(gameDir);
21 |
22 | int length = 0;
23 | char *minecraftBytes = findMinecraft(&length);
24 |
25 | int transformedLength = length;
26 | char *transformedBytes = transformMod("minecraft", minecraftBytes, &transformedLength);
27 |
28 | MainFunc minecraftMain = findMain(transformedBytes, transformedLength);
29 | int exitCode = minecraftMain(argc, argv, enter);
30 |
31 | exit(exitCode);
32 | }
33 |
34 | static MainFunc findMain(char *minecraftBytes, int length) {
35 | char *name = mainName();
36 | return findMainFunc(name, minecraftBytes, length);
37 | }
38 |
39 | string getRelauncherGameDir() {
40 | return gameDir;
41 | }
42 |
--------------------------------------------------------------------------------
/src/common/relauncher/relauncher.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // relauncher.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/2/18.
6 | //
7 | //
8 |
9 | #ifndef relauncher_hpp
10 | #define relauncher_hpp
11 |
12 | #include
13 |
14 | #include
15 |
16 | using namespace std;
17 |
18 | // Typedefs
19 | typedef int (*MainFunc)(int, char **, EnterFunc);
20 |
21 | // API functions
22 | void relaunch(int, char **);
23 | string getRelauncherGameDir();
24 |
25 | // Platform dependent functions
26 | string findGameDir(int, char **);
27 | char *findMinecraft(int *);
28 | string mainName(void);
29 |
30 | // Processor dependent functions
31 | MainFunc findMainFunc(string, char *, int);
32 |
33 | #endif /* relauncher_hpp */
34 |
--------------------------------------------------------------------------------
/src/ios/relauncher/iosRelaunch.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // iosRelaunch.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/11/18.
6 | //
7 | //
8 |
9 | #include
10 | #include "stackDigger.hpp"
11 |
12 | // TBD
13 | #define MAIN_OFFSET
14 |
15 | char *findMinecraft(void) {
16 | void *stackStart = getStackStart(); // 4 stack frames in, but skip the last Minecraft frame.
17 | void **p_retAddr = (void **) (stackStart-sizeof(void *));
18 |
19 | void *retAddr = *p_retAddr;
20 | return (char *) (retAddr-MAIN_OFFSET);
21 | }
22 |
23 | string mainName(void) {
24 | return "bmlReentry";
25 | }
26 |
--------------------------------------------------------------------------------
/src/ios/relauncher/launchHandler.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // launchHandler.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/11/18.
6 | //
7 | //
8 |
9 | #include
10 | #include "stackDigger.hpp"
11 |
12 | #include
13 |
14 | using namespace std;
15 |
16 | static void vanillaLaunch(void);
17 |
18 | void entry(void) {
19 | initStackDigger(); // Keep this first!
20 |
21 | void *stackStart = getStackStart();
22 |
23 | void **retAddr = (void **) (stackStart-sizeof(void *));
24 | char ***p_argv = (char ***) (retAddr-sizeof(char **));
25 | int *p_argc = (int *) (p_argv-sizeof(int));
26 |
27 | int argc = *p_argc;
28 | char **argv = *p_argv;
29 |
30 | int i;
31 | bool enable = false;
32 |
33 | for (i = 0; i < argc; i++) {
34 | string arg = argv[i];
35 |
36 | if (arg == "enableBlacksmithMod") {
37 | enable = true;
38 | } else if (enable && i < argc-1)
39 | argv[i] = argv[i+1];
40 | }
41 |
42 | if (enable)
43 | relaunch(argc-1, argv);
44 | else
45 | vanillaLaunch();
46 | }
47 |
48 | static void vanillaLaunch(void) {
49 | // TODO: Remove the Blacksmith resource pack from the list, then let Minecraft proceed.
50 | }
51 |
--------------------------------------------------------------------------------
/src/ios/relauncher/stackDigger.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // stackDigger.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/11/18.
6 | //
7 | //
8 |
9 | #include "stackDigger.hpp"
10 | #include "rbpLocator.hpp"
11 |
12 | // TBD
13 | #define MEMORY_SIZE
14 |
15 | static void *stackStart;
16 |
17 | void initStackDigger(void) {
18 | char dummy;
19 | char *addr = &dummy;
20 |
21 | addr += MEMORY_SIZE;
22 | stackStart = addr;
23 | }
24 |
25 | void *getStackStart(void) {
26 | return stackStart;
27 | }
28 |
--------------------------------------------------------------------------------
/src/ios/relauncher/stackDigger.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // stackDigger.hpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/11/18.
6 | //
7 | //
8 |
9 | #ifndef stackDigger_hpp
10 | #define stackDigger_hpp
11 |
12 | void initStackDigger(void);
13 | void *getStackStart(void);
14 |
15 | #endif /* stackDigger_hpp */
16 |
--------------------------------------------------------------------------------
/src/win10/relauncher/launcher.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // launcher.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/3/18.
6 | //
7 | //
8 |
9 | #include
10 |
11 | #include
12 |
13 | static void returned(void);
14 |
15 | int main(int argc, char **argv) {
16 | relaunch(argc, argv);
17 |
18 | // Should not reach here.
19 | returned();
20 | return 1;
21 | }
22 |
23 | static void returned(void) {
24 | cerr << "MinecraftBlacksmith somehow returned from the relauncher.";
25 | }
26 |
--------------------------------------------------------------------------------
/src/win10/relauncher/winRelaunch.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // winRelaunch.cpp
3 | // MinecraftBlacksmith
4 | //
5 | // Created by Hallowizer on 11/3/18.
6 | //
7 | //
8 |
9 | #include
10 |
11 | string mainName(void) {
12 | return "main";
13 | }
14 |
--------------------------------------------------------------------------------