SayoriOS  0.3.3
rom.c
1 #include "lib/stdio.h"
2 #include "rom.h"
3 
4 unsigned char *bytes;
5 unsigned int mapper;
6 
7 static long rom_size;
8 
9 static char *carts[] = {
10  [0x00] = "ROM ONLY",
11  [0x01] = "MBC1",
12  [0x02] = "MBC1+RAM",
13  [0x03] = "MBC1+RAM+BATTERY",
14  [0x05] = "MBC2",
15  [0x06] = "MBC2+BATTERY",
16  [0x08] = "ROM+RAM",
17  [0x09] = "ROM+RAM+BATTERY",
18  [0x0B] = "MMM01",
19  [0x0C] = "MMM01+RAM",
20  [0x0D] = "MMM01+RAM+BATTERY",
21  [0x0F] = "MBC3+TIMER+BATTERY",
22  [0x10] = "MBC3+TIMER+RAM+BATTERY",
23  [0x11] = "MBC3",
24  [0x12] = "MBC3+RAM",
25  [0x13] = "MBC3+RAM+BATTERY",
26  [0x15] = "MBC4",
27  [0x16] = "MBC4+RAM",
28  [0x17] = "MBC4+RAM+BATTERY",
29  [0x19] = "MBC5",
30  [0x1A] = "MBC5+RAM",
31  [0x1B] = "MBC5+RAM+BATTERY",
32  [0x1C] = "MBC5+RUMBLE",
33  [0x1D] = "MBC5+RUMBLE+RAM",
34  [0x1E] = "MBC5+RUMBLE+RAM+BATTERY",
35  [0xFC] = "POCKET CAMERA",
36  [0xFD] = "BANDAI TAMA5",
37  [0xFE] = "HuC3",
38  [0xFF] = "HuC1+RAM+BATTERY",
39 };
40 
41 static char *banks[] = {
42  " 32KiB",
43  " 64KiB",
44  "128KiB",
45  "256KiB",
46  "512KiB",
47  " 1MiB",
48  " 2MiB",
49  " 4MiB",
50  /* 0x52 */
51  "1.1MiB",
52  "1.2MiB",
53  "1.5MiB",
54  "Unknown"
55 };
56 
57 static const int bank_sizes[] = {
58  32*1024,
59  64*1024,
60  128*1024,
61  256*1024,
62  512*1024,
63  1024*1024,
64  2048*1024,
65  4096*1024,
66  1152*1024,
67  1280*1024,
68  1536*1024
69 };
70 
71 static char *rams[] = {
72  "None",
73  " 2KiB",
74  " 8KiB",
75  " 32KiB",
76  "Unknown"
77 };
78 
79 static char *regions[] = {
80  "Japan",
81  "Non-Japan",
82  "Unknown"
83 };
84 
85 static unsigned char header[] = {
86  0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
87  0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
88  0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E,
89  0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99,
90  0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC,
91  0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E
92 };
93 
94 static int rom_init(unsigned char *rombytes, size_t filesize)
95 {
96  char buf[17] = {0};
97  int type, bank_index, ram, region, version, i, pass;
98  unsigned char checksum = 0;
99 
100  if(memcmp((const char*)&rombytes[0x104], (const char*)header, sizeof(header)) != 0)
101  return 0;
102 
103  memcpy(buf, &rombytes[0x134], 16);
104  buf[16] = '\0';
105  printf("Rom title: %s\n", buf);
106 
107  type = (int)rombytes[0x147];
108 
109  printf("Cartridge type: %s (%02X)\n", carts[type], type);
110 
111  bank_index = rombytes[0x148];
112  /* Adjust for the gap in the bank indicies */
113  if(bank_index >= 0x52 && bank_index <= 0x54)
114  bank_index -= 74;
115  else if(bank_index > 7)
116  bank_index = 11;
117 
118  if(bank_index >= 10)
119  {
120  printf("Illegal ROM size in header\n");
121  return 0;
122  }
123 
124  printf("Rom size: %s\n", banks[bank_index]);
125 
126  rom_size = bank_sizes[bank_index];
127 
128  if(rom_size < filesize)
129  {
130  printf("File not big enough for ROM size.\n");
131  return 0;
132  }
133 
134  ram = rombytes[0x149];
135  if(ram > 3)
136  ram = 4;
137 
138  printf("RAM size: %s\n", rams[ram]);
139 
140  region = rombytes[0x14A];
141  if(region > 2)
142  region = 2;
143  printf("Region: %s\n", regions[region]);
144 
145  version = rombytes[0x14C];
146  printf("Version: %02X\n", version);
147 
148  for(i = 0x134; i <= 0x14C; i++)
149  checksum = checksum - rombytes[i] - 1;
150 
151  pass = rombytes[0x14D] == checksum;
152 
153  printf("Checksum: %s (%02X)\n", pass ? "OK" : "FAIL", checksum);
154  if(!pass)
155  return 0;
156 
157  bytes = rombytes;
158 
159  switch(type)
160  {
161  case 0x00:
162  case 0x08:
163  case 0x09:
164  mapper = NROM;
165  break;
166  case 0x01:
167  case 0x02:
168  case 0x03:
169  mapper = MBC1;
170  break;
171  case 0x05:
172  case 0x06:
173  mapper = MBC2;
174  break;
175  case 0x0B:
176  case 0x0C:
177  mapper = MMM01;
178  break;
179  case 0x0F:
180  case 0x10:
181  case 0x11:
182  case 0x12:
183  case 0x13:
184  mapper = MBC3;
185  break;
186  case 0x15:
187  case 0x16:
188  case 0x17:
189  mapper = MBC4;
190  break;
191  case 0x19:
192  case 0x1A:
193  case 0x1B:
194  case 0x1C:
195  case 0x1D:
196  case 0x1E:
197  mapper = MBC5;
198  break;
199  }
200 
201  return 1;
202 }
203 
204 unsigned int rom_get_mapper(void)
205 {
206  return mapper;
207 }
208 
209 int rom_load(const char *filename) {
210  FILE* f;
211  unsigned char *bytes = NULL;
212  size_t rom_size = 0;
213 
214  f = fopen(filename, "r");
215 
216  if(!f)
217  return 0;
218 
219  rom_size = fsize(f);
220 
221  bytes = malloc(rom_size);
222 
223  if(!bytes)
224  return 0;
225 
226  fread(f, rom_size, 1, bytes);
227 
228  return rom_init(bytes, rom_size);
229 }
230 
231 unsigned char *rom_getbytes(void)
232 {
233  return bytes;
234 }
235 
236 int rom_bank_valid(int bank)
237 {
238  if(bank * 0x4000 > rom_size)
239  return 0;
240  return 1;
241 }
size_t filesize(const char *Path)
[FileIO] Возвращает размер указанного файла
Definition: fileio.c:67
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
int32_t memcmp(const char *s1, const char *s2, size_t n)
Сравнение массивов
Definition: string.c:305
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
int fsize(FILE *stream)
Получение размера файла в байтах
Definition: stdio.c:227
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21