fal.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674
  1. /*
  2. fal.c - Flash Linker Advance support for uCON64
  3. Copyright (c) 2001 Jeff Frohwein
  4. Copyright (c) 2001 NoisyB
  5. Copyright (c) 2001 - 2004 dbjh
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include "config.h"
  20. #endif
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "misc/archive.h"
  24. #include "misc/parallel.h"
  25. #include "misc/term.h"
  26. #include "ucon64_misc.h"
  27. #include "console/gba.h"
  28. #include "backup/fal.h"
  29. #ifdef USE_PARALLEL
  30. static st_ucon64_obj_t fal_obj[] =
  31. {
  32. {UCON64_GBA, WF_DEFAULT | WF_STOP | WF_NO_ROM},
  33. {UCON64_GBA, WF_DEFAULT | WF_STOP},
  34. {UCON64_GBA, WF_STOP | WF_NO_ROM},
  35. {UCON64_GBA, WF_SWITCH}
  36. };
  37. #endif
  38. const st_getopt2_t fal_usage[] =
  39. {
  40. {
  41. NULL, 0, 0, 0,
  42. NULL, "Flash Advance Linker"/*"2001 Visoly http://www.visoly.com"*/,
  43. NULL
  44. },
  45. #ifdef USE_PARALLEL
  46. {
  47. "xfal", 0, 0, UCON64_XFAL,
  48. NULL, "send/receive ROM to/from Flash Advance Linker; " OPTION_LONG_S "port=PORT\n"
  49. "receives automatically (32 Mbits) when ROM does not exist",
  50. &fal_obj[0]
  51. },
  52. {
  53. "xfalmulti", 1, 0, UCON64_XFALMULTI, // send only
  54. "SIZE", "send multiple ROMs to Flash Advance Linker (makes temporary\n"
  55. "multi-game file truncated to SIZE Mbit); specify a loader in\n"
  56. "the configuration file; " OPTION_LONG_S "port=PORT",
  57. &fal_obj[1]
  58. },
  59. {
  60. "xfalc", 1, 0, UCON64_XFALC,
  61. "N", "receive N Mbits of ROM from Flash Advance Linker; " OPTION_LONG_S "port=PORT\n"
  62. "N can be 8, 16, 32, 64, 128 or 256",
  63. &fal_obj[2]
  64. },
  65. {
  66. "xfals", 0, 0, UCON64_XFALS,
  67. NULL, "send/receive SRAM to/from Flash Advance Linker; " OPTION_LONG_S "port=PORT\n"
  68. "receives automatically when SRAM does not exist",
  69. &fal_obj[2]
  70. },
  71. {
  72. "xfalb", 1, 0, UCON64_XFALB,
  73. "BANK", "send/receive SRAM to/from Flash Advance Linker BANK\n"
  74. "BANK can be 1, 2, 3 or 4; " OPTION_LONG_S "port=PORT\n"
  75. "receives automatically when SRAM does not exist",
  76. &fal_obj[2]
  77. },
  78. {
  79. "xfalm", 0, 0, UCON64_XFALM,
  80. NULL, "try to enable EPP mode, default is SPP mode",
  81. &fal_obj[3]
  82. },
  83. #endif // USE_PARALLEL
  84. {NULL, 0, 0, 0, NULL, NULL, NULL}
  85. };
  86. #ifdef USE_PARALLEL
  87. /********************************************************/
  88. /* Flash Linker Advance */
  89. /* by Jeff Frohwein, 2001-Jun-28 */
  90. /* Compiled with DJGPP & linux */
  91. /********************************************************/
  92. // V1.0 - 01/06/28 - Original release
  93. // V1.1 - 01/06/29 - Add -w option to slow down I/O transfer for some.
  94. // V1.11 - 01/06/30 - Set ECP chipsets to proper parallel port mode.
  95. // V1.2 - 01/07/23 - Fixed programming bug for Visoly carts.
  96. // - Only the first block was getting erased.
  97. // - -v option now appears on help (-h) menu.
  98. // - -v & -s options now work properly after fixing a bug.
  99. // V1.3 - 01/07/24 - Added support for Visoly turbo carts.
  100. // V1.4 - 01/07/27 - Added support for longer filenames.
  101. // - Fixed bug where files the size of the cart overwrite
  102. // the first 16 half-words of the cart. Thnx goes to
  103. // Richard W for the code fix. Thanks Richard!
  104. // Fixed random lockup bug when programming Turbo carts.
  105. // Added -n option. Header is now repaired by default.
  106. // V1.5 - 01/09/25 - Added error retries/checking for older Visoly carts.
  107. // - Odd length files no longer give a verify error on last byte+1 location.
  108. // V1.6 - 01/11/11 - Made IRQ 7 instead of 5 and DMA 3 instead of 1 default
  109. // - linux values. (Thanks to Massimiliano Marsiglietti.)
  110. // - Added -D & -I to allow linux to change IRQ & DMA defaults.
  111. // - Added LPT3 support.
  112. // - Added error checking for space between switch & parameters.
  113. // - Added -2 options for faster operation for some EPP ports.
  114. // V1.7 - 01/11/13 - Added -b option to backup game save SRAM or game save Flash.
  115. // - Added -r option to restore game save SRAM. (No flash support.)
  116. // V1.71 - 01/11/23 - Fixed bug introduced in v1.7 where -d option printed out twice.
  117. // V1.72 - 01/12/12 - Force 0x96 at location 0xb2 in header since it's required.
  118. // To compile source on linux:
  119. // cc -o fl fl.c -O2
  120. // You must have root access to run this under linux.
  121. //
  122. // NOTE: This file is filled with cr+lf line terminators. This may
  123. // lead to unhelpful and weird error messages with gcc for linux.
  124. // Strip out the cr characters to prevent this problem. The following
  125. // unix command line will work for that:
  126. // tr -d \\r < dosfile > unixfile
  127. // On some unix distributions you can also use the following command:
  128. // dos2unix
  129. // (Thanks to Massimiliano Marsiglietti for locating this problem.)
  130. // RAM Detect notes for dev. (Just ignore!)
  131. //-----------------------------------------
  132. // To detect backup type.
  133. // 1. First check for eeprom.
  134. // 2. Read byte from 0xe000000.
  135. // 3. Write new byte to 0xe000000.
  136. // 4. If diff, write back data & exit with SRAM detect flag.
  137. // 5. If no diff get device Manuf ID for flash.
  138. // 6. If no Manuf ID detected then report no cart backup available.
  139. #define outpb(p, v) outportb ((unsigned short) (p), (unsigned char) (v)); iodelay ()
  140. #define inpb(p) inportb ((unsigned short) (p))
  141. #define outpw(p, v) outportw ((unsigned short) (p), (unsigned char) (v)); iodelay ()
  142. #define inpw(p) inportw ((unsigned short) (p))
  143. //#define HEADER_LENGTH 0xc0
  144. //#define OUTBUFLEN 256 // Must be a multiple of 2! (ex:64,128,256...)
  145. #define INTEL28F_BLOCKERASE 0x20
  146. #define INTEL28F_CLEARSR 0x50
  147. #define INTEL28F_CONFIRM 0xD0
  148. #define INTEL28F_QUIRY 0x98
  149. #define INTEL28F_READARRAY 0xff
  150. #define INTEL28F_READSR 0x70
  151. #define INTEL28F_RIC 0x90
  152. #define INTEL28F_WRTOBUF 0xe8
  153. #define SHARP28F_BLOCKERASE 0x20
  154. #define SHARP28F_CONFIRM 0xD0
  155. #define SHARP28F_READARRAY 0xff
  156. #define SHARP28F_WORDWRITE 0x10
  157. #define u8 unsigned char
  158. #define u16 unsigned short int
  159. #define u32 unsigned int
  160. #define u64 unsigned long long int
  161. // u64 is needed to compile cartlib.c without warnings on Linux/x86_64
  162. #define CONST_U8 const unsigned char
  163. // ***Global Variables ***
  164. //int WaitDelay,WaitNCDelay;
  165. unsigned SPPDataPort;
  166. unsigned SPPStatPort;
  167. unsigned SPPCtrlPort;
  168. unsigned EPPAddrPort;
  169. unsigned EPPDataPort;
  170. unsigned ECPRegECR;
  171. // prototypes
  172. void WriteFlash (int addr, int data);
  173. int ReadFlash (int addr);
  174. void iodelay (void);
  175. int PPReadWord (void);
  176. void PPWriteWord (int i);
  177. void SetCartAddr (int addr);
  178. void l4021d0 (int i);
  179. void l40226c (void);
  180. #define FLINKER 1
  181. #include "cartlib.c"
  182. static int debug, verbose, DataSize16, Device, EPPMode, RepairHeader,
  183. VisolyTurbo, WaitDelay, FileHeader[0xc0], HeaderBad, Complement = 0;
  184. void
  185. iodelay (void)
  186. {
  187. volatile int i;
  188. for (i = 0; i < WaitDelay; i++)
  189. {
  190. i++;
  191. i--;
  192. }
  193. }
  194. void
  195. ProgramExit (int code)
  196. {
  197. exit (code);
  198. }
  199. #if 0
  200. void
  201. usage (char *name)
  202. {
  203. char _small[255];
  204. char smaller[255];
  205. int i = 0;
  206. strcpy (_small, name);
  207. #if 0
  208. if (strchr (name, '.') != NULL)
  209. _small[strlen (_small) - 4] = 0; /* remove trailing file type */
  210. #endif
  211. while ((_small[strlen (_small) - i] != 0x2f) && /* loop until we find a / */
  212. ((strlen (_small) - i) > 0))
  213. i++;
  214. if ((strlen (_small) - i) == 0)
  215. i++;
  216. strcpy (smaller, (char *) (&_small[strlen (_small) - i + 1]));
  217. fprintf (stderr, "GBA FLinker v1.72 by Jeff F.\n");
  218. fprintf (stderr, "Usage: %s [options]\n", smaller);
  219. fprintf (stderr,
  220. "\t-2 Use 16bit EPP data path for faster operation (default=8bit)\n");
  221. fprintf (stderr,
  222. "\t-b o s file Backup game save SRAM or Flash to file\n");
  223. fprintf (stderr, "\t (o = Bank Number [1-4])\n");
  224. fprintf (stderr, "\t (s=1 - Backup 32K bytes to file.)\n");
  225. fprintf (stderr, "\t (s=2 - Backup 64K bytes to file.)\n");
  226. fprintf (stderr, "\t (s=3 - Backup 128K bytes to file.)\n");
  227. fprintf (stderr, "\t (s=4 - Backup 256K bytes to file.)\n");
  228. fprintf (stderr,
  229. "\t-c n Specify chip size in mbits (8,16,32,64,128,256) (default=32)\n");
  230. fprintf (stderr,
  231. "\t-d n Dump 256 bytes of ROM to screen (default: n=0)\n");
  232. fprintf (stderr, "\t-h This help screen\n");
  233. fprintf (stderr,
  234. "\t-l n Specify the parallel port to use (default is 1 = LPT1)\n");
  235. // fprintf (stderr, "\t-m\tSet Standard Parallel Port (SPP) mode (default = EPP)\n");
  236. fprintf (stderr,
  237. "\t-n Do not repair incorrect header (default = repair header)\n");
  238. fprintf (stderr, "\t-p file Program flash cart with file\n");
  239. fprintf (stderr,
  240. "\t-r o file Restore game save SRAM from file (No save flash support)\n");
  241. fprintf (stderr, "\t (o = Bank Number [1-4])\n");
  242. fprintf (stderr,
  243. "\t-s file Save the cart into a file (Use -c to specify size)\n");
  244. fprintf (stderr, "\t-v file Verify flash cart with file\n");
  245. fprintf (stderr, "\t-w n Add delay to make transfer more reliable\n");
  246. }
  247. #endif
  248. void
  249. InitPort (int port)
  250. {
  251. // uCON64 comment: see the comment in fal_main() where port is initialised
  252. SPPDataPort = port;
  253. SPPStatPort = SPPDataPort + 1;
  254. SPPCtrlPort = SPPDataPort + 2;
  255. EPPAddrPort = SPPDataPort + 3;
  256. EPPDataPort = SPPDataPort + 4;
  257. ECPRegECR = SPPDataPort + 0x402;
  258. }
  259. void
  260. l4020a4 (int reg)
  261. {
  262. outpb (SPPCtrlPort, 1);
  263. outpb (SPPDataPort, reg);
  264. outpb (SPPCtrlPort, 9);
  265. outpb (SPPCtrlPort, 1);
  266. }
  267. void
  268. SPPWriteByte (int i) // l4020dc
  269. {
  270. outpb (SPPDataPort, i);
  271. outpb (SPPCtrlPort, 3);
  272. outpb (SPPCtrlPort, 1);
  273. }
  274. void
  275. l402108 (int reg, int adr)
  276. {
  277. l4020a4 (reg);
  278. SPPWriteByte (adr);
  279. }
  280. int
  281. SPPReadByte (void) // 402124
  282. {
  283. int v;
  284. outpb (SPPCtrlPort, 0);
  285. outpb (SPPCtrlPort, 2);
  286. v = ((inpb (SPPStatPort)) >> 3) & 0xf;
  287. outpb (SPPCtrlPort, 6);
  288. v += (((inpb (SPPStatPort)) << 1) & 0xf0);
  289. outpb (SPPCtrlPort, 0);
  290. return v;
  291. }
  292. void
  293. l402188 (int reg)
  294. {
  295. outpb (SPPCtrlPort, 1);
  296. outpb (EPPAddrPort, reg);
  297. }
  298. void
  299. l4021a8 (int reg, int adr)
  300. {
  301. l402188 (reg);
  302. outpb (SPPCtrlPort, 1);
  303. outpb (EPPDataPort, adr);
  304. }
  305. void
  306. l4021d0 (int i)
  307. {
  308. outpb (SPPCtrlPort, 1);
  309. if (EPPMode)
  310. l402188 (i);
  311. else
  312. l4020a4 (i);
  313. }
  314. void
  315. l402200 (int reg, int adr)
  316. {
  317. if (EPPMode)
  318. l4021a8 (reg, adr);
  319. else
  320. l402108 (reg, adr);
  321. }
  322. void
  323. l402234 (void)
  324. {
  325. if (EPPMode)
  326. l402200 (4, 0x83);
  327. else
  328. l402200 (4, 0xc3);
  329. }
  330. void
  331. l40226c (void)
  332. {
  333. if (EPPMode)
  334. l402200 (4, 7);
  335. else
  336. l402200 (4, 0x47);
  337. }
  338. void
  339. PPWriteByte (int i) // 4022d0
  340. {
  341. if (EPPMode)
  342. {
  343. outpb (EPPDataPort, i);
  344. }
  345. else
  346. SPPWriteByte (i);
  347. }
  348. void
  349. PPWriteWord (int i) // 4022d0
  350. {
  351. if (EPPMode)
  352. {
  353. if (DataSize16)
  354. {
  355. outpw (EPPDataPort, i);
  356. }
  357. else
  358. {
  359. outpb (EPPDataPort, i);
  360. outpb (EPPDataPort, (i >> 8));
  361. }
  362. }
  363. else
  364. {
  365. SPPWriteByte (i);
  366. SPPWriteByte (i >> 8);
  367. }
  368. }
  369. int
  370. PPReadByte (void) // 40234c
  371. {
  372. int v;
  373. if (EPPMode)
  374. v = inpb (EPPDataPort);
  375. else
  376. v = SPPReadByte ();
  377. return v;
  378. }
  379. int
  380. PPReadWord (void) // 402368 // ReadFlash
  381. {
  382. int v = 0;
  383. if (EPPMode)
  384. {
  385. if (DataSize16)
  386. v = inpw (EPPDataPort);
  387. else
  388. {
  389. v = inpb (EPPDataPort);
  390. v += (inpb (EPPDataPort) << 8);
  391. }
  392. }
  393. else
  394. {
  395. v = SPPReadByte (); //402124
  396. v += (SPPReadByte () << 8);
  397. }
  398. return v;
  399. }
  400. void
  401. SetCartAddr (int addr) // 4023cc
  402. {
  403. l402200 (2, addr >> 16);
  404. l402200 (1, addr >> 8);
  405. l402200 (0, addr);
  406. }
  407. void
  408. WriteFlash (int addr, int data) // 402414
  409. {
  410. SetCartAddr (addr);
  411. l4021d0 (3);
  412. PPWriteWord (data);
  413. }
  414. int
  415. ReadFlash (int addr)
  416. {
  417. SetCartAddr (addr);
  418. l4021d0 (3);
  419. outpb (SPPCtrlPort, 0);
  420. return PPReadWord ();
  421. }
  422. void
  423. l402684 (void)
  424. {
  425. #ifndef USE_PPDEV
  426. outpb (SPPStatPort, 1); // clear EPP time flag
  427. #endif
  428. l40226c ();
  429. }
  430. int
  431. LookForLinker (void) // 4026a8
  432. {
  433. l402684 ();
  434. l402200 (2, 0x12);
  435. l402200 (1, 0x34);
  436. l402200 (0, 0x56);
  437. l4021d0 (2);
  438. outpb (SPPCtrlPort, 0);
  439. if (PPReadByte () != 0x12) // 40234c
  440. return 0;
  441. l4021d0 (1);
  442. outpb (SPPCtrlPort, 0);
  443. if (PPReadByte () != 0x34)
  444. return 0;
  445. l4021d0 (0);
  446. outpb (SPPCtrlPort, 0);
  447. if (PPReadByte () != 0x56)
  448. return 0;
  449. outpb (SPPCtrlPort, 4);
  450. return 1;
  451. }
  452. void
  453. LinkerInit (void) // 4027c4
  454. {
  455. int linker_found = 0;
  456. /*
  457. uCON64 comment:
  458. Accessing I/O ports with addresses higher than 0x3ff causes an access
  459. violation on Windows XP (NT/2000) for _Windows_ executables without the use
  460. of an appropriate I/O port driver. UserPort is an example of an
  461. *inappropriate* I/O port driver, because it enables access to I/O ports up
  462. to 0x3ff. For some (ridiculous) reason, DOS executables are allowed to
  463. _access_ at least the ECP register this code uses. That doesn't mean it will
  464. result in the expected behaviour like enabling EPP.
  465. */
  466. if (EPPMode)
  467. {
  468. /*
  469. Writing to the ECP register seems to have no effect on my PC (which
  470. supports ECP, used appropriate BIOS setting). Tested on Windows XP with
  471. Windows executables (Cygwin, VC++ and MinGW) - dbjh
  472. */
  473. #ifndef USE_PPDEV
  474. outpb (ECPRegECR, 4); // set EPP mode for ECP chipsets
  475. #endif
  476. if (LookForLinker ())
  477. {
  478. // Linker found using EPP mode.
  479. linker_found = 1;
  480. puts ("Linker found. EPP found");
  481. if (SPPDataPort == 0x3bc)
  482. return;
  483. outpb (SPPCtrlPort, 4);
  484. }
  485. }
  486. if (!linker_found)
  487. {
  488. // Look for linker in SPP mode.
  489. #ifndef USE_PPDEV
  490. if (EPPMode)
  491. outpb (ECPRegECR, 0); // set SPP mode for ECP chipsets
  492. #endif
  493. EPPMode = 0;
  494. if (LookForLinker ())
  495. puts ("Linker found. EPP not found or not enabled - SPP used");
  496. else
  497. {
  498. fputs ("ERROR: Flash Advance Linker not found or not turned on\n",
  499. stderr);
  500. ProgramExit (1);
  501. }
  502. }
  503. }
  504. int
  505. ReadStatusRegister (int addr) // 402dd8
  506. {
  507. int v;
  508. WriteFlash (addr, INTEL28F_READSR);
  509. outpb (SPPCtrlPort, 0);
  510. v = PPReadWord (); // & 0xff;
  511. v = PPReadWord (); // & 0xff;
  512. return v;
  513. }
  514. // StartOffSet: 1 = 0, 2 = 64k, 3 = 128k, 4 = 192k
  515. // Size: 1 = 32k, 2 = 64k, 3 = 128k, 4 = 256k
  516. void
  517. BackupSRAM (FILE *fp, int StartOS, int Size) // 4046f4
  518. {
  519. int j, k, v;
  520. int m;
  521. int n = 1 << (Size - 1);
  522. int size = n * 32 * 1024, bytesread = 0;
  523. time_t starttime;
  524. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  525. starttime = time (NULL);
  526. for (m = ((StartOS - 1) << 1); m < (((StartOS - 1) << 1) + n); m++)
  527. {
  528. if ((m & 1) == 0)
  529. {
  530. SetVisolyBackupRWMode (m >> 1);
  531. l402234 ();
  532. }
  533. // Backup a 32k byte chunk
  534. for (j = 0; j < 0x80; j++)
  535. {
  536. l402200 (0, 0);
  537. l402200 (1, j + (0x80 * (m & 1)));
  538. l402200 (2, 0);
  539. l4021d0 (3);
  540. outpb (SPPCtrlPort, 0);
  541. for (k = 0; k < 0x100; k++)
  542. {
  543. v = PPReadByte ();
  544. fputc (v, fp);
  545. }
  546. bytesread += 256;
  547. if ((bytesread & 0x1fff) == 0) // call ucon64_gauge() after receiving 8 kB
  548. ucon64_gauge (starttime, bytesread, size);
  549. }
  550. }
  551. }
  552. // StartOffSet: 1 = 0, 2 = 64k, 3 = 128k, 4 = 192k
  553. void
  554. RestoreSRAM (FILE *fp, int StartOS)
  555. {
  556. int i;
  557. int j, k;
  558. int m = ((StartOS - 1) << 1);
  559. int byteswritten = 0;
  560. time_t starttime;
  561. printf ("Send: %d Bytes (%.4f Mb)\n\n", ucon64.file_size,
  562. (float) ucon64.file_size / MBIT);
  563. starttime = time (NULL);
  564. i = fgetc (fp);
  565. while (!feof (fp))
  566. {
  567. if ((m & 1) == 0)
  568. {
  569. SetVisolyBackupRWMode (m >> 1);
  570. l402234 ();
  571. }
  572. // Restore a 32k byte chunk
  573. for (j = 0; j < 0x80; j++)
  574. {
  575. l402200 (0, 0);
  576. l402200 (1, j + (0x80 * (m & 1)));
  577. l402200 (2, 0);
  578. l4021d0 (3);
  579. outpb (SPPCtrlPort, 0);
  580. for (k = 0; k < 0x100; k++)
  581. {
  582. PPWriteByte (i);
  583. i = fgetc (fp);
  584. }
  585. byteswritten += 256;
  586. if ((byteswritten & 0x1fff) == 0) // call ucon64_gauge() after sending 8 kB
  587. ucon64_gauge (starttime, byteswritten, ucon64.file_size);
  588. }
  589. m++;
  590. }
  591. }
  592. void
  593. BackupROM (FILE *fp, int SizekW)
  594. {
  595. u16 valw;
  596. u32 i, j;
  597. int size = SizekW << 1, bytesread = 0;
  598. time_t starttime;
  599. printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
  600. WriteFlash (0, INTEL28F_READARRAY); // Set flash (intel 28F640J3A) Read Mode
  601. starttime = time (NULL);
  602. for (i = 0; i < (u32) (SizekW >> 8); i++)
  603. {
  604. SetCartAddr (i << 8); // Set cart base addr to 0
  605. l4021d0 (3);
  606. outpb (SPPCtrlPort, 0);
  607. for (j = 0; j < 256; j++)
  608. {
  609. valw = (unsigned short) PPReadWord ();
  610. fputc (valw & 0xff, fp);
  611. fputc (valw >> 8, fp);
  612. }
  613. bytesread += 256 << 1; // 256 words
  614. if ((bytesread & 0xffff) == 0) // call ucon64_gauge() after receiving 64 kB
  615. ucon64_gauge (starttime, bytesread, size);
  616. }
  617. }
  618. void
  619. dump (u8 BaseAdr)
  620. {
  621. // unsigned char low, high;
  622. int i;
  623. u8 First = 1;
  624. u16 v;
  625. u8 val1, val2;
  626. u8 Display[17] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  627. WriteFlash (0, INTEL28F_READARRAY); // Set flash (intel 28F640J3A) Read Mode
  628. SetCartAddr (BaseAdr << 7); // Set cart base addr to read
  629. l4021d0 (3);
  630. outpb (SPPCtrlPort, 0);
  631. for (i = 0; i < 128; i++)
  632. {
  633. if (First == 1)
  634. {
  635. if (i * 2 < 256)
  636. fputc ('0', stdout);
  637. if (i * 2 < 16)
  638. fputc ('0', stdout);
  639. printf ("%hx - ", (i * 2));
  640. First = 0;
  641. }
  642. v = (unsigned short) PPReadWord ();
  643. val2 = v >> 8;
  644. val1 = v & 255;
  645. if ((val1 > 31) & (val1 < 127))
  646. Display[(i & 7) * 2] = val1;
  647. else
  648. Display[(i & 7) * 2] = 46;
  649. if (val1 < 16)
  650. fputc ('0', stdout);
  651. printf ("%hx ", val1);
  652. if ((val2 > 31) & (val2 < 127))
  653. Display[(i & 7) * 2 + 1] = val2;
  654. else
  655. Display[(i & 7) * 2 + 1] = 46;
  656. if (val2 < 16)
  657. fputc ('0', stdout);
  658. printf ("%hx ", val2);
  659. if ((i & 7) == 7)
  660. {
  661. First = 1;
  662. printf (" %3s\n", (&Display[0]));
  663. }
  664. }
  665. }
  666. void
  667. CheckForFC (void)
  668. {
  669. LinkerInit ();
  670. SetVisolyFlashRWMode ();
  671. Device = CartTypeDetect ();
  672. VisolyTurbo = 0;
  673. printf ("Device ID = 0x%x: ", Device);
  674. switch (Device)
  675. {
  676. case 0x16:
  677. fputs ("FA 32M (i28F320J3A)", stdout);
  678. break;
  679. case 0x17:
  680. fputs ("FA 64M (i28F640J3A)", stdout);
  681. break;
  682. case 0x18:
  683. fputs ("FA 128M (i28F128J3A)", stdout);
  684. break;
  685. case 0x2e:
  686. fputs ("Standard ROM", stdout);
  687. break;
  688. case 0x96:
  689. fputs ("Turbo FA 64M (2 x i28F320J3A)", stdout);
  690. VisolyTurbo = 1;
  691. break;
  692. case 0x97:
  693. fputs ("Turbo FA 128M (2 x i28F640J3A)", stdout);
  694. VisolyTurbo = 1;
  695. break;
  696. case 0x98:
  697. fputs ("Turbo FA 256M (2 x i28F128J3A", stdout);
  698. VisolyTurbo = 1;
  699. break;
  700. case 0xdc:
  701. fputs ("Hudson", stdout);
  702. break;
  703. case 0xe2:
  704. fputs ("Nintendo Flash Card (LH28F320BJE)", stdout);
  705. break;
  706. default:
  707. fputs ("Unknown", stdout);
  708. break;
  709. }
  710. fputc ('\n', stdout);
  711. }
  712. int
  713. GetFileByte (FILE *fp)
  714. {
  715. static int FilePos = 0;
  716. int i = 0;
  717. if (RepairHeader)
  718. {
  719. // Set file pointer just past header
  720. if (FilePos == 0)
  721. for (i = 0; i < 0xa0; i++)
  722. (void) fgetc (fp);
  723. if (FilePos < 0xa0)
  724. {
  725. if ((HeaderBad) && (FilePos > 3))
  726. i = gba_logodata[FilePos - 4]; // GoodHeader[FilePos];
  727. else
  728. i = FileHeader[FilePos];
  729. }
  730. else if ((FilePos == 0xb2) || (FilePos == 0xbd))
  731. {
  732. if (FilePos == 0xb2)
  733. i = 0x96; // Required
  734. else
  735. i = Complement;
  736. (void) fgetc (fp); // Discard file value
  737. }
  738. else
  739. i = fgetc (fp);
  740. }
  741. else
  742. i = fgetc (fp);
  743. FilePos++;
  744. return i;
  745. }
  746. int
  747. GetFileSize2 (FILE *fp)
  748. /*
  749. The name "GetFileSize" conflicts with a Windows function.
  750. For some odd reason Jeff Frohwein returned the file size minus 1. I (dbjh)
  751. guess that's a bug. I disabled the (terribly inefficient) file size code
  752. because uCON64 already determined the file size at this point.
  753. */
  754. {
  755. int FileSize;
  756. if (RepairHeader)
  757. {
  758. int i;
  759. int j;
  760. FileSize = 0;
  761. while (!feof (fp) && (FileSize < 0xc0))
  762. FileHeader[FileSize++] = fgetc (fp);
  763. if (feof (fp))
  764. {
  765. fputs ("ERROR: File must be 192 bytes or larger\n", stderr);
  766. ProgramExit (1);
  767. }
  768. HeaderBad = 0;
  769. i = 4;
  770. while (i < 0xa0) //9c)
  771. {
  772. if (FileHeader[i] != gba_logodata[i - 4]) // GoodHeader[i]
  773. HeaderBad = 1;
  774. i++;
  775. }
  776. if (HeaderBad)
  777. puts ("NOTE: Fixing logo area");
  778. Complement = 0;
  779. FileHeader[0xb2] = 0x96; // Required
  780. for (j = 0xa0; j < 0xbd; j++)
  781. Complement += FileHeader[j];
  782. Complement = (0 - (0x19 + Complement)) & 0xff;
  783. //printf("[Complement = 0x%x]", (int)Complement);
  784. //printf("[HeaderComp = 0x%x]", (int)FileHeader[0xbd]);
  785. if (FileHeader[0xbd] != Complement)
  786. puts ("NOTE: Fixing complement check");
  787. rewind (fp);
  788. }
  789. else
  790. rewind (fp);
  791. return ucon64.file_size;
  792. }
  793. // Program older (non-Turbo) Visoly flash card
  794. // (Single flash chip)
  795. void
  796. ProgramNonTurboIntelFlash (FILE *fp)
  797. {
  798. int i, j, k;
  799. int addr = 0;
  800. int FileSize;
  801. int Ready = 0;
  802. int Timeout;
  803. time_t starttime;
  804. // Get file size
  805. FileSize = GetFileSize2 (fp);
  806. puts ("Erasing Visoly non-turbo flash card...");
  807. // Erase as many 128k blocks as are required
  808. Ready = EraseNonTurboFABlocks (0, ((FileSize - 1) >> 17) + 1);
  809. clear_line (); // remove "erase gauge"
  810. if (Ready)
  811. {
  812. printf ("Send: %d Bytes (%.4f Mb)\n\n", FileSize, (float) FileSize / MBIT);
  813. //403018
  814. starttime = time (NULL);
  815. j = GetFileByte (fp);
  816. while (!feof (fp))
  817. {
  818. Ready = 0;
  819. Timeout = 0x4000;
  820. while ((Ready == 0) && (Timeout != 0))
  821. {
  822. WriteFlash (addr, INTEL28F_WRTOBUF);
  823. outpb (SPPCtrlPort, 0);
  824. Ready = PPReadWord () & 0x80;
  825. Timeout--;
  826. }
  827. if (Ready)
  828. {
  829. WriteFlash (addr, 15); // Write 15+1 16bit words
  830. SetCartAddr (addr); // Set cart base addr to 0
  831. l4021d0 (3);
  832. for (i = 0; i < 16; i++)
  833. {
  834. k = j;
  835. if (j != EOF)
  836. j = GetFileByte (fp);
  837. k += (j << 8);
  838. PPWriteWord (k);
  839. if (j != EOF)
  840. j = GetFileByte (fp);
  841. }
  842. addr += 16;
  843. if ((addr & 0x3fff) == 0) // call ucon64_gauge() after sending 32 kB
  844. ucon64_gauge (starttime, addr << 1, FileSize);
  845. PPWriteWord (INTEL28F_CONFIRM); // Comfirm block write
  846. Ready = 0;
  847. Timeout = 0x4000;
  848. while ((Ready == 0) && (Timeout != 0))
  849. {
  850. WriteFlash (0, INTEL28F_READSR);
  851. outpb (SPPCtrlPort, 0);
  852. i = PPReadWord () & 0xff;
  853. Ready = i & 0x80;
  854. Timeout--;
  855. }
  856. if (Ready)
  857. {
  858. if (i & 0x7f)
  859. {
  860. // One or more status register error bits are set
  861. outpb (SPPCtrlPort, 1);
  862. WriteFlash (0, INTEL28F_CLEARSR);
  863. Ready = 0;
  864. break;
  865. }
  866. }
  867. else
  868. {
  869. outpb (SPPCtrlPort, 1);
  870. WriteFlash (0, INTEL28F_CLEARSR);
  871. break;
  872. }
  873. }
  874. else
  875. break;
  876. }
  877. clear_line (); // remove last gauge
  878. ucon64_gauge (starttime, addr << 1, FileSize); // make gauge reach 100% when size % 32 k != 0
  879. WriteFlash (0, INTEL28F_READARRAY);
  880. outpb (SPPCtrlPort, 0);
  881. if (Ready)
  882. ;
  883. else
  884. fputs ("\nERROR: Flash card write failed\n", stderr);
  885. }
  886. else
  887. fputs ("\nERROR: Flash card erase failed\n", stderr);
  888. }
  889. // Program newer (Turbo) Visoly flash card
  890. // (Dual chip / Interleave)
  891. void
  892. ProgramTurboIntelFlash (FILE *fp)
  893. {
  894. int i, j = 0;
  895. int k; //z;
  896. int addr = 0;
  897. int done1, done2;
  898. int FileSize;
  899. int Timeout;
  900. int Ready; //= 0;
  901. time_t starttime;
  902. // Get file size
  903. FileSize = GetFileSize2 (fp);
  904. puts ("Erasing Visoly turbo flash card...");
  905. // Erase as many 256k blocks as are required
  906. Ready = EraseTurboFABlocks (0, ((FileSize - 1) >> 18) + 1);
  907. clear_line (); // remove "erase gauge"
  908. if (Ready)
  909. {
  910. printf ("Send: %d Bytes (%.4f Mb)\n\n", FileSize, (float) FileSize / MBIT);
  911. //403018
  912. starttime = time (NULL);
  913. j = GetFileByte (fp);
  914. while (!feof (fp))
  915. {
  916. done1 = 0;
  917. done2 = 0;
  918. Ready = 0;
  919. Timeout = 0x4000;
  920. while ((!Ready) && (Timeout != 0))
  921. {
  922. if (done1 == 0)
  923. WriteFlash (addr + 0, INTEL28F_WRTOBUF);
  924. if (done2 == 0)
  925. WriteFlash (addr + 1, INTEL28F_WRTOBUF);
  926. SetCartAddr (addr); // Set cart base addr
  927. l4021d0 (3);
  928. outpb (SPPCtrlPort, 0);
  929. done1 = PPReadWord () & 0x80;
  930. done2 = PPReadWord () & 0x80;
  931. Ready = ((done1 + done2) == 0x100);
  932. Timeout--;
  933. }
  934. if (Ready)
  935. {
  936. WriteFlash (addr, 15); // Write 15+1 16bit words
  937. PPWriteWord (15);
  938. SetCartAddr (addr); // Set cart base addr
  939. l4021d0 (3);
  940. for (i = 0; i < 32; i++)
  941. {
  942. k = j;
  943. if (j != EOF)
  944. j = GetFileByte (fp);
  945. k += (j << 8);
  946. PPWriteWord (k);
  947. if (j != EOF)
  948. j = GetFileByte (fp);
  949. }
  950. addr += 32;
  951. if ((addr & 0x3fff) == 0) // call ucon64_gauge() after sending 32 kB
  952. ucon64_gauge (starttime, addr << 1, FileSize);
  953. PPWriteWord (INTEL28F_CONFIRM); // Comfirm block write
  954. PPWriteWord (INTEL28F_CONFIRM); // Comfirm block write
  955. Ready = 0;
  956. Timeout = 0x4000;
  957. k = 0;
  958. while (((k & 0x8080) != 0x8080) && (Timeout != 0))
  959. {
  960. outpb (SPPCtrlPort, 0);
  961. k = PPReadWord () & 0xff;
  962. k += ((PPReadWord () & 0xff) << 8);
  963. Ready = (k == 0x8080);
  964. Timeout--;
  965. }
  966. if (!Ready)
  967. break;
  968. }
  969. else
  970. break;
  971. }
  972. clear_line (); // remove last gauge
  973. ucon64_gauge (starttime, addr << 1, FileSize); // make gauge reach 100% when size % 32 k != 0
  974. WriteFlash (0, INTEL28F_READARRAY);
  975. outpb (SPPCtrlPort, 0);
  976. WriteFlash (1, INTEL28F_READARRAY);
  977. outpb (SPPCtrlPort, 0);
  978. if (Ready)
  979. ;
  980. else
  981. {
  982. WriteFlash (0, INTEL28F_CLEARSR);
  983. PPWriteWord (INTEL28F_CLEARSR);
  984. fputs ("\nERROR: Flash card write failed\n", stderr);
  985. }
  986. }
  987. else
  988. fputs ("\nERROR: Flash card erase failed\n", stderr);
  989. }
  990. // Program official Nintendo flash card
  991. void
  992. ProgramSharpFlash (FILE *fp)
  993. {
  994. int i, j;
  995. int k = 0;
  996. int addr = 0;
  997. int FileSize;
  998. int Ready;
  999. time_t starttime;
  1000. // Get file size
  1001. FileSize = GetFileSize2 (fp);
  1002. puts ("Erasing Nintendo flash card...");
  1003. // Erase as many 64k blocks as are required
  1004. Ready = EraseNintendoFlashBlocks (0, ((FileSize - 1) >> 16) + 1);
  1005. clear_line (); // remove "erase gauge"
  1006. if (Ready)
  1007. {
  1008. printf ("Send: %d Bytes (%.4f Mb)\n\n", FileSize, (float) FileSize / MBIT);
  1009. starttime = time (NULL);
  1010. j = GetFileByte (fp);
  1011. while (!feof (fp))
  1012. {
  1013. if (j != EOF)
  1014. k = GetFileByte (fp);
  1015. i = ((k & 0xff) << 8) + (j & 0xff);
  1016. while ((ReadStatusRegister (0) & 0x80) == 0)
  1017. ;
  1018. WriteFlash (addr, SHARP28F_WORDWRITE);
  1019. WriteFlash (addr, i);
  1020. addr += 1;
  1021. j = GetFileByte (fp);
  1022. if ((addr & 0x3fff) == 0) // call ucon64_gauge() after sending 32 kB
  1023. ucon64_gauge (starttime, addr << 1, FileSize);
  1024. }
  1025. clear_line (); // remove last gauge
  1026. ucon64_gauge (starttime, addr << 1, FileSize); // make gauge reach 100% when size % 32 k != 0
  1027. WriteFlash (0, INTEL28F_READARRAY);
  1028. outpb (SPPCtrlPort, 0);
  1029. }
  1030. else
  1031. fputs ("\nERROR: Flash card erase failed\n", stderr);
  1032. }
  1033. #if 0 // not used
  1034. void
  1035. VerifyFlash (FILE *fp)
  1036. {
  1037. int addr = 0;
  1038. int CompareFail = 0;
  1039. int k = 0;
  1040. int i, j, m, n;
  1041. WriteFlash (0, INTEL28F_READARRAY); // Set flash (intel 28F640J3A) Read Mode
  1042. j = 0;
  1043. while (!feof (fp))
  1044. {
  1045. j = fgetc (fp);
  1046. if (j != EOF)
  1047. {
  1048. if ((addr & 0x1ff) == 0)
  1049. {
  1050. SetCartAddr (addr >> 1); // Set cart base addr to read
  1051. l4021d0 (3);
  1052. outpb (SPPCtrlPort, 0);
  1053. }
  1054. k = fgetc (fp);
  1055. i = PPReadWord ();
  1056. m = i & 0xff;
  1057. n = i >> 8;
  1058. if (m != j)
  1059. {
  1060. printf ("Address %x - Cartridge %x: File %hx\n", addr, m, j);
  1061. CompareFail = 1;
  1062. }
  1063. if ((n != k) && (k != EOF))
  1064. {
  1065. printf ("Address %x - Cartridge %x: File %hx\n", addr + 1, n,
  1066. k);
  1067. CompareFail = 1;
  1068. }
  1069. addr += 2;
  1070. }
  1071. }
  1072. // Correct verify length if at EOF
  1073. if (k == EOF)
  1074. addr--;
  1075. if (CompareFail == 0)
  1076. printf ("%d bytes compared OK\n", addr);
  1077. }
  1078. #endif
  1079. void
  1080. SpaceCheck (char c)
  1081. {
  1082. if (c != 0)
  1083. {
  1084. fputs ("ERROR: Space required between option and parameter\n", stderr);
  1085. ProgramExit (1);
  1086. }
  1087. }
  1088. int
  1089. fal_main (int argc, char **argv)
  1090. {
  1091. int arg, i;
  1092. u8 Base = 0;
  1093. FILE *fp;
  1094. char fname[128];//, fname2[128];
  1095. int OptB = 0;
  1096. int OptD = 0;
  1097. int OptP = 0;
  1098. int OptR = 0;
  1099. int OptS = 0;
  1100. // int OptV = 0;
  1101. // int OptZ = 0;
  1102. int port = 0x378;
  1103. int ChipSize = 32;
  1104. int BackupMemOffset = 0;
  1105. int BackupMemSize = 0;
  1106. if (argc < 2)
  1107. {
  1108. // usage (argv[0]);
  1109. ProgramExit (1);
  1110. }
  1111. debug = 0;
  1112. verbose = 1;
  1113. EPPMode = 0; // uCON64 comment: use the most compatible setting as default
  1114. DataSize16 = 0;
  1115. WaitDelay = 0;
  1116. VisolyTurbo = 0;
  1117. RepairHeader = 1;
  1118. for (arg = 1; arg < argc; arg++)
  1119. {
  1120. if (argv[arg][0] != '-')
  1121. {
  1122. // usage (argv[0]);
  1123. ProgramExit (1);
  1124. }
  1125. switch (argv[arg][1])
  1126. {
  1127. case 'b':
  1128. SpaceCheck (argv[arg][2]);
  1129. BackupMemOffset = *(char *) argv[++arg] - 0x30;
  1130. SpaceCheck (argv[arg][1]);
  1131. BackupMemSize = *(char *) argv[++arg] - 0x30;
  1132. if ((BackupMemSize < 1) || (BackupMemSize > 4) ||
  1133. (BackupMemOffset < 1) || (BackupMemOffset > 4))
  1134. {
  1135. fputs ("ERROR: -b parameter values must be between 1-4\n", stderr);
  1136. ProgramExit (1);
  1137. }
  1138. SpaceCheck (argv[arg][1]);
  1139. strcpy (fname, argv[++arg]);
  1140. OptB = 1;
  1141. break;
  1142. case '2':
  1143. // 16-bit EPP support enable (doesn't work with
  1144. // "Turbo FA 128M (2 x i28F640J3A)" - dbjh)
  1145. DataSize16 = 1;
  1146. break;
  1147. case 'c':
  1148. // Set cart size
  1149. SpaceCheck (argv[arg][2]);
  1150. ChipSize = (u16) (atoi (argv[++arg]));
  1151. if ((ChipSize != 8) &&
  1152. (ChipSize != 16) &&
  1153. (ChipSize != 32) &&
  1154. (ChipSize != 64) && (ChipSize != 128) && (ChipSize != 256))
  1155. {
  1156. fputs ("ERROR: Chip size must be 8,16,32,64,128 or 256\n", stderr);
  1157. ProgramExit (1);
  1158. }
  1159. break;
  1160. case 'd':
  1161. // Dump 256 bytes to screen
  1162. SpaceCheck (argv[arg][2]);
  1163. if (argv[++arg] != NULL)
  1164. Base = (u8) (atoi (argv[arg]));
  1165. printf ("Base address: %hx\n", Base * 256);
  1166. OptD = 1;
  1167. break;
  1168. case 's':
  1169. // Backup flash cart
  1170. SpaceCheck (argv[arg][2]);
  1171. strcpy (fname, argv[++arg]);
  1172. OptS = 1;
  1173. break;
  1174. case 'p':
  1175. // Program flash cart
  1176. SpaceCheck (argv[arg][2]);
  1177. strcpy (fname, argv[++arg]);
  1178. OptP = 1;
  1179. break;
  1180. case 'r':
  1181. SpaceCheck (argv[arg][2]);
  1182. BackupMemOffset = *(char *) argv[++arg] - 0x30;
  1183. if ((BackupMemOffset < 1) || (BackupMemOffset > 4))
  1184. {
  1185. fputs ("ERROR: -r parameter value must be between 1-4\n", stderr);
  1186. ProgramExit (1);
  1187. }
  1188. SpaceCheck (argv[arg][1]);
  1189. strcpy (fname, argv[++arg]);
  1190. OptR = 1;
  1191. break;
  1192. #if 0
  1193. case 'v':
  1194. // Verify flash cart
  1195. SpaceCheck (argv[arg][2]);
  1196. strcpy (fname2, argv[++arg]);
  1197. OptV = 1;
  1198. break;
  1199. #endif
  1200. case 'l':
  1201. SpaceCheck (argv[arg][2]);
  1202. i = atoi (argv[++arg]);
  1203. /*
  1204. uCON64 comment: we want to support non-standard parallel port
  1205. addresses too. So, instead of passing a number from 1 to 4, we pass
  1206. the address itself
  1207. */
  1208. port = i;
  1209. break;
  1210. case 'm':
  1211. // uCON64 comment: See comment in LinkerInit(). Note that we reverse
  1212. // the meaning compared to the original code.
  1213. EPPMode = 1; // Set EPP mode
  1214. break;
  1215. case 'n':
  1216. // Don't repair header
  1217. RepairHeader = 0;
  1218. break;
  1219. case 'w':
  1220. SpaceCheck (argv[arg][2]);
  1221. WaitDelay = atoi (argv[++arg]);
  1222. break;
  1223. #if 0
  1224. case 'z':
  1225. OptZ = 1;
  1226. break;
  1227. #endif
  1228. default:
  1229. // usage (argv[0]);
  1230. ProgramExit (1);
  1231. }
  1232. }
  1233. InitPort (port);
  1234. CheckForFC ();
  1235. if (OptB)
  1236. {
  1237. //DumpSRAM ();
  1238. if ((fp = fopen (fname, "wb")) == NULL)
  1239. {
  1240. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], fname);
  1241. ProgramExit (1);
  1242. }
  1243. BackupSRAM (fp, BackupMemOffset, BackupMemSize);
  1244. fclose (fp);
  1245. }
  1246. if (OptD)
  1247. dump (Base);
  1248. if ((OptP) && ((Device == 0) || (Device == 0x2e) || (Device == 0xff)))
  1249. {
  1250. fputs ("ERROR: Device type not recognized as programmable\n", stderr);
  1251. ProgramExit (1);
  1252. }
  1253. if (OptR)
  1254. {
  1255. if ((fp = fopen (fname, "rb")) == NULL)
  1256. {
  1257. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname);
  1258. ProgramExit (1);
  1259. }
  1260. RestoreSRAM (fp, BackupMemOffset);
  1261. fclose (fp);
  1262. }
  1263. if (OptP)
  1264. {
  1265. if ((fp = fopen (fname, "rb")) == NULL)
  1266. {
  1267. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname);
  1268. ProgramExit (1);
  1269. }
  1270. if (Device == 0xe2)
  1271. ProgramSharpFlash (fp);
  1272. else
  1273. {
  1274. if (VisolyTurbo)
  1275. ProgramTurboIntelFlash (fp);
  1276. else
  1277. ProgramNonTurboIntelFlash (fp);
  1278. }
  1279. fclose (fp);
  1280. }
  1281. if (OptS)
  1282. {
  1283. if ((fp = fopen (fname, "wb")) == NULL)
  1284. {
  1285. fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], fname);
  1286. ProgramExit (1);
  1287. }
  1288. BackupROM (fp, ChipSize << 16);
  1289. fclose (fp);
  1290. }
  1291. #if 0
  1292. if (OptV)
  1293. {
  1294. if ((fp = fopen (fname2, "rb")) == NULL)
  1295. {
  1296. fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname2);
  1297. ProgramExit (1);
  1298. }
  1299. VerifyFlash (fp);
  1300. fclose (fp);
  1301. }
  1302. #endif
  1303. // ProgramExit (0);
  1304. return 0;
  1305. }
  1306. /*
  1307. It will save you some work if you don't fully integrate the code above with
  1308. uCON64's code, because it is a project separate from the uCON64 project.
  1309. */
  1310. int fal_argc = 0;
  1311. char *fal_argv[128];
  1312. void
  1313. fal_args (unsigned int parport)
  1314. {
  1315. char parport_str[80];
  1316. parport_print_info ();
  1317. fal_argv[fal_argc++] = "fl";
  1318. fal_argv[fal_argc++] = "-l";
  1319. sprintf (parport_str, "%d", parport); // don't use %x, as Jeff Frohwein uses atoi()
  1320. fal_argv[fal_argc++] = parport_str;
  1321. if (ucon64.parport_mode == UCON64_EPP)
  1322. fal_argv[fal_argc++] = "-m";
  1323. }
  1324. int
  1325. fal_read_rom (const char *filename, unsigned int parport, int size)
  1326. {
  1327. char size_str[80];
  1328. fal_args (parport);
  1329. fal_argv[fal_argc++] = "-c";
  1330. if (size != 8 && size != 16 && size != 32 && size != 64 && size != 128 &&
  1331. size != 256)
  1332. {
  1333. fputs ("ERROR: Invalid argument for -xfalc=n\n"
  1334. " n can be 8, 16, 32, 64, 128 or 256\n", stderr);
  1335. exit (1);
  1336. }
  1337. sprintf (size_str, "%d", size);
  1338. fal_argv[fal_argc++] = size_str;
  1339. fal_argv[fal_argc++] = "-s";
  1340. fal_argv[fal_argc++] = (char *) filename; // this is safe (FAL code
  1341. // doesn't modify argv)
  1342. if (!fal_main (fal_argc, fal_argv))
  1343. return 0;
  1344. return -1;
  1345. }
  1346. int
  1347. fal_write_rom (const char *filename, unsigned int parport)
  1348. {
  1349. fal_args (parport);
  1350. fal_argv[fal_argc++] = "-p";
  1351. fal_argv[fal_argc++] = (char *) filename;
  1352. if (!fal_main (fal_argc, fal_argv))
  1353. return 0;
  1354. return -1;
  1355. }
  1356. int
  1357. fal_read_sram (const char *filename, unsigned int parport, int bank)
  1358. {
  1359. char bank_str[2];
  1360. fal_args (parport);
  1361. fal_argv[fal_argc++] = "-b";
  1362. if (bank == UCON64_UNKNOWN)
  1363. {
  1364. fal_argv[fal_argc++] = "1";
  1365. fal_argv[fal_argc++] = "4"; // 256 kB
  1366. }
  1367. else
  1368. {
  1369. if (bank < 1 || bank > 4)
  1370. {
  1371. fputs ("ERROR: Bank must be 1, 2, 3 or 4\n", stderr);
  1372. exit (1);
  1373. }
  1374. bank_str[0] = (char) ('0' + bank);
  1375. bank_str[1] = 0; // terminate string
  1376. fal_argv[fal_argc++] = bank_str;
  1377. fal_argv[fal_argc++] = "2"; // 64 kB
  1378. }
  1379. fal_argv[fal_argc++] = (char *) filename;
  1380. if (!fal_main (fal_argc, fal_argv))
  1381. return 0;
  1382. return -1;
  1383. }
  1384. int
  1385. fal_write_sram (const char *filename, unsigned int parport, int bank)
  1386. {
  1387. char bank_str[2];
  1388. fal_args (parport);
  1389. fal_argv[fal_argc++] = "-r";
  1390. if (bank == UCON64_UNKNOWN)
  1391. fal_argv[fal_argc++] = "1";
  1392. else
  1393. {
  1394. if (bank < 1 || bank > 4)
  1395. {
  1396. fputs ("ERROR: Bank must be 1, 2, 3 or 4\n", stderr);
  1397. exit (1);
  1398. }
  1399. bank_str[0] = (char) ('0' + bank);
  1400. bank_str[1] = 0; // terminate string
  1401. fal_argv[fal_argc++] = bank_str;
  1402. }
  1403. fal_argv[fal_argc++] = (char *) filename;
  1404. if (!fal_main (fal_argc, fal_argv))
  1405. return 0;
  1406. return -1;
  1407. }
  1408. #endif // USE_PARALLEL