fal.c 40 KB

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