gba.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /*
  2. gba.c - Game Boy Advance support for uCON64
  3. Copyright (c) 2001 NoisyB <noisyb@gmx.net>
  4. Copyright (c) 2001 - 2004 dbjh
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #ifdef HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #include <sys/stat.h>
  27. #include "misc/file.h"
  28. #include "misc/misc.h"
  29. #include "misc/property.h"
  30. #ifdef USE_ZLIB
  31. #include "misc/archive.h"
  32. #endif
  33. #include "misc/getopt2.h" // st_getopt2_t
  34. #include "misc/string.h"
  35. #include "ucon64.h"
  36. #include "ucon64_misc.h"
  37. #include "gba.h"
  38. #include "backup/fal.h"
  39. #define GBA_NAME_LEN 12
  40. #define GBA_HEADER_START 0
  41. #define GBA_HEADER_LEN (sizeof (st_gba_header_t))
  42. static int gba_chksum (void);
  43. const st_getopt2_t gba_usage[] =
  44. {
  45. {
  46. NULL, 0, 0, 0,
  47. NULL, "Game Boy Advance"/*"2001 Nintendo http://www.nintendo.com"*/,
  48. NULL
  49. },
  50. {
  51. "gba", 0, 0, UCON64_GBA,
  52. NULL, "force recognition",
  53. &ucon64_wf[WF_OBJ_GBA_SWITCH]
  54. },
  55. {
  56. "n", 1, 0, UCON64_N,
  57. "NEW_NAME", "change internal ROM name to NEW_NAME",
  58. &ucon64_wf[WF_OBJ_ALL_DEFAULT]
  59. },
  60. {
  61. "logo", 0, 0, UCON64_LOGO,
  62. NULL, "restore ROM logo character data (offset: 0x04-0x9F)",
  63. &ucon64_wf[WF_OBJ_ALL_DEFAULT]
  64. },
  65. {
  66. "chk", 0, 0, UCON64_CHK,
  67. NULL, "fix ROM header checksum",
  68. &ucon64_wf[WF_OBJ_ALL_DEFAULT]
  69. },
  70. {
  71. "sram", 0, 0, UCON64_SRAM,
  72. NULL, "patch ROM for SRAM saving",
  73. &ucon64_wf[WF_OBJ_GBA_DEFAULT]
  74. },
  75. {
  76. "crp", 1, 0, UCON64_CRP,
  77. "WAIT_TIME", "slow down ROM access (\"crash patch\");\n"
  78. "WAIT_TIME=0 default in most crash patches\n"
  79. "WAIT_TIME=4 faster than 0, slower than 8\n"
  80. "WAIT_TIME=8 faster than 4, slower than 28\n"
  81. "WAIT_TIME=12 slowest cartridge access speed\n"
  82. "WAIT_TIME=16 faster than 28, but slower than 20\n"
  83. "WAIT_TIME=20 default in most original cartridges\n"
  84. "WAIT_TIME=24 fastest cartridge access speed\n"
  85. "WAIT_TIME=28 faster than 8 but slower than 16",
  86. &ucon64_wf[WF_OBJ_GBA_DEFAULT]
  87. },
  88. // "n 0 and 28, with a stepping of 4. I.e. 0, 4, 8, 12 ...\n"
  89. {
  90. "multi", 1, 0, UCON64_MULTI,
  91. "SIZE", "make multi-game file for use with FAL/F2A flash card, truncated\n"
  92. "to SIZE Mbit; file with loader must be specified first, then\n"
  93. "all the ROMs, multi-game file to create last",
  94. &ucon64_wf[WF_OBJ_ALL_INIT_PROBE_STOP]
  95. },
  96. {NULL, 0, 0, 0, NULL, NULL, NULL}
  97. };
  98. /*
  99. Offset 00h-03h - Start Address - A 32 bit ARM B command with jump destination
  100. to the start address of the program, cannot be manipulated
  101. with this tool, there's no reason.
  102. Offset 04h-9fh - Nintendo logo character data - The fix Nintendo logo graphics
  103. needed to start a ROM on the real machine as it is verified
  104. by it.
  105. Offset a0h-abh - Game title - The game title is an ASCII string, officially
  106. can use only ASCII characters between the ASCII code 20h and
  107. 60h. Although it is not a strict rule for hobby programmers,
  108. it is fun to follow such a rules in my opinion. As I know
  109. developers can choose their own game title here describing
  110. the product in short.
  111. Offset ach-afh - Game code - The 4 bytes long code of the game is an ASCII
  112. string too, officially can use only ASCII characters between
  113. the ASCII code 20h and 60h. The first letter is always A as I
  114. know, probably stands for GBA, so it won't change unless a
  115. higher hardware with backwards compatibility won't be
  116. introduced and this letter could hold some more infos about
  117. it. The second and third letters are the shortened version of
  118. the name of the game. And the fourth letter is the territory
  119. code. Don't afraid, there's no territory lockout, this is for
  120. information purposes only. So far as I know J stands for
  121. Japan and Asia, E stands for USA and the whole American
  122. continent and P stands for Europe, Australia and Africa
  123. (probably came from that these are the PAL video standard
  124. territories, but I could be wrong). Although it is not a
  125. strict rule for hobby programmers, it is fun to follow such a
  126. rules in my opinion. Developers get this 4 letter code right
  127. from Nintendo and they have to use that.
  128. Offset b0h-b1h - Maker code - The 2 bytes long code of the developer company
  129. is an ASCII string too, officially can use only ASCII
  130. characters between the ASCII code 20h and 60h. Although it is
  131. not a strict rule for hobby programmers, it is fun to follow
  132. such a rules in my opinion. Developers get this 2 letter code
  133. right from Nintendo and they have to use that.
  134. Offset b2h-b2h - 96h - Fixed 96h byte without any useful information.
  135. Offset b3h-b3h - Main unit code - This hexadecimal byte is the destination
  136. hardware code. It is always 00h at the moment as it stands
  137. for Game Boy Advance, so it won't change in the future either
  138. unless a higher hardware with backwards compatibility won't
  139. be introduced and this byte could hold some more infos about
  140. it. There's no reason to change this or write something
  141. different than 00h into it.
  142. Offset b4h-b4h - Device type - This hexadecimal byte is the device type code.
  143. It is always 00h as the only other possible value stands for
  144. a debugger cart what I assume won't be available on the
  145. streets and I assume even if a developer works with such a
  146. hardware, he or she doesn't have to change this byte, however
  147. he or she easily can of course. So there's no reason to
  148. change this or write something different than 00h into it.
  149. Offset b5h-bbh - Reserved area - Fixed, 00h filled area without any useful
  150. information.
  151. Offset bch-bch - Mask ROM version number - This hexadecimal byte holds the
  152. version number of the ROM. As I know it works somehow that
  153. way, the first published (and released on the streets) is
  154. always the first version and for that 00h is stored here. In
  155. the case it is getting updated, so in the same territory the
  156. very same game with the very same title is getting replaced
  157. with a new version, what is happening rarely, the number here
  158. is getting increased by one. So usually this byte holds 00h
  159. and there isn't too much reason to write something here and
  160. something else than 00h.
  161. Offset bdh-bdh - Complement check - This hexadecimal byte have to be
  162. calculated automatically, when the whole header is in its
  163. final state, so nothing will change inside of it. (Manually
  164. it would be hard to calculate.) Add the bytes between offset
  165. a0h and bch together, take the number's two's complement and
  166. add 19h to the result. Store the lowest 8 bits here. Or
  167. calculate automatically with GBARM. The hardware is
  168. verifying this byte just like the Nintendo logo character
  169. data and in the case it isn't correct, the game won't start
  170. on the real machine.
  171. Offset beh-bfh - Reserved area - Fixed, 00h filled area without any useful
  172. information.
  173. */
  174. typedef struct st_gba_header
  175. {
  176. unsigned char start[4]; // 0x00
  177. unsigned char logo[GBA_LOGODATA_LEN]; // 0x04
  178. unsigned char name[GBA_NAME_LEN]; // 0xa0
  179. unsigned char game_id_prefix; // 0xac
  180. unsigned char game_id_low; // 0xad
  181. unsigned char game_id_high; // 0xae
  182. unsigned char game_id_country; // 0xaf
  183. unsigned char maker_high; // 0xb0
  184. unsigned char maker_low; // 0xb1
  185. unsigned char pad1;
  186. unsigned char gba_type; // 0xb3
  187. unsigned char device_type; // 0xb4
  188. unsigned char pad2[7];
  189. unsigned char version; // 0xbc
  190. unsigned char checksum; // 0xbd
  191. unsigned char pad3[2];
  192. } st_gba_header_t;
  193. static st_gba_header_t gba_header;
  194. const unsigned char gba_logodata[] = // Note: not a static variable
  195. {
  196. 0x24, 0xff, 0xae, 0x51,
  197. 0x69, 0x9a, 0xa2, 0x21, 0x3d, 0x84, 0x82, 0x0a,
  198. 0x84, 0xe4, 0x09, 0xad, 0x11, 0x24, 0x8b, 0x98,
  199. 0xc0, 0x81, 0x7f, 0x21, 0xa3, 0x52, 0xbe, 0x19,
  200. 0x93, 0x09, 0xce, 0x20, 0x10, 0x46, 0x4a, 0x4a,
  201. 0xf8, 0x27, 0x31, 0xec, 0x58, 0xc7, 0xe8, 0x33,
  202. 0x82, 0xe3, 0xce, 0xbf, 0x85, 0xf4, 0xdf, 0x94,
  203. 0xce, 0x4b, 0x09, 0xc1, 0x94, 0x56, 0x8a, 0xc0,
  204. 0x13, 0x72, 0xa7, 0xfc, 0x9f, 0x84, 0x4d, 0x73,
  205. 0xa3, 0xca, 0x9a, 0x61, 0x58, 0x97, 0xa3, 0x27,
  206. 0xfc, 0x03, 0x98, 0x76, 0x23, 0x1d, 0xc7, 0x61,
  207. 0x03, 0x04, 0xae, 0x56, 0xbf, 0x38, 0x84, 0x00,
  208. 0x40, 0xa7, 0x0e, 0xfd, 0xff, 0x52, 0xfe, 0x03,
  209. 0x6f, 0x95, 0x30, 0xf1, 0x97, 0xfb, 0xc0, 0x85,
  210. 0x60, 0xd6, 0x80, 0x25, 0xa9, 0x63, 0xbe, 0x03,
  211. 0x01, 0x4e, 0x38, 0xe2, 0xf9, 0xa2, 0x34, 0xff,
  212. 0xbb, 0x3e, 0x03, 0x44, 0x78, 0x00, 0x90, 0xcb,
  213. 0x88, 0x11, 0x3a, 0x94, 0x65, 0xc0, 0x7c, 0x63,
  214. 0x87, 0xf0, 0x3c, 0xaf, 0xd6, 0x25, 0xe4, 0x8b,
  215. 0x38, 0x0a, 0xac, 0x72, 0x21, 0xd4, 0xf8, 0x07
  216. };
  217. int
  218. gba_n (st_rominfo_t *rominfo, const char *name)
  219. {
  220. char buf[GBA_NAME_LEN], dest_name[FILENAME_MAX];
  221. memset (buf, 0, GBA_NAME_LEN);
  222. strncpy (buf, name, GBA_NAME_LEN);
  223. strcpy (dest_name, ucon64.rom);
  224. ucon64_file_handler (dest_name, NULL, 0);
  225. fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
  226. ucon64_fwrite (buf, GBA_HEADER_START + rominfo->buheader_len + 0xa0, GBA_NAME_LEN,
  227. dest_name, "r+b");
  228. printf (ucon64_msg[WROTE], dest_name);
  229. return 0;
  230. }
  231. int
  232. gba_logo (st_rominfo_t *rominfo)
  233. {
  234. char dest_name[FILENAME_MAX];
  235. strcpy (dest_name, ucon64.rom);
  236. ucon64_file_handler (dest_name, NULL, 0);
  237. fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
  238. ucon64_fwrite (gba_logodata, GBA_HEADER_START + rominfo->buheader_len + 0x04,
  239. GBA_LOGODATA_LEN, dest_name, "r+b");
  240. printf (ucon64_msg[WROTE], dest_name);
  241. return 0;
  242. }
  243. int
  244. gba_chk (st_rominfo_t *rominfo)
  245. {
  246. char buf, dest_name[FILENAME_MAX];
  247. strcpy (dest_name, ucon64.rom);
  248. ucon64_file_handler (dest_name, NULL, 0);
  249. fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
  250. buf = rominfo->current_internal_crc;
  251. ucon64_fputc (dest_name, GBA_HEADER_START + rominfo->buheader_len + 0xbd,
  252. buf, "r+b");
  253. dumper (stdout, &buf, 1, GBA_HEADER_START + rominfo->buheader_len + 0xbd, DUMPER_HEX);
  254. printf (ucon64_msg[WROTE], dest_name);
  255. return 0;
  256. }
  257. int
  258. gba_sram (void)
  259. // This function is based on Omar Kilani's gbautil 1.1
  260. {
  261. unsigned char st_orig[2][10] =
  262. {
  263. { 0x0E, 0x48, 0x39, 0x68, 0x01, 0x60, 0x0E, 0x48, 0x79, 0x68 },
  264. { 0x13, 0x4B, 0x18, 0x60, 0x13, 0x48, 0x01, 0x60, 0x13, 0x49 }
  265. },
  266. st_repl[2][10] =
  267. {
  268. { 0x00, 0x48, 0x00, 0x47, 0x01, 0xFF, 0xFF, 0x08, 0x79, 0x68 },
  269. { 0x01, 0x4C, 0x20, 0x47, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x08 }
  270. },
  271. fl_orig[2][24] =
  272. {
  273. {
  274. 0xD0, 0x20, 0x00, 0x05, 0x01, 0x88, 0x01, 0x22, 0x08, 0x1C,
  275. 0x10, 0x40, 0x02, 0x1C, 0x11, 0x04, 0x08, 0x0C, 0x00, 0x28,
  276. 0x01, 0xD0, 0x1B, 0xE0
  277. },
  278. {
  279. 0xD0, 0x21, 0x09, 0x05, 0x01, 0x23, 0x0C, 0x4A, 0x08, 0x88,
  280. 0x18, 0x40, 0x00, 0x28, 0x08, 0xD1, 0x10, 0x78, 0x00, 0x28,
  281. 0xF8, 0xD0, 0x08, 0x88
  282. }
  283. },
  284. fl_repl[2][24] =
  285. {
  286. {
  287. 0xE0, 0x20, 0x00, 0x05, 0x01, 0x88, 0x01, 0x22, 0x08, 0x1C,
  288. 0x10, 0x40, 0x02, 0x1C, 0x11, 0x04, 0x08, 0x0C, 0x00, 0x28,
  289. 0x01, 0xD0, 0x1B, 0xE0
  290. },
  291. {
  292. 0xE0, 0x21, 0x09, 0x05, 0x01, 0x23, 0x0C, 0x4A, 0x08, 0x88,
  293. 0x18, 0x40, 0x00, 0x28, 0x08, 0xD1, 0x10, 0x78, 0x00, 0x28,
  294. 0xF8, 0xD0, 0x08, 0x88
  295. }
  296. },
  297. p_repl[2][188] =
  298. {
  299. {
  300. 0x39, 0x68, 0x27, 0x48, 0x81, 0x42, 0x23, 0xD0, 0x89, 0x1C,
  301. 0x08, 0x88, 0x01, 0x28, 0x02, 0xD1, 0x24, 0x48, 0x78, 0x60,
  302. 0x33, 0xE0, 0x00, 0x23, 0x00, 0x22, 0x89, 0x1C, 0x10, 0xB4,
  303. 0x01, 0x24, 0x08, 0x68, 0x20, 0x40, 0x5B, 0x00, 0x03, 0x43,
  304. 0x89, 0x1C, 0x52, 0x1C, 0x06, 0x2A, 0xF7, 0xD1, 0x10, 0xBC,
  305. 0x39, 0x60, 0xDB, 0x01, 0x02, 0x20, 0x00, 0x02, 0x1B, 0x18,
  306. 0x0E, 0x20, 0x00, 0x06, 0x1B, 0x18, 0x7B, 0x60, 0x39, 0x1C,
  307. 0x08, 0x31, 0x08, 0x88, 0x09, 0x38, 0x08, 0x80, 0x16, 0xE0,
  308. 0x15, 0x49, 0x00, 0x23, 0x00, 0x22, 0x10, 0xB4, 0x01, 0x24,
  309. 0x08, 0x68, 0x20, 0x40, 0x5B, 0x00, 0x03, 0x43, 0x89, 0x1C,
  310. 0x52, 0x1C, 0x06, 0x2A, 0xF7, 0xD1, 0x10, 0xBC, 0xDB, 0x01,
  311. 0x02, 0x20, 0x00, 0x02, 0x1B, 0x18, 0x0E, 0x20, 0x00, 0x06,
  312. 0x1B, 0x18, 0x08, 0x3B, 0x3B, 0x60, 0x0B, 0x48, 0x39, 0x68,
  313. 0x01, 0x60, 0x0A, 0x48, 0x79, 0x68, 0x01, 0x60, 0x0A, 0x48,
  314. 0x39, 0x1C, 0x08, 0x31, 0x0A, 0x88, 0x80, 0x21, 0x09, 0x06,
  315. 0x0A, 0x43, 0x02, 0x60, 0x07, 0x48, 0x00, 0x47, 0x00, 0x00,
  316. 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x04, 0x00,
  317. 0x00, 0x0E, 0xD4, 0x00, 0x00, 0x04, 0xD8, 0x00, 0x00, 0x04,
  318. 0xDC, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0x08
  319. },
  320. {
  321. 0x22, 0x4C, 0x84, 0x42, 0x20, 0xD0, 0x80, 0x1C, 0x04, 0x88,
  322. 0x01, 0x25, 0x2C, 0x40, 0x01, 0x2C, 0x02, 0xD1, 0x80, 0x1E,
  323. 0x1E, 0x49, 0x2E, 0xE0, 0x00, 0x23, 0x00, 0x24, 0x80, 0x1C,
  324. 0x40, 0xB4, 0x01, 0x26, 0x05, 0x68, 0x35, 0x40, 0x5B, 0x00,
  325. 0x2B, 0x43, 0x80, 0x1C, 0x64, 0x1C, 0x06, 0x2C, 0xF7, 0xD1,
  326. 0x40, 0xBC, 0xDB, 0x01, 0x02, 0x24, 0x24, 0x02, 0x1B, 0x19,
  327. 0x0E, 0x24, 0x24, 0x06, 0x1B, 0x19, 0x19, 0x1C, 0x09, 0x3A,
  328. 0x16, 0xE0, 0x12, 0x48, 0x00, 0x23, 0x00, 0x24, 0x40, 0xB4,
  329. 0x01, 0x26, 0x05, 0x68, 0x35, 0x40, 0x5B, 0x00, 0x2B, 0x43,
  330. 0x80, 0x1C, 0x64, 0x1C, 0x06, 0x2C, 0xF7, 0xD1, 0x40, 0xBC,
  331. 0xDB, 0x01, 0x02, 0x24, 0x24, 0x02, 0x1B, 0x19, 0x0E, 0x24,
  332. 0x24, 0x06, 0x1B, 0x19, 0x08, 0x3B, 0x18, 0x1C, 0x08, 0x4C,
  333. 0x20, 0x60, 0x08, 0x4C, 0x21, 0x60, 0x08, 0x49, 0x80, 0x20,
  334. 0x00, 0x06, 0x02, 0x43, 0x0A, 0x60, 0x06, 0x4C, 0x20, 0x47,
  335. 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x04, 0x00,
  336. 0x00, 0x0E, 0xD4, 0x00, 0x00, 0x04, 0xD8, 0x00, 0x00, 0x04,
  337. 0xDC, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0x08
  338. }
  339. },
  340. major, minor, micro, *buffer, *bufferptr, *ptr, value;
  341. char dest_name[FILENAME_MAX];
  342. int p_size[2] = { 188, 168 }, p_off, st_off;
  343. unsigned int fsize = ucon64.file_size;
  344. FILE *destfile;
  345. strcpy (dest_name, ucon64.rom);
  346. ucon64_file_handler (dest_name, NULL, 0);
  347. fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
  348. if ((destfile = fopen (dest_name, "rb+")) == NULL)
  349. {
  350. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name);
  351. return -1;
  352. }
  353. if (!(buffer = (unsigned char *) malloc (fsize)))
  354. {
  355. fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], fsize);
  356. fclose (destfile);
  357. exit (1);
  358. }
  359. if (fread (buffer, 1, fsize, destfile) != fsize)
  360. {
  361. fprintf (stderr, ucon64_msg[READ_ERROR], dest_name);
  362. free (buffer);
  363. fclose (destfile);
  364. return -1;
  365. }
  366. bufferptr = buffer + 160 + 12 + 4;
  367. ptr = (unsigned char *) memmem2 (bufferptr, fsize, "EEPROM_", 7, 0);
  368. if (ptr == 0)
  369. {
  370. printf ("This ROM does not appear to use EEPROM saving\n");
  371. free (buffer);
  372. fclose (destfile);
  373. return -1;
  374. }
  375. major = ptr[8] - '0';
  376. minor = ptr[9] - '0';
  377. micro = ptr[10] - '0';
  378. if (ucon64.quiet < 0)
  379. printf ("version: %d.%d.%d; offset: 0x%08x\n",
  380. major, minor, micro, (int) (ptr - buffer));
  381. if (minor > 2)
  382. {
  383. fputs ("ERROR: ROMs with an EEPROM minor version higher than 2 are not supported\n", stderr);
  384. free (buffer);
  385. fclose (destfile);
  386. return -1;
  387. }
  388. ptr = (unsigned char *) memmem2 (bufferptr, fsize,
  389. fl_orig[minor - 1], sizeof (fl_orig[minor - 1]), 0);
  390. if (ptr == 0)
  391. {
  392. fputs ("ERROR: Could not find fl pattern. Perhaps this file is already patched?\n", stderr);
  393. free (buffer);
  394. fclose (destfile);
  395. return -1;
  396. }
  397. if (ucon64.quiet < 0)
  398. printf ("fl offset: 0x%08x\n", (int) (ptr - buffer));
  399. fseek (destfile, ptr - buffer, SEEK_SET);
  400. fwrite (fl_repl[minor - 1], 1, sizeof (fl_repl[minor - 1]), destfile);
  401. ptr = buffer + fsize - 1;
  402. value = *ptr;
  403. do
  404. ptr--;
  405. while (*ptr == value && ptr - buffer > 0);
  406. p_off = (ptr - buffer + 0xff) & ~0xff; // align at 256 byte boundary
  407. if (ucon64.quiet < 0)
  408. printf ("p_off: 0x%08x\n", p_off);
  409. // if the SRAM function won't fit at the end of the ROM, abort
  410. if ((minor == 1 && (int) (fsize - 188) < p_off) ||
  411. (minor == 2 && (int) (fsize - 168) < p_off))
  412. {
  413. fputs ("ERROR: Not enough room for SRAM function at end of ROM\n", stderr);
  414. free (buffer);
  415. fclose (destfile);
  416. return -1;
  417. }
  418. ptr = (unsigned char *) memmem2 (bufferptr, fsize,
  419. st_orig[minor - 1], sizeof (st_orig[minor - 1]), 0);
  420. if (ptr == 0)
  421. {
  422. fputs ("ERROR: Could not find st pattern\n", stderr);
  423. free (buffer);
  424. fclose (destfile);
  425. return -1;
  426. }
  427. st_off = ptr - buffer;
  428. if (ucon64.quiet < 0)
  429. printf ("st offset: 0x%08x\n", st_off);
  430. bufferptr = buffer + p_off;
  431. switch (minor)
  432. {
  433. case 1:
  434. // these are the offsets to the caller function, it handles all saving and
  435. // is at st_off
  436. p_repl[minor - 1][184] = (unsigned char) (st_off + 0x21);
  437. p_repl[minor - 1][186] = (unsigned char) (st_off >> 16);
  438. if (*(bufferptr - 1) == 0xff)
  439. p_repl[minor - 1][185] = (unsigned char) (st_off >> 8);
  440. else
  441. {
  442. st_off += 0x1f;
  443. p_repl[minor - 1][185] = (unsigned char) (st_off >> 8);
  444. }
  445. // tell the calling function where the SRAM function is (p_off)
  446. st_repl[minor - 1][5] = (unsigned char) (p_off >> 8);
  447. st_repl[minor - 1][6] = (unsigned char) (p_off >> 16);
  448. break;
  449. case 2:
  450. // offsets to the caller function
  451. p_repl[minor - 1][164] = (unsigned char) (st_off + 0x13);
  452. p_repl[minor - 1][165] = (unsigned char) (st_off >> 8);
  453. p_repl[minor - 1][166] = (unsigned char) (st_off >> 16);
  454. // tell the calling function where the SRAM function is
  455. st_repl[minor - 1][7] = (unsigned char) (p_off >> 8);
  456. st_repl[minor - 1][8] = (unsigned char) (p_off >> 16);
  457. break;
  458. }
  459. fseek (destfile, st_off, SEEK_SET);
  460. fwrite (st_repl[minor - 1], 1, sizeof (st_repl[minor - 1]), destfile);
  461. fseek (destfile, p_off, SEEK_SET);
  462. fwrite (p_repl[minor - 1], 1, p_size[minor - 1], destfile);
  463. free (buffer);
  464. fclose (destfile);
  465. puts ("SRAM patch applied");
  466. printf (ucon64_msg[WROTE], dest_name);
  467. return 0;
  468. }
  469. int
  470. gba_crp (st_rominfo_t *rominfo, const char *value)
  471. {
  472. FILE *srcfile, *destfile;
  473. int bytesread, n = 0;
  474. char buffer[32 * 1024], src_name[FILENAME_MAX], dest_name[FILENAME_MAX],
  475. replace[2], wait_time = atoi (value);
  476. if (wait_time % 4 != 0 || wait_time > 28 || wait_time < 0)
  477. {
  478. fprintf (stderr, "ERROR: You specified an incorrect WAIT_TIME value\n");
  479. return -1;
  480. }
  481. puts ("Applying crash patch...");
  482. strcpy (src_name, ucon64.rom);
  483. strcpy (dest_name, ucon64.rom);
  484. ucon64_file_handler (dest_name, src_name, 0);
  485. if ((srcfile = fopen (src_name, "rb")) == NULL)
  486. {
  487. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], src_name);
  488. return -1;
  489. }
  490. if ((destfile = fopen (dest_name, "wb")) == NULL)
  491. {
  492. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name);
  493. return -1;
  494. }
  495. if (rominfo->buheader_len) // copy header (if present)
  496. {
  497. fread (buffer, 1, rominfo->buheader_len, srcfile);
  498. fwrite (buffer, 1, rominfo->buheader_len, destfile);
  499. }
  500. replace[0] = wait_time;
  501. replace[1] = 0x40;
  502. while ((bytesread = fread (buffer, 1, 32 * 1024, srcfile)))
  503. { // '!' == ASCII 33 (\x21), '*' == 42 (\x2a)
  504. n += change_mem (buffer, bytesread, "\x04\x02\x00\x04\x14\x40", 6, '*', '!', replace, 1, -1);
  505. n += change_mem (buffer, bytesread, "\x02\x00\x04\x14\x40\x00", 6, '*', '!', replace, 1, -2);
  506. n += change_mem (buffer, bytesread, "\x04\x02\x00\x04\xB4\x45", 6, '*', '!', replace, 2, -1);
  507. n += change_mem (buffer, bytesread, "\x3E\xE0\x00\x00\xB4\x45", 6, '*', '!', replace, 2, -1);
  508. n += change_mem (buffer, bytesread, "\x04\x02\x00\x04\x94\x44", 6, '*', '!', replace, 2, -1);
  509. fwrite (buffer, 1, bytesread, destfile);
  510. }
  511. fclose (srcfile);
  512. fclose (destfile);
  513. printf ("Found %d pattern%s\n", n, n != 1 ? "s" : "");
  514. printf (ucon64_msg[WROTE], dest_name);
  515. remove_temp_file ();
  516. return 0;
  517. }
  518. int
  519. gba_init (st_rominfo_t *rominfo)
  520. {
  521. int result = -1, value;
  522. char buf[MAXBUFSIZE];
  523. rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
  524. ucon64.buheader_len : 0;
  525. ucon64_fread (&gba_header, GBA_HEADER_START +
  526. rominfo->buheader_len, GBA_HEADER_LEN, ucon64.rom);
  527. if (/*gba_header.game_id_prefix == 'A' && */ // 'B' in Mario vs. Donkey Kong
  528. gba_header.start[3] == 0xea && gba_header.pad1 == 0x96 && gba_header.gba_type == 0)
  529. result = 0;
  530. else
  531. {
  532. #if 0 // AFAIK (dbjh) GBA ROMs never have a header
  533. rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
  534. ucon64.buheader_len : UNKNOWN_HEADER_LEN;
  535. ucon64_fread (&gba_header, GBA_HEADER_START +
  536. rominfo->buheader_len, GBA_HEADER_LEN, ucon64.rom);
  537. if (gba_header.game_id_prefix == 'A' && gba_header.gba_type == 0)
  538. result = 0;
  539. else
  540. #endif
  541. result = -1;
  542. }
  543. if (ucon64.console == UCON64_GBA)
  544. result = 0;
  545. rominfo->header_start = GBA_HEADER_START;
  546. rominfo->header_len = GBA_HEADER_LEN;
  547. rominfo->header = &gba_header;
  548. // internal ROM name
  549. strncpy (rominfo->name, (const char *) gba_header.name, GBA_NAME_LEN);
  550. rominfo->name[GBA_NAME_LEN] = 0;
  551. // ROM maker
  552. {
  553. int ih = gba_header.maker_high <= '9' ?
  554. gba_header.maker_high - '0' : gba_header.maker_high - 'A' + 10,
  555. il = gba_header.maker_low <= '9' ?
  556. gba_header.maker_low - '0' : gba_header.maker_low - 'A' + 10;
  557. value = ih * 36 + il;
  558. }
  559. if (value < 0 || value >= NINTENDO_MAKER_LEN)
  560. value = 0;
  561. rominfo->maker = NULL_TO_UNKNOWN_S (nintendo_maker[value]);
  562. // ROM country
  563. rominfo->country =
  564. (gba_header.game_id_country == 'J') ? "Japan/Asia" :
  565. (gba_header.game_id_country == 'E') ? "U.S.A." :
  566. (gba_header.game_id_country == 'P') ? "Europe, Australia and Africa" :
  567. "Unknown country";
  568. // misc stuff
  569. sprintf (buf, "Version: %d\n", gba_header.version);
  570. strcat (rominfo->misc, buf);
  571. sprintf (buf, "Device type: 0x%02x\n", gba_header.device_type);
  572. strcat (rominfo->misc, buf);
  573. /*
  574. start address = current address + (parameter of B instruction * 4) + 8
  575. gba_header.start[3] is opcode of B instruction (0xea)
  576. */
  577. value = 0x8000008 +
  578. (gba_header.start[2] << 18 | gba_header.start[1] << 10 | gba_header.start[0] << 2);
  579. sprintf (buf, "Start address: 0x%08x\n", value);
  580. strcat (rominfo->misc, buf);
  581. strcat (rominfo->misc, "Logo data: ");
  582. if (memcmp (gba_header.logo, gba_logodata, GBA_LOGODATA_LEN) == 0)
  583. {
  584. #ifdef USE_ANSI_COLOR
  585. if (ucon64.ansi_color)
  586. strcat (rominfo->misc, "\x1b[01;32mOk\x1b[0m");
  587. else
  588. #endif
  589. strcat (rominfo->misc, "Ok");
  590. }
  591. else
  592. {
  593. #ifdef USE_ANSI_COLOR
  594. if (ucon64.ansi_color)
  595. strcat (rominfo->misc, "\x1b[01;31mBad\x1b[0m");
  596. else
  597. #endif
  598. strcat (rominfo->misc, "Bad");
  599. }
  600. // internal ROM crc
  601. if (!UCON64_ISSET (ucon64.do_not_calc_crc) && result == 0)
  602. {
  603. rominfo->has_internal_crc = 1;
  604. rominfo->internal_crc_len = 1;
  605. rominfo->current_internal_crc = gba_chksum ();
  606. rominfo->internal_crc = gba_header.checksum;
  607. rominfo->internal_crc2[0] = 0;
  608. }
  609. rominfo->console_usage = gba_usage[0].help;
  610. // We use fal_usage, but we could just as well use f2a_usage
  611. rominfo->copier_usage = (!rominfo->buheader_len ? fal_usage[0].help : unknown_usage[0].help);
  612. return result;
  613. }
  614. int
  615. gba_chksum (void)
  616. // Note that this function only calculates the checksum of the internal header
  617. {
  618. unsigned char sum = 0x19, *ptr = (unsigned char *) &gba_header + 0xa0;
  619. while (ptr < (unsigned char *) &gba_header + 0xbd)
  620. sum += *ptr++;
  621. sum = -sum;
  622. return sum;
  623. }
  624. int
  625. gba_multi (int truncate_size, char *multi_fname)
  626. // TODO: Check if 1024 Mbit multi-game files are supported by the FAL code
  627. {
  628. #define BUFSIZE (32 * 1024)
  629. int n, n_files, file_no, bytestowrite, byteswritten, totalsize = 0, done,
  630. truncated = 0, size_pow2_lesser = 1, size_pow2 = 1, truncate_size_ispow2 = 0;
  631. struct stat fstate;
  632. FILE *srcfile, *destfile;
  633. char buffer[BUFSIZE], fname[FILENAME_MAX], *fname_ptr;
  634. if (truncate_size == 0)
  635. {
  636. fprintf (stderr, "ERROR: Can't make multi-game file of 0 bytes\n");
  637. return -1;
  638. }
  639. #if 0
  640. if (truncate_size != 64 * MBIT && truncate_size != 128 * MBIT &&
  641. truncate_size != 256 * MBIT && truncate_size != 512 * MBIT &&
  642. truncate_size != 1024 * MBIT)
  643. {
  644. fprintf (stderr, "ERROR: Truncate size must be 64, 128, 256, 512 or 1024\n");
  645. return -1;
  646. }
  647. #endif
  648. if (multi_fname != NULL) // -xfalmulti
  649. {
  650. strcpy (fname, multi_fname);
  651. n_files = ucon64.argc;
  652. }
  653. else // -multi
  654. {
  655. strcpy (fname, ucon64.argv[ucon64.argc - 1]);
  656. n_files = ucon64.argc - 1;
  657. }
  658. ucon64_file_handler (fname, NULL, OF_FORCE_BASENAME);
  659. if ((destfile = fopen (fname, "wb")) == NULL)
  660. {
  661. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], fname);
  662. return -1;
  663. }
  664. printf ("Creating multi-game file for FAL(/F2A): %s\n", fname);
  665. file_no = 0;
  666. for (n = 1; n < n_files; n++)
  667. {
  668. if (access (ucon64.argv[n], F_OK))
  669. continue; // "file" does not exist (option)
  670. stat (ucon64.argv[n], &fstate);
  671. if (!S_ISREG (fstate.st_mode))
  672. continue;
  673. if (file_no == 0)
  674. {
  675. if (multi_fname != NULL) // -xfalmulti
  676. {
  677. get_property_fname (ucon64.configfile, "gbaloader", fname, "loader.bin");
  678. if (access (fname, F_OK))
  679. {
  680. fprintf (stderr, "ERROR: Cannot open loader binary (%s)\n", fname);
  681. return -1;
  682. }
  683. fname_ptr = fname;
  684. // NOTE: loop counter is modified, because we have to insert
  685. // loader in the file list
  686. n--;
  687. }
  688. else // -multi
  689. fname_ptr = ucon64.argv[n];
  690. printf ("Loader: %s\n", fname_ptr);
  691. if (fsizeof (fname_ptr) > 64 * 1024)
  692. printf ("WARNING: Are you sure %s is a loader binary?\n", fname_ptr);
  693. }
  694. else
  695. {
  696. fname_ptr = ucon64.argv[n];
  697. printf ("ROM%d: %s\n", file_no, fname_ptr);
  698. }
  699. if ((srcfile = fopen (fname_ptr, "rb")) == NULL)
  700. {
  701. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname_ptr);
  702. continue;
  703. }
  704. done = 0;
  705. byteswritten = 0; // # of bytes written per file
  706. while (!done)
  707. {
  708. bytestowrite = fread (buffer, 1, BUFSIZE, srcfile);
  709. if (totalsize + bytestowrite > truncate_size)
  710. {
  711. bytestowrite = truncate_size - totalsize;
  712. done = 1;
  713. truncated = 1;
  714. printf ("Output file is %d Mbit, truncating %s, skipping %d bytes\n",
  715. truncate_size / MBIT, fname_ptr,
  716. fsizeof (fname_ptr) - (byteswritten + bytestowrite));
  717. // DON'T use fstate.st_size, because file could be compressed
  718. }
  719. totalsize += bytestowrite;
  720. if (bytestowrite == 0)
  721. done = 1;
  722. fwrite (buffer, 1, bytestowrite, destfile);
  723. byteswritten += bytestowrite;
  724. }
  725. fclose (srcfile);
  726. if (truncated)
  727. break;
  728. file_no++;
  729. }
  730. fclose (destfile);
  731. /*
  732. Display a notification if a truncate size was specified that is not exactly
  733. the size of one of the flash card sizes.
  734. */
  735. n = truncate_size;
  736. while (n >>= 1)
  737. size_pow2 <<= 1;
  738. if (truncate_size == size_pow2)
  739. truncate_size_ispow2 = 1;
  740. n = totalsize - 1;
  741. while (n >>= 1)
  742. size_pow2_lesser <<= 1;
  743. size_pow2 = size_pow2_lesser << 1;
  744. if (totalsize > 64 * MBIT && !truncate_size_ispow2)
  745. printf("\n"
  746. "NOTE: This multi-game file can only be written to a card >= %d Mbit.\n"
  747. " Use -multi=%d to create a file truncated to %d Mbit.\n"
  748. " Current size is %.5f Mbit\n", // 5 digits to have 1 byte resolution
  749. size_pow2 / MBIT, size_pow2_lesser / MBIT, size_pow2_lesser / MBIT,
  750. totalsize / (float) MBIT);
  751. return 0;
  752. }