-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopensearch.c
371 lines (311 loc) · 11.5 KB
/
opensearch.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
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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
// Name: OpenSearch
// Author: mcpancakes
// Version: 0.1
// Date: 12 April 2009
//
// Copyright (C) 2009 mcpancakes
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "filename.h"
bool checkRelativity(char strChar1, char strChar2, unsigned char romChar1, unsigned char romChar2); // Returns true (1) if the two chars in the string and in the ROM are relatively the same.
void searchComplete(void); // If the string was found, control passes to this function.
void charComparison(void); // Prints the hex values of the string and of the portion of the ROM that passed the relativity check.
void makeTable(void); // Outputs a table file of the ROM's English alphabet.
bool mktbl = 0; // Command line argument to produce a table (.tbl) file.
bool autocaps = 0; // Command line argument to generate the set of hex values for capital letters.
bool tblOverwrite = 0; // Command line argument to make certain it's alright to overwrite an existing table file.
int disp = 1; // Command line argument to specify which occurrence of the string is to be reported.
char *filePath; // The path of the file (argv[1]).
char autoCapsAsciiChar; // AutoCaps ASCII letter ("-autocaps %c").
char *autoCapsStrPtr; // AutoCaps pointer to the first wildcard that directly precedes the first letter of the string.
int autoCapsPtrDist; // AutoCaps distance from beginning of string to wildcard directly before the first letter of the string.
unsigned long romSize; // Size of the ROM in bytes.
char string[31]; // String to search for in the ROM.
unsigned char *romInMem; // Pointer to the ROM once it is read into memory.
unsigned char *beginningOfRom; // Pointer to the first byte of the ROM in memory.
unsigned char *endOfRom; // Pointer to the last byte of the ROM in memory.
char *strChar1; // The first of two chars from the string used in relative searching.
char *strChar2; // The second of two chars from the string used in relative searching.
unsigned char *romChar1; // The first of two chars from the ROM used in relative searching.
unsigned char *romChar2; // The second of two chars from the ROM used in relative searching.
long int byteCount; // A marker of how far we are into the ROM.
int main(int argc, char *argv[])
{
if (argv[1] != NULL && !strcmp(argv[1], "-help"))
{
printf("OpenSearch 0.1 - optional arguments:\n");
printf(" -mktbl Create the table file for the English alphabet in the\n");
printf(" case that was searched for.\n");
printf(" -autocaps <letter> Automatically generate the uppercase alphabet of the ROM\n");
printf(" and include it in your table file.\n");
printf(" -disp <number> Specify which occurrence of the string you want to\n");
printf(" be returned (and subsequently used to make a table file).\n");
printf(" -f Allows for overwriting of an existing table file.\n");
exit(EXIT_SUCCESS);
}
if (argc < 3) // At least three arguments are required.
{
printf("Usage: %s <filename> <string>\n", argv[0]);
printf("For an explanation of optional arguments, type \"%s -help\".\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("OpenSearch 0.1 Copyright (C) 2009 mcpancakes\n");
while (argc--) // Parse the optional arguments.
{
if (!strcmp(argv[argc], "-mktbl")) mktbl = 1;
else if (!strcmp(argv[argc], "-autocaps"))
{
if (autocaps) printf("Warning: Redundant \"-autocaps\" calling.\n");
else if (argv[argc + 1] == NULL) printf("Error: No AutoCaps letter specified.\n");
else if (argv[argc + 1][0] < 'A' || argv[argc + 1][0] > 'Z') printf("Error: AutoCaps letter must be A-Z.\n");
else
{
autoCapsAsciiChar = argv[argc + 1][0];
autocaps = 1;
}
}
else if (!strcmp(argv[argc], "-disp"))
{
if (disp != 1) printf("Warning: Redundant \"-disp\" calling.\n");
else if (atoi(argv[argc + 1]) <= 0) printf("Error: Invalid \"-disp\" argument.\n");
else disp = atoi(argv[argc + 1]);
}
else if (!strcmp(argv[argc], "-f")) tblOverwrite = 1;
else if (argc > 2 && strcmp(argv[argc - 1], "-autocaps") && strcmp(argv[argc - 1], "-disp")) printf("Unrecognized argument: %s\n", argv[argc]);
}
filePath = (char *) malloc(strlen(argv[1]) + 1);
strcpy(filePath, argv[1]);
strncpy(string, argv[2], 30);
if (strlen(string) < 2)
{
printf("Error: At least two characters are required for a relative search.\n");
exit(EXIT_FAILURE);
}
if (strlen(string) < 5)
{
printf("Warning: For accuracy, the search string should be at least 5 characters.\n");
}
strChar1 = &string[0];
strChar2 = &string[1];
while (strChar1 != &string[strlen(string) - 1])
{
if (*strChar1 >= 'A' && *strChar1 <= 'Z' && *strChar2 >= 'a' && *strChar2 <= 'z') // This tests for Xx.
{
printf("Warning: Mixing cases may yield inaccurate results.\n");
break;
}
if (*strChar2 >= 'A' && *strChar2 <= 'Z' && *strChar1 >= 'a' && *strChar1 <= 'z') // This tests for xX (for when the last char of the string is the only uppercase).
{
printf("Warning: Mixing cases may yield inaccurate results.\n");
break;
}
strChar1++;
strChar2++;
}
autoCapsStrPtr = &string[0];
if (*autoCapsStrPtr == '*')
{
autoCapsPtrDist = 0;
while (*autoCapsStrPtr == '*')
{
autoCapsStrPtr++;
autoCapsPtrDist++;
}
autoCapsPtrDist--; // Used to set autoCapsHexChar later in makeTable().
}
else if (autocaps) printf("Error: No wildcard for AutoCaps was at the start of the string.\n");
FILE *romFile;
romFile = fopen(argv[1], "rb");
if (romFile == NULL)
{
perror(argv[1]);
exit(EXIT_FAILURE);
}
fseek(romFile, 0, SEEK_END);
romSize = ftell(romFile);
// printf("ROM size: %lu bytes\n", romSize);
rewind(romFile);
romInMem = (unsigned char*) malloc(romSize);
if (romInMem == NULL)
{
perror("Allocating space for ROM in RAM");
exit(EXIT_FAILURE);
}
if (!fread(romInMem, 1, romSize, romFile))
{
perror("Copying ROM into RAM");
free(romInMem);
exit(EXIT_FAILURE);
}
fclose(romFile);
beginningOfRom = romInMem;
endOfRom = romInMem + romSize - 1;
while (romChar2 <= endOfRom) // If romChar2 is on the last byte of the file, and it failed the previous test, the string isn't in the ROM.
{
// printf("byte count: %d (0x%X)\n", byteCount, byteCount);
strChar1 = &string[0];
strChar2 = &string[1];
// printf("strChars: %02X %02X\n", *strChar1, *strChar2);
romChar1 = beginningOfRom + byteCount;
romChar2 = romChar1 + 1;
// printf("romChars: %02X %02X\n", *romChar1, *romChar2);
bool tryNextChars = 1; // Should we continue testing for relativity from a certain offset or move on?
while (tryNextChars)
{
if (romChar2 > endOfRom) break;
if (strChar1 == &string[strlen(string) - 1])
{
disp--;
if (disp == 0) searchComplete();
}
tryNextChars = checkRelativity(*strChar1, *strChar2, *romChar1, *romChar2);
if (*strChar1 == '*' || *strChar2 == '*') tryNextChars = 1; // Lazy wildcard check (does not check letters before and after the wildcard for matching relativity).
strChar1++;
strChar2++;
romChar1++;
romChar2++;
}
byteCount++;
}
printf("String not found!\n");
free(romInMem);
return 0;
}
bool checkRelativity(char strChar1, char strChar2, unsigned char romChar1, unsigned char romChar2)
{
int strCharsRelativity = strChar1 - strChar2;
int romCharsRelativity = romChar1 - romChar2;
if (strCharsRelativity == romCharsRelativity) return 1;
else return 0;
}
void searchComplete(void)
{
charComparison();
if (mktbl) makeTable();
free(romInMem);
exit(EXIT_SUCCESS);
}
void charComparison(void)
{
printf("Input:");
int i;
for (i = 0; i < strlen(string); i++)
{
if (string[i] == '*') printf(" *");
else printf(" %02X", string[i]);
}
printf("\nROM: ");
unsigned char *romChar;
for (romChar = beginningOfRom + byteCount; romChar < romChar2; romChar++)
{
printf(" %02X", *romChar);
}
printf("\n");
printf("Offset: 0x%X (%ld)\n", (unsigned int) byteCount, byteCount);
}
void makeTable(void)
{
unsigned char *hexPtr = (romChar2 - strlen(string));
char *asciiPtr = &string[0];
while (*asciiPtr == '*') // If wildcards were at the beginning of the string, we want to advance to a non-wildcard.
{
hexPtr++;
asciiPtr++;
}
unsigned char hexChar = *hexPtr;
char asciiChar = *asciiPtr;
while (asciiChar != 'A' && asciiChar != 'a') // "Rewind" the characters back to the beginning of the alphabet.
{
hexChar--;
asciiChar--;
}
FILE *tblExists;
tblExists = fopen(strcat(fileNameNoExt(filePath), ".tbl"), "r");
if (tblExists != NULL) // Check if table already exists, and if so, only allow overwriting if it was specified with "-over".
{
if (tblOverwrite == 0)
{
printf("Error: Table already exists. Run with \"-f\" to overwrite.\n");
fclose(tblExists);
return;
}
}
FILE *romTable;
romTable = fopen(strcat(fileNameNoExt(filePath), ".tbl"), "w");
if (romTable == NULL)
{
perror("Creating table");
return;
}
printf("Creating table... ");
if (autocaps) // If "-autocaps" was present when the program was run.
{
unsigned char autoCapsHexChar = *(beginningOfRom + byteCount + autoCapsPtrDist); // Point to the byte directly preceding the first non-wildcarded byte.
while (autoCapsAsciiChar > 'A') // "Rewind" uppercase characters back to A.
{
autoCapsAsciiChar--;
autoCapsHexChar--;
}
if (autoCapsHexChar < hexChar) // If the uppercase alphabet is before the lowercase in the ROM's text system, output it before the lowercase.
{
while (autoCapsAsciiChar != 'Z' + 1)
{
fprintf(romTable, "%02X", autoCapsHexChar);
fprintf(romTable, "=%c\n", autoCapsAsciiChar);
autoCapsHexChar++;
autoCapsAsciiChar++;
}
while (asciiChar != 'Z' + 1 && asciiChar != 'z' + 1)
{
fprintf(romTable, "%02X", hexChar);
fprintf(romTable, "=%c\n", asciiChar);
hexChar++;
asciiChar++;
}
}
else // If the uppercase alphabet is after the lowercase in the ROM's text system, output it after the lowercase.
{
while (asciiChar != 'Z' + 1 && asciiChar != 'z' + 1)
{
fprintf(romTable, "%02X", hexChar);
fprintf(romTable, "=%c\n", asciiChar);
hexChar++;
asciiChar++;
}
while (autoCapsAsciiChar != 'Z' + 1)
{
fprintf(romTable, "%02X", autoCapsHexChar);
fprintf(romTable, "=%c\n", autoCapsAsciiChar);
autoCapsHexChar++;
autoCapsAsciiChar++;
}
}
}
else // If the "-autocaps" option was not enabled.
{
while (asciiChar != 'Z' + 1 && asciiChar != 'z' + 1)
{
fprintf(romTable, "%02X", hexChar);
fprintf(romTable, "=%c\n", asciiChar);
hexChar++;
asciiChar++;
}
}
fclose(romTable);
printf("Done!\n");
}