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
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <dirent.h>
#include <zlib.h>
#include <minizip/unzip.h>
#include <sys/stat.h>
#define INES_HEADER_SIZE 16
static void process_nes_file(const char *path) {
FILE *f = fopen(path, "rb");
if(!f) return;
uint8_t header[INES_HEADER_SIZE];
if(fread(header, 1, INES_HEADER_SIZE, f) != INES_HEADER_SIZE) {
fclose(f);
return;
}
fclose(f);
if(memcmp(header, "NES\x1A", 4) != 0) return;
uint8_t mapper_low = (header[6] >> 4);
uint8_t mapper_high = (header[7] & 0xF0);
uint8_t mapper_ext = header[8] & 0x0F;
uint8_t submapper = header[8] >> 4;
uint32_t mapper = (submapper << 12) | (mapper_ext << 8) | mapper_high | mapper_low;
printf("0x%04x %s\n", mapper, path);
}
static void process_zip_file(const char *path) {
unzFile zip = unzOpen(path);
if(!zip) return;
if(unzGoToFirstFile(zip) != UNZ_OK) {
unzClose(zip);
return;
}
char filename[256];
unz_file_info info;
if(unzGetCurrentFileInfo(zip, &info, filename, sizeof(filename), 0, 0, 0, 0) != UNZ_OK) {
unzClose(zip);
return;
}
if(strstr(filename, ".nes") == 0) {
unzClose(zip);
return;
}
if(unzOpenCurrentFile(zip) != UNZ_OK) {
unzClose(zip);
return;
}
uint8_t header[INES_HEADER_SIZE];
if(unzReadCurrentFile(zip, header, INES_HEADER_SIZE) != INES_HEADER_SIZE) {
unzCloseCurrentFile(zip);
unzClose(zip);
return;
}
unzCloseCurrentFile(zip);
unzClose(zip);
if(memcmp(header, "NES\x1A", 4) != 0) return;
uint8_t mapper_low = (header[6] >> 4);
uint8_t mapper_high = (header[7] & 0xF0);
uint8_t mapper_ext = header[8] & 0x0F;
uint8_t submapper = header[8] >> 4;
uint32_t mapper = (submapper << 12) | (mapper_ext << 8) | mapper_high | mapper_low;
printf("0x%04x %s\n", mapper, path);
}
static void scan_directory(const char *path) {
DIR *dir = opendir(path);
if(!dir) return;
struct dirent *entry;
while((entry = readdir(dir))) {
if(entry->d_name[0] == '.') continue;
char fullpath[1024];
snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
struct stat st;
if(stat(fullpath, &st) < 0) continue;
if(S_ISDIR(st.st_mode)) {
scan_directory(fullpath);
} else if(strstr(fullpath, ".nes")) {
process_nes_file(fullpath);
} else if(strstr(fullpath, ".zip")) {
process_zip_file(fullpath);
}
}
closedir(dir);
}
int main(int argc, char **argv) {
if(argc < 2) {
fprintf(stderr, "usage: %s <romdir>\n", argv[0]);
return 1;
}
scan_directory(argv[1]);
return 0;
}
|