123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674 |
- /*
- fal.c - Flash Linker Advance support for uCON64
- Copyright (c) 2001 Jeff Frohwein
- Copyright (c) 2001 NoisyB
- Copyright (c) 2001 - 2004 dbjh
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <stdlib.h>
- #include <string.h>
- #include "misc/archive.h"
- #include "misc/parallel.h"
- #include "misc/term.h"
- #include "ucon64_misc.h"
- #include "console/gba.h"
- #include "backup/fal.h"
- #ifdef USE_PARALLEL
- static st_ucon64_obj_t fal_obj[] =
- {
- {UCON64_GBA, WF_DEFAULT | WF_STOP | WF_NO_ROM},
- {UCON64_GBA, WF_DEFAULT | WF_STOP},
- {UCON64_GBA, WF_STOP | WF_NO_ROM},
- {UCON64_GBA, WF_SWITCH}
- };
- #endif
- const st_getopt2_t fal_usage[] =
- {
- {
- NULL, 0, 0, 0,
- NULL, "Flash Advance Linker"/*"2001 Visoly http://www.visoly.com"*/,
- NULL
- },
- #ifdef USE_PARALLEL
- {
- "xfal", 0, 0, UCON64_XFAL,
- NULL, "send/receive ROM to/from Flash Advance Linker; " OPTION_LONG_S "port=PORT\n"
- "receives automatically (32 Mbits) when ROM does not exist",
- &fal_obj[0]
- },
- {
- "xfalmulti", 1, 0, UCON64_XFALMULTI, // send only
- "SIZE", "send multiple ROMs to Flash Advance Linker (makes temporary\n"
- "multi-game file truncated to SIZE Mbit); specify a loader in\n"
- "the configuration file; " OPTION_LONG_S "port=PORT",
- &fal_obj[1]
- },
- {
- "xfalc", 1, 0, UCON64_XFALC,
- "N", "receive N Mbits of ROM from Flash Advance Linker; " OPTION_LONG_S "port=PORT\n"
- "N can be 8, 16, 32, 64, 128 or 256",
- &fal_obj[2]
- },
- {
- "xfals", 0, 0, UCON64_XFALS,
- NULL, "send/receive SRAM to/from Flash Advance Linker; " OPTION_LONG_S "port=PORT\n"
- "receives automatically when SRAM does not exist",
- &fal_obj[2]
- },
- {
- "xfalb", 1, 0, UCON64_XFALB,
- "BANK", "send/receive SRAM to/from Flash Advance Linker BANK\n"
- "BANK can be 1, 2, 3 or 4; " OPTION_LONG_S "port=PORT\n"
- "receives automatically when SRAM does not exist",
- &fal_obj[2]
- },
- {
- "xfalm", 0, 0, UCON64_XFALM,
- NULL, "try to enable EPP mode, default is SPP mode",
- &fal_obj[3]
- },
- #endif // USE_PARALLEL
- {NULL, 0, 0, 0, NULL, NULL, NULL}
- };
- #ifdef USE_PARALLEL
- /********************************************************/
- /* Flash Linker Advance */
- /* by Jeff Frohwein, 2001-Jun-28 */
- /* Compiled with DJGPP & linux */
- /********************************************************/
- // V1.0 - 01/06/28 - Original release
- // V1.1 - 01/06/29 - Add -w option to slow down I/O transfer for some.
- // V1.11 - 01/06/30 - Set ECP chipsets to proper parallel port mode.
- // V1.2 - 01/07/23 - Fixed programming bug for Visoly carts.
- // - Only the first block was getting erased.
- // - -v option now appears on help (-h) menu.
- // - -v & -s options now work properly after fixing a bug.
- // V1.3 - 01/07/24 - Added support for Visoly turbo carts.
- // V1.4 - 01/07/27 - Added support for longer filenames.
- // - Fixed bug where files the size of the cart overwrite
- // the first 16 half-words of the cart. Thnx goes to
- // Richard W for the code fix. Thanks Richard!
- // Fixed random lockup bug when programming Turbo carts.
- // Added -n option. Header is now repaired by default.
- // V1.5 - 01/09/25 - Added error retries/checking for older Visoly carts.
- // - Odd length files no longer give a verify error on last byte+1 location.
- // V1.6 - 01/11/11 - Made IRQ 7 instead of 5 and DMA 3 instead of 1 default
- // - linux values. (Thanks to Massimiliano Marsiglietti.)
- // - Added -D & -I to allow linux to change IRQ & DMA defaults.
- // - Added LPT3 support.
- // - Added error checking for space between switch & parameters.
- // - Added -2 options for faster operation for some EPP ports.
- // V1.7 - 01/11/13 - Added -b option to backup game save SRAM or game save Flash.
- // - Added -r option to restore game save SRAM. (No flash support.)
- // V1.71 - 01/11/23 - Fixed bug introduced in v1.7 where -d option printed out twice.
- // V1.72 - 01/12/12 - Force 0x96 at location 0xb2 in header since it's required.
- // To compile source on linux:
- // cc -o fl fl.c -O2
- // You must have root access to run this under linux.
- //
- // NOTE: This file is filled with cr+lf line terminators. This may
- // lead to unhelpful and weird error messages with gcc for linux.
- // Strip out the cr characters to prevent this problem. The following
- // unix command line will work for that:
- // tr -d \\r < dosfile > unixfile
- // On some unix distributions you can also use the following command:
- // dos2unix
- // (Thanks to Massimiliano Marsiglietti for locating this problem.)
- // RAM Detect notes for dev. (Just ignore!)
- //-----------------------------------------
- // To detect backup type.
- // 1. First check for eeprom.
- // 2. Read byte from 0xe000000.
- // 3. Write new byte to 0xe000000.
- // 4. If diff, write back data & exit with SRAM detect flag.
- // 5. If no diff get device Manuf ID for flash.
- // 6. If no Manuf ID detected then report no cart backup available.
- #define outpb(p, v) outportb ((unsigned short) (p), (unsigned char) (v)); iodelay ()
- #define inpb(p) inportb ((unsigned short) (p))
- #define outpw(p, v) outportw ((unsigned short) (p), (unsigned char) (v)); iodelay ()
- #define inpw(p) inportw ((unsigned short) (p))
- //#define HEADER_LENGTH 0xc0
- //#define OUTBUFLEN 256 // Must be a multiple of 2! (ex:64,128,256...)
- #define INTEL28F_BLOCKERASE 0x20
- #define INTEL28F_CLEARSR 0x50
- #define INTEL28F_CONFIRM 0xD0
- #define INTEL28F_QUIRY 0x98
- #define INTEL28F_READARRAY 0xff
- #define INTEL28F_READSR 0x70
- #define INTEL28F_RIC 0x90
- #define INTEL28F_WRTOBUF 0xe8
- #define SHARP28F_BLOCKERASE 0x20
- #define SHARP28F_CONFIRM 0xD0
- #define SHARP28F_READARRAY 0xff
- #define SHARP28F_WORDWRITE 0x10
- #define u8 unsigned char
- #define u16 unsigned short int
- #define u32 unsigned int
- #define u64 unsigned long long int
- // u64 is needed to compile cartlib.c without warnings on Linux/x86_64
- #define CONST_U8 const unsigned char
- // ***Global Variables ***
- //int WaitDelay,WaitNCDelay;
- unsigned SPPDataPort;
- unsigned SPPStatPort;
- unsigned SPPCtrlPort;
- unsigned EPPAddrPort;
- unsigned EPPDataPort;
- unsigned ECPRegECR;
- // prototypes
- void WriteFlash (int addr, int data);
- int ReadFlash (int addr);
- void iodelay (void);
- int PPReadWord (void);
- void PPWriteWord (int i);
- void SetCartAddr (int addr);
- void l4021d0 (int i);
- void l40226c (void);
- #define FLINKER 1
- #include "cartlib.c"
- static int debug, verbose, DataSize16, Device, EPPMode, RepairHeader,
- VisolyTurbo, WaitDelay, FileHeader[0xc0], HeaderBad, Complement = 0;
- void
- iodelay (void)
- {
- volatile int i;
- for (i = 0; i < WaitDelay; i++)
- {
- i++;
- i--;
- }
- }
- void
- ProgramExit (int code)
- {
- exit (code);
- }
- #if 0
- void
- usage (char *name)
- {
- char _small[255];
- char smaller[255];
- int i = 0;
- strcpy (_small, name);
- #if 0
- if (strchr (name, '.') != NULL)
- _small[strlen (_small) - 4] = 0; /* remove trailing file type */
- #endif
- while ((_small[strlen (_small) - i] != 0x2f) && /* loop until we find a / */
- ((strlen (_small) - i) > 0))
- i++;
- if ((strlen (_small) - i) == 0)
- i++;
- strcpy (smaller, (char *) (&_small[strlen (_small) - i + 1]));
- fprintf (stderr, "GBA FLinker v1.72 by Jeff F.\n");
- fprintf (stderr, "Usage: %s [options]\n", smaller);
- fprintf (stderr,
- "\t-2 Use 16bit EPP data path for faster operation (default=8bit)\n");
- fprintf (stderr,
- "\t-b o s file Backup game save SRAM or Flash to file\n");
- fprintf (stderr, "\t (o = Bank Number [1-4])\n");
- fprintf (stderr, "\t (s=1 - Backup 32K bytes to file.)\n");
- fprintf (stderr, "\t (s=2 - Backup 64K bytes to file.)\n");
- fprintf (stderr, "\t (s=3 - Backup 128K bytes to file.)\n");
- fprintf (stderr, "\t (s=4 - Backup 256K bytes to file.)\n");
- fprintf (stderr,
- "\t-c n Specify chip size in mbits (8,16,32,64,128,256) (default=32)\n");
- fprintf (stderr,
- "\t-d n Dump 256 bytes of ROM to screen (default: n=0)\n");
- fprintf (stderr, "\t-h This help screen\n");
- fprintf (stderr,
- "\t-l n Specify the parallel port to use (default is 1 = LPT1)\n");
- // fprintf (stderr, "\t-m\tSet Standard Parallel Port (SPP) mode (default = EPP)\n");
- fprintf (stderr,
- "\t-n Do not repair incorrect header (default = repair header)\n");
- fprintf (stderr, "\t-p file Program flash cart with file\n");
- fprintf (stderr,
- "\t-r o file Restore game save SRAM from file (No save flash support)\n");
- fprintf (stderr, "\t (o = Bank Number [1-4])\n");
- fprintf (stderr,
- "\t-s file Save the cart into a file (Use -c to specify size)\n");
- fprintf (stderr, "\t-v file Verify flash cart with file\n");
- fprintf (stderr, "\t-w n Add delay to make transfer more reliable\n");
- }
- #endif
- void
- InitPort (int port)
- {
- // uCON64 comment: see the comment in fal_main() where port is initialised
- SPPDataPort = port;
- SPPStatPort = SPPDataPort + 1;
- SPPCtrlPort = SPPDataPort + 2;
- EPPAddrPort = SPPDataPort + 3;
- EPPDataPort = SPPDataPort + 4;
- ECPRegECR = SPPDataPort + 0x402;
- }
- void
- l4020a4 (int reg)
- {
- outpb (SPPCtrlPort, 1);
- outpb (SPPDataPort, reg);
- outpb (SPPCtrlPort, 9);
- outpb (SPPCtrlPort, 1);
- }
- void
- SPPWriteByte (int i) // l4020dc
- {
- outpb (SPPDataPort, i);
- outpb (SPPCtrlPort, 3);
- outpb (SPPCtrlPort, 1);
- }
- void
- l402108 (int reg, int adr)
- {
- l4020a4 (reg);
- SPPWriteByte (adr);
- }
- int
- SPPReadByte (void) // 402124
- {
- int v;
- outpb (SPPCtrlPort, 0);
- outpb (SPPCtrlPort, 2);
- v = ((inpb (SPPStatPort)) >> 3) & 0xf;
- outpb (SPPCtrlPort, 6);
- v += (((inpb (SPPStatPort)) << 1) & 0xf0);
- outpb (SPPCtrlPort, 0);
- return v;
- }
- void
- l402188 (int reg)
- {
- outpb (SPPCtrlPort, 1);
- outpb (EPPAddrPort, reg);
- }
- void
- l4021a8 (int reg, int adr)
- {
- l402188 (reg);
- outpb (SPPCtrlPort, 1);
- outpb (EPPDataPort, adr);
- }
- void
- l4021d0 (int i)
- {
- outpb (SPPCtrlPort, 1);
- if (EPPMode)
- l402188 (i);
- else
- l4020a4 (i);
- }
- void
- l402200 (int reg, int adr)
- {
- if (EPPMode)
- l4021a8 (reg, adr);
- else
- l402108 (reg, adr);
- }
- void
- l402234 (void)
- {
- if (EPPMode)
- l402200 (4, 0x83);
- else
- l402200 (4, 0xc3);
- }
- void
- l40226c (void)
- {
- if (EPPMode)
- l402200 (4, 7);
- else
- l402200 (4, 0x47);
- }
- void
- PPWriteByte (int i) // 4022d0
- {
- if (EPPMode)
- {
- outpb (EPPDataPort, i);
- }
- else
- SPPWriteByte (i);
- }
- void
- PPWriteWord (int i) // 4022d0
- {
- if (EPPMode)
- {
- if (DataSize16)
- {
- outpw (EPPDataPort, i);
- }
- else
- {
- outpb (EPPDataPort, i);
- outpb (EPPDataPort, (i >> 8));
- }
- }
- else
- {
- SPPWriteByte (i);
- SPPWriteByte (i >> 8);
- }
- }
- int
- PPReadByte (void) // 40234c
- {
- int v;
- if (EPPMode)
- v = inpb (EPPDataPort);
- else
- v = SPPReadByte ();
- return v;
- }
- int
- PPReadWord (void) // 402368 // ReadFlash
- {
- int v = 0;
- if (EPPMode)
- {
- if (DataSize16)
- v = inpw (EPPDataPort);
- else
- {
- v = inpb (EPPDataPort);
- v += (inpb (EPPDataPort) << 8);
- }
- }
- else
- {
- v = SPPReadByte (); //402124
- v += (SPPReadByte () << 8);
- }
- return v;
- }
- void
- SetCartAddr (int addr) // 4023cc
- {
- l402200 (2, addr >> 16);
- l402200 (1, addr >> 8);
- l402200 (0, addr);
- }
- void
- WriteFlash (int addr, int data) // 402414
- {
- SetCartAddr (addr);
- l4021d0 (3);
- PPWriteWord (data);
- }
- int
- ReadFlash (int addr)
- {
- SetCartAddr (addr);
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- return PPReadWord ();
- }
- void
- l402684 (void)
- {
- #ifndef USE_PPDEV
- outpb (SPPStatPort, 1); // clear EPP time flag
- #endif
- l40226c ();
- }
- int
- LookForLinker (void) // 4026a8
- {
- l402684 ();
- l402200 (2, 0x12);
- l402200 (1, 0x34);
- l402200 (0, 0x56);
- l4021d0 (2);
- outpb (SPPCtrlPort, 0);
- if (PPReadByte () != 0x12) // 40234c
- return 0;
- l4021d0 (1);
- outpb (SPPCtrlPort, 0);
- if (PPReadByte () != 0x34)
- return 0;
- l4021d0 (0);
- outpb (SPPCtrlPort, 0);
- if (PPReadByte () != 0x56)
- return 0;
- outpb (SPPCtrlPort, 4);
- return 1;
- }
- void
- LinkerInit (void) // 4027c4
- {
- int linker_found = 0;
- /*
- uCON64 comment:
- Accessing I/O ports with addresses higher than 0x3ff causes an access
- violation on Windows XP (NT/2000) for _Windows_ executables without the use
- of an appropriate I/O port driver. UserPort is an example of an
- *inappropriate* I/O port driver, because it enables access to I/O ports up
- to 0x3ff. For some (ridiculous) reason, DOS executables are allowed to
- _access_ at least the ECP register this code uses. That doesn't mean it will
- result in the expected behaviour like enabling EPP.
- */
- if (EPPMode)
- {
- /*
- Writing to the ECP register seems to have no effect on my PC (which
- supports ECP, used appropriate BIOS setting). Tested on Windows XP with
- Windows executables (Cygwin, VC++ and MinGW) - dbjh
- */
- #ifndef USE_PPDEV
- outpb (ECPRegECR, 4); // set EPP mode for ECP chipsets
- #endif
- if (LookForLinker ())
- {
- // Linker found using EPP mode.
- linker_found = 1;
- puts ("Linker found. EPP found");
- if (SPPDataPort == 0x3bc)
- return;
- outpb (SPPCtrlPort, 4);
- }
- }
- if (!linker_found)
- {
- // Look for linker in SPP mode.
- #ifndef USE_PPDEV
- if (EPPMode)
- outpb (ECPRegECR, 0); // set SPP mode for ECP chipsets
- #endif
- EPPMode = 0;
- if (LookForLinker ())
- puts ("Linker found. EPP not found or not enabled - SPP used");
- else
- {
- fputs ("ERROR: Flash Advance Linker not found or not turned on\n",
- stderr);
- ProgramExit (1);
- }
- }
- }
- int
- ReadStatusRegister (int addr) // 402dd8
- {
- int v;
- WriteFlash (addr, INTEL28F_READSR);
- outpb (SPPCtrlPort, 0);
- v = PPReadWord (); // & 0xff;
- v = PPReadWord (); // & 0xff;
- return v;
- }
- // StartOffSet: 1 = 0, 2 = 64k, 3 = 128k, 4 = 192k
- // Size: 1 = 32k, 2 = 64k, 3 = 128k, 4 = 256k
- void
- BackupSRAM (FILE *fp, int StartOS, int Size) // 4046f4
- {
- int j, k, v;
- int m;
- int n = 1 << (Size - 1);
- int size = n * 32 * 1024, bytesread = 0;
- time_t starttime;
- printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
- starttime = time (NULL);
- for (m = ((StartOS - 1) << 1); m < (((StartOS - 1) << 1) + n); m++)
- {
- if ((m & 1) == 0)
- {
- SetVisolyBackupRWMode (m >> 1);
- l402234 ();
- }
- // Backup a 32k byte chunk
- for (j = 0; j < 0x80; j++)
- {
- l402200 (0, 0);
- l402200 (1, j + (0x80 * (m & 1)));
- l402200 (2, 0);
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- for (k = 0; k < 0x100; k++)
- {
- v = PPReadByte ();
- fputc (v, fp);
- }
- bytesread += 256;
- if ((bytesread & 0x1fff) == 0) // call ucon64_gauge() after receiving 8 kB
- ucon64_gauge (starttime, bytesread, size);
- }
- }
- }
- // StartOffSet: 1 = 0, 2 = 64k, 3 = 128k, 4 = 192k
- void
- RestoreSRAM (FILE *fp, int StartOS)
- {
- int i;
- int j, k;
- int m = ((StartOS - 1) << 1);
- int byteswritten = 0;
- time_t starttime;
- printf ("Send: %d Bytes (%.4f Mb)\n\n", ucon64.file_size,
- (float) ucon64.file_size / MBIT);
- starttime = time (NULL);
- i = fgetc (fp);
- while (!feof (fp))
- {
- if ((m & 1) == 0)
- {
- SetVisolyBackupRWMode (m >> 1);
- l402234 ();
- }
- // Restore a 32k byte chunk
- for (j = 0; j < 0x80; j++)
- {
- l402200 (0, 0);
- l402200 (1, j + (0x80 * (m & 1)));
- l402200 (2, 0);
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- for (k = 0; k < 0x100; k++)
- {
- PPWriteByte (i);
- i = fgetc (fp);
- }
- byteswritten += 256;
- if ((byteswritten & 0x1fff) == 0) // call ucon64_gauge() after sending 8 kB
- ucon64_gauge (starttime, byteswritten, ucon64.file_size);
- }
- m++;
- }
- }
- void
- BackupROM (FILE *fp, int SizekW)
- {
- u16 valw;
- u32 i, j;
- int size = SizekW << 1, bytesread = 0;
- time_t starttime;
- printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
-
- WriteFlash (0, INTEL28F_READARRAY); // Set flash (intel 28F640J3A) Read Mode
- starttime = time (NULL);
- for (i = 0; i < (u32) (SizekW >> 8); i++)
- {
- SetCartAddr (i << 8); // Set cart base addr to 0
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- for (j = 0; j < 256; j++)
- {
- valw = (unsigned short) PPReadWord ();
- fputc (valw & 0xff, fp);
- fputc (valw >> 8, fp);
- }
- bytesread += 256 << 1; // 256 words
- if ((bytesread & 0xffff) == 0) // call ucon64_gauge() after receiving 64 kB
- ucon64_gauge (starttime, bytesread, size);
- }
- }
- void
- dump (u8 BaseAdr)
- {
- // unsigned char low, high;
- int i;
- u8 First = 1;
- u16 v;
- u8 val1, val2;
- u8 Display[17] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- WriteFlash (0, INTEL28F_READARRAY); // Set flash (intel 28F640J3A) Read Mode
- SetCartAddr (BaseAdr << 7); // Set cart base addr to read
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- for (i = 0; i < 128; i++)
- {
- if (First == 1)
- {
- if (i * 2 < 256)
- fputc ('0', stdout);
- if (i * 2 < 16)
- fputc ('0', stdout);
- printf ("%hx - ", (i * 2));
- First = 0;
- }
- v = (unsigned short) PPReadWord ();
- val2 = v >> 8;
- val1 = v & 255;
- if ((val1 > 31) & (val1 < 127))
- Display[(i & 7) * 2] = val1;
- else
- Display[(i & 7) * 2] = 46;
- if (val1 < 16)
- fputc ('0', stdout);
- printf ("%hx ", val1);
- if ((val2 > 31) & (val2 < 127))
- Display[(i & 7) * 2 + 1] = val2;
- else
- Display[(i & 7) * 2 + 1] = 46;
- if (val2 < 16)
- fputc ('0', stdout);
- printf ("%hx ", val2);
- if ((i & 7) == 7)
- {
- First = 1;
- printf (" %3s\n", (&Display[0]));
- }
- }
- }
- void
- CheckForFC (void)
- {
- LinkerInit ();
- SetVisolyFlashRWMode ();
- Device = CartTypeDetect ();
- VisolyTurbo = 0;
- printf ("Device ID = 0x%x: ", Device);
- switch (Device)
- {
- case 0x16:
- fputs ("FA 32M (i28F320J3A)", stdout);
- break;
- case 0x17:
- fputs ("FA 64M (i28F640J3A)", stdout);
- break;
- case 0x18:
- fputs ("FA 128M (i28F128J3A)", stdout);
- break;
- case 0x2e:
- fputs ("Standard ROM", stdout);
- break;
- case 0x96:
- fputs ("Turbo FA 64M (2 x i28F320J3A)", stdout);
- VisolyTurbo = 1;
- break;
- case 0x97:
- fputs ("Turbo FA 128M (2 x i28F640J3A)", stdout);
- VisolyTurbo = 1;
- break;
- case 0x98:
- fputs ("Turbo FA 256M (2 x i28F128J3A", stdout);
- VisolyTurbo = 1;
- break;
- case 0xdc:
- fputs ("Hudson", stdout);
- break;
- case 0xe2:
- fputs ("Nintendo Flash Card (LH28F320BJE)", stdout);
- break;
- default:
- fputs ("Unknown", stdout);
- break;
- }
- fputc ('\n', stdout);
- }
- int
- GetFileByte (FILE *fp)
- {
- static int FilePos = 0;
- int i = 0;
- if (RepairHeader)
- {
- // Set file pointer just past header
- if (FilePos == 0)
- for (i = 0; i < 0xa0; i++)
- (void) fgetc (fp);
- if (FilePos < 0xa0)
- {
- if ((HeaderBad) && (FilePos > 3))
- i = gba_logodata[FilePos - 4]; // GoodHeader[FilePos];
- else
- i = FileHeader[FilePos];
- }
- else if ((FilePos == 0xb2) || (FilePos == 0xbd))
- {
- if (FilePos == 0xb2)
- i = 0x96; // Required
- else
- i = Complement;
- (void) fgetc (fp); // Discard file value
- }
- else
- i = fgetc (fp);
- }
- else
- i = fgetc (fp);
- FilePos++;
- return i;
- }
- int
- GetFileSize2 (FILE *fp)
- /*
- The name "GetFileSize" conflicts with a Windows function.
- For some odd reason Jeff Frohwein returned the file size minus 1. I (dbjh)
- guess that's a bug. I disabled the (terribly inefficient) file size code
- because uCON64 already determined the file size at this point.
- */
- {
- int FileSize;
- if (RepairHeader)
- {
- int i;
- int j;
- FileSize = 0;
- while (!feof (fp) && (FileSize < 0xc0))
- FileHeader[FileSize++] = fgetc (fp);
- if (feof (fp))
- {
- fputs ("ERROR: File must be 192 bytes or larger\n", stderr);
- ProgramExit (1);
- }
- HeaderBad = 0;
- i = 4;
- while (i < 0xa0) //9c)
- {
- if (FileHeader[i] != gba_logodata[i - 4]) // GoodHeader[i]
- HeaderBad = 1;
- i++;
- }
- if (HeaderBad)
- puts ("NOTE: Fixing logo area");
- Complement = 0;
- FileHeader[0xb2] = 0x96; // Required
- for (j = 0xa0; j < 0xbd; j++)
- Complement += FileHeader[j];
- Complement = (0 - (0x19 + Complement)) & 0xff;
- //printf("[Complement = 0x%x]", (int)Complement);
- //printf("[HeaderComp = 0x%x]", (int)FileHeader[0xbd]);
- if (FileHeader[0xbd] != Complement)
- puts ("NOTE: Fixing complement check");
- rewind (fp);
- }
- else
- rewind (fp);
- return ucon64.file_size;
- }
- // Program older (non-Turbo) Visoly flash card
- // (Single flash chip)
- void
- ProgramNonTurboIntelFlash (FILE *fp)
- {
- int i, j, k;
- int addr = 0;
- int FileSize;
- int Ready = 0;
- int Timeout;
- time_t starttime;
- // Get file size
- FileSize = GetFileSize2 (fp);
- puts ("Erasing Visoly non-turbo flash card...");
- // Erase as many 128k blocks as are required
- Ready = EraseNonTurboFABlocks (0, ((FileSize - 1) >> 17) + 1);
- clear_line (); // remove "erase gauge"
- if (Ready)
- {
- printf ("Send: %d Bytes (%.4f Mb)\n\n", FileSize, (float) FileSize / MBIT);
- //403018
- starttime = time (NULL);
- j = GetFileByte (fp);
- while (!feof (fp))
- {
- Ready = 0;
- Timeout = 0x4000;
- while ((Ready == 0) && (Timeout != 0))
- {
- WriteFlash (addr, INTEL28F_WRTOBUF);
- outpb (SPPCtrlPort, 0);
- Ready = PPReadWord () & 0x80;
- Timeout--;
- }
- if (Ready)
- {
- WriteFlash (addr, 15); // Write 15+1 16bit words
- SetCartAddr (addr); // Set cart base addr to 0
- l4021d0 (3);
- for (i = 0; i < 16; i++)
- {
- k = j;
- if (j != EOF)
- j = GetFileByte (fp);
- k += (j << 8);
- PPWriteWord (k);
- if (j != EOF)
- j = GetFileByte (fp);
- }
- addr += 16;
- if ((addr & 0x3fff) == 0) // call ucon64_gauge() after sending 32 kB
- ucon64_gauge (starttime, addr << 1, FileSize);
- PPWriteWord (INTEL28F_CONFIRM); // Comfirm block write
- Ready = 0;
- Timeout = 0x4000;
- while ((Ready == 0) && (Timeout != 0))
- {
- WriteFlash (0, INTEL28F_READSR);
- outpb (SPPCtrlPort, 0);
- i = PPReadWord () & 0xff;
- Ready = i & 0x80;
- Timeout--;
- }
- if (Ready)
- {
- if (i & 0x7f)
- {
- // One or more status register error bits are set
- outpb (SPPCtrlPort, 1);
- WriteFlash (0, INTEL28F_CLEARSR);
- Ready = 0;
- break;
- }
- }
- else
- {
- outpb (SPPCtrlPort, 1);
- WriteFlash (0, INTEL28F_CLEARSR);
- break;
- }
- }
- else
- break;
- }
- clear_line (); // remove last gauge
- ucon64_gauge (starttime, addr << 1, FileSize); // make gauge reach 100% when size % 32 k != 0
- WriteFlash (0, INTEL28F_READARRAY);
- outpb (SPPCtrlPort, 0);
- if (Ready)
- ;
- else
- fputs ("\nERROR: Flash card write failed\n", stderr);
- }
- else
- fputs ("\nERROR: Flash card erase failed\n", stderr);
- }
- // Program newer (Turbo) Visoly flash card
- // (Dual chip / Interleave)
- void
- ProgramTurboIntelFlash (FILE *fp)
- {
- int i, j = 0;
- int k; //z;
- int addr = 0;
- int done1, done2;
- int FileSize;
- int Timeout;
- int Ready; //= 0;
- time_t starttime;
- // Get file size
- FileSize = GetFileSize2 (fp);
- puts ("Erasing Visoly turbo flash card...");
- // Erase as many 256k blocks as are required
- Ready = EraseTurboFABlocks (0, ((FileSize - 1) >> 18) + 1);
- clear_line (); // remove "erase gauge"
- if (Ready)
- {
- printf ("Send: %d Bytes (%.4f Mb)\n\n", FileSize, (float) FileSize / MBIT);
- //403018
- starttime = time (NULL);
- j = GetFileByte (fp);
- while (!feof (fp))
- {
- done1 = 0;
- done2 = 0;
- Ready = 0;
- Timeout = 0x4000;
- while ((!Ready) && (Timeout != 0))
- {
- if (done1 == 0)
- WriteFlash (addr + 0, INTEL28F_WRTOBUF);
- if (done2 == 0)
- WriteFlash (addr + 1, INTEL28F_WRTOBUF);
- SetCartAddr (addr); // Set cart base addr
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- done1 = PPReadWord () & 0x80;
- done2 = PPReadWord () & 0x80;
- Ready = ((done1 + done2) == 0x100);
- Timeout--;
- }
- if (Ready)
- {
- WriteFlash (addr, 15); // Write 15+1 16bit words
- PPWriteWord (15);
- SetCartAddr (addr); // Set cart base addr
- l4021d0 (3);
- for (i = 0; i < 32; i++)
- {
- k = j;
- if (j != EOF)
- j = GetFileByte (fp);
- k += (j << 8);
- PPWriteWord (k);
- if (j != EOF)
- j = GetFileByte (fp);
- }
- addr += 32;
- if ((addr & 0x3fff) == 0) // call ucon64_gauge() after sending 32 kB
- ucon64_gauge (starttime, addr << 1, FileSize);
- PPWriteWord (INTEL28F_CONFIRM); // Comfirm block write
- PPWriteWord (INTEL28F_CONFIRM); // Comfirm block write
- Ready = 0;
- Timeout = 0x4000;
- k = 0;
- while (((k & 0x8080) != 0x8080) && (Timeout != 0))
- {
- outpb (SPPCtrlPort, 0);
- k = PPReadWord () & 0xff;
- k += ((PPReadWord () & 0xff) << 8);
- Ready = (k == 0x8080);
- Timeout--;
- }
- if (!Ready)
- break;
- }
- else
- break;
- }
- clear_line (); // remove last gauge
- ucon64_gauge (starttime, addr << 1, FileSize); // make gauge reach 100% when size % 32 k != 0
- WriteFlash (0, INTEL28F_READARRAY);
- outpb (SPPCtrlPort, 0);
- WriteFlash (1, INTEL28F_READARRAY);
- outpb (SPPCtrlPort, 0);
- if (Ready)
- ;
- else
- {
- WriteFlash (0, INTEL28F_CLEARSR);
- PPWriteWord (INTEL28F_CLEARSR);
- fputs ("\nERROR: Flash card write failed\n", stderr);
- }
- }
- else
- fputs ("\nERROR: Flash card erase failed\n", stderr);
- }
- // Program official Nintendo flash card
- void
- ProgramSharpFlash (FILE *fp)
- {
- int i, j;
- int k = 0;
- int addr = 0;
- int FileSize;
- int Ready;
- time_t starttime;
- // Get file size
- FileSize = GetFileSize2 (fp);
- puts ("Erasing Nintendo flash card...");
- // Erase as many 64k blocks as are required
- Ready = EraseNintendoFlashBlocks (0, ((FileSize - 1) >> 16) + 1);
- clear_line (); // remove "erase gauge"
- if (Ready)
- {
- printf ("Send: %d Bytes (%.4f Mb)\n\n", FileSize, (float) FileSize / MBIT);
- starttime = time (NULL);
- j = GetFileByte (fp);
- while (!feof (fp))
- {
- if (j != EOF)
- k = GetFileByte (fp);
- i = ((k & 0xff) << 8) + (j & 0xff);
- while ((ReadStatusRegister (0) & 0x80) == 0)
- ;
- WriteFlash (addr, SHARP28F_WORDWRITE);
- WriteFlash (addr, i);
- addr += 1;
- j = GetFileByte (fp);
- if ((addr & 0x3fff) == 0) // call ucon64_gauge() after sending 32 kB
- ucon64_gauge (starttime, addr << 1, FileSize);
- }
- clear_line (); // remove last gauge
- ucon64_gauge (starttime, addr << 1, FileSize); // make gauge reach 100% when size % 32 k != 0
- WriteFlash (0, INTEL28F_READARRAY);
- outpb (SPPCtrlPort, 0);
- }
- else
- fputs ("\nERROR: Flash card erase failed\n", stderr);
- }
- #if 0 // not used
- void
- VerifyFlash (FILE *fp)
- {
- int addr = 0;
- int CompareFail = 0;
- int k = 0;
- int i, j, m, n;
- WriteFlash (0, INTEL28F_READARRAY); // Set flash (intel 28F640J3A) Read Mode
- j = 0;
- while (!feof (fp))
- {
- j = fgetc (fp);
- if (j != EOF)
- {
- if ((addr & 0x1ff) == 0)
- {
- SetCartAddr (addr >> 1); // Set cart base addr to read
- l4021d0 (3);
- outpb (SPPCtrlPort, 0);
- }
- k = fgetc (fp);
- i = PPReadWord ();
- m = i & 0xff;
- n = i >> 8;
- if (m != j)
- {
- printf ("Address %x - Cartridge %x: File %hx\n", addr, m, j);
- CompareFail = 1;
- }
- if ((n != k) && (k != EOF))
- {
- printf ("Address %x - Cartridge %x: File %hx\n", addr + 1, n,
- k);
- CompareFail = 1;
- }
- addr += 2;
- }
- }
- // Correct verify length if at EOF
- if (k == EOF)
- addr--;
- if (CompareFail == 0)
- printf ("%d bytes compared OK\n", addr);
- }
- #endif
- void
- SpaceCheck (char c)
- {
- if (c != 0)
- {
- fputs ("ERROR: Space required between option and parameter\n", stderr);
- ProgramExit (1);
- }
- }
- int
- fal_main (int argc, char **argv)
- {
- int arg, i;
- u8 Base = 0;
- FILE *fp;
- char fname[128];//, fname2[128];
- int OptB = 0;
- int OptD = 0;
- int OptP = 0;
- int OptR = 0;
- int OptS = 0;
- // int OptV = 0;
- // int OptZ = 0;
- int port = 0x378;
- int ChipSize = 32;
- int BackupMemOffset = 0;
- int BackupMemSize = 0;
- if (argc < 2)
- {
- // usage (argv[0]);
- ProgramExit (1);
- }
- debug = 0;
- verbose = 1;
- EPPMode = 0; // uCON64 comment: use the most compatible setting as default
- DataSize16 = 0;
- WaitDelay = 0;
- VisolyTurbo = 0;
- RepairHeader = 1;
- for (arg = 1; arg < argc; arg++)
- {
- if (argv[arg][0] != '-')
- {
- // usage (argv[0]);
- ProgramExit (1);
- }
- switch (argv[arg][1])
- {
- case 'b':
- SpaceCheck (argv[arg][2]);
- BackupMemOffset = *(char *) argv[++arg] - 0x30;
- SpaceCheck (argv[arg][1]);
- BackupMemSize = *(char *) argv[++arg] - 0x30;
- if ((BackupMemSize < 1) || (BackupMemSize > 4) ||
- (BackupMemOffset < 1) || (BackupMemOffset > 4))
- {
- fputs ("ERROR: -b parameter values must be between 1-4\n", stderr);
- ProgramExit (1);
- }
- SpaceCheck (argv[arg][1]);
- strcpy (fname, argv[++arg]);
- OptB = 1;
- break;
- case '2':
- // 16-bit EPP support enable (doesn't work with
- // "Turbo FA 128M (2 x i28F640J3A)" - dbjh)
- DataSize16 = 1;
- break;
- case 'c':
- // Set cart size
- SpaceCheck (argv[arg][2]);
- ChipSize = (u16) (atoi (argv[++arg]));
- if ((ChipSize != 8) &&
- (ChipSize != 16) &&
- (ChipSize != 32) &&
- (ChipSize != 64) && (ChipSize != 128) && (ChipSize != 256))
- {
- fputs ("ERROR: Chip size must be 8,16,32,64,128 or 256\n", stderr);
- ProgramExit (1);
- }
- break;
- case 'd':
- // Dump 256 bytes to screen
- SpaceCheck (argv[arg][2]);
- if (argv[++arg] != NULL)
- Base = (u8) (atoi (argv[arg]));
- printf ("Base address: %hx\n", Base * 256);
- OptD = 1;
- break;
- case 's':
- // Backup flash cart
- SpaceCheck (argv[arg][2]);
- strcpy (fname, argv[++arg]);
- OptS = 1;
- break;
- case 'p':
- // Program flash cart
- SpaceCheck (argv[arg][2]);
- strcpy (fname, argv[++arg]);
- OptP = 1;
- break;
- case 'r':
- SpaceCheck (argv[arg][2]);
- BackupMemOffset = *(char *) argv[++arg] - 0x30;
- if ((BackupMemOffset < 1) || (BackupMemOffset > 4))
- {
- fputs ("ERROR: -r parameter value must be between 1-4\n", stderr);
- ProgramExit (1);
- }
- SpaceCheck (argv[arg][1]);
- strcpy (fname, argv[++arg]);
- OptR = 1;
- break;
- #if 0
- case 'v':
- // Verify flash cart
- SpaceCheck (argv[arg][2]);
- strcpy (fname2, argv[++arg]);
- OptV = 1;
- break;
- #endif
- case 'l':
- SpaceCheck (argv[arg][2]);
- i = atoi (argv[++arg]);
- /*
- uCON64 comment: we want to support non-standard parallel port
- addresses too. So, instead of passing a number from 1 to 4, we pass
- the address itself
- */
- port = i;
- break;
- case 'm':
- // uCON64 comment: See comment in LinkerInit(). Note that we reverse
- // the meaning compared to the original code.
- EPPMode = 1; // Set EPP mode
- break;
- case 'n':
- // Don't repair header
- RepairHeader = 0;
- break;
- case 'w':
- SpaceCheck (argv[arg][2]);
- WaitDelay = atoi (argv[++arg]);
- break;
- #if 0
- case 'z':
- OptZ = 1;
- break;
- #endif
- default:
- // usage (argv[0]);
- ProgramExit (1);
- }
- }
- InitPort (port);
- CheckForFC ();
- if (OptB)
- {
- //DumpSRAM ();
- if ((fp = fopen (fname, "wb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], fname);
- ProgramExit (1);
- }
- BackupSRAM (fp, BackupMemOffset, BackupMemSize);
- fclose (fp);
- }
- if (OptD)
- dump (Base);
- if ((OptP) && ((Device == 0) || (Device == 0x2e) || (Device == 0xff)))
- {
- fputs ("ERROR: Device type not recognized as programmable\n", stderr);
- ProgramExit (1);
- }
- if (OptR)
- {
- if ((fp = fopen (fname, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname);
- ProgramExit (1);
- }
- RestoreSRAM (fp, BackupMemOffset);
- fclose (fp);
- }
- if (OptP)
- {
- if ((fp = fopen (fname, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname);
- ProgramExit (1);
- }
- if (Device == 0xe2)
- ProgramSharpFlash (fp);
- else
- {
- if (VisolyTurbo)
- ProgramTurboIntelFlash (fp);
- else
- ProgramNonTurboIntelFlash (fp);
- }
- fclose (fp);
- }
- if (OptS)
- {
- if ((fp = fopen (fname, "wb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], fname);
- ProgramExit (1);
- }
- BackupROM (fp, ChipSize << 16);
- fclose (fp);
- }
- #if 0
- if (OptV)
- {
- if ((fp = fopen (fname2, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname2);
- ProgramExit (1);
- }
- VerifyFlash (fp);
- fclose (fp);
- }
- #endif
- // ProgramExit (0);
- return 0;
- }
- /*
- It will save you some work if you don't fully integrate the code above with
- uCON64's code, because it is a project separate from the uCON64 project.
- */
- int fal_argc = 0;
- char *fal_argv[128];
- void
- fal_args (unsigned int parport)
- {
- char parport_str[80];
- parport_print_info ();
- fal_argv[fal_argc++] = "fl";
- fal_argv[fal_argc++] = "-l";
- sprintf (parport_str, "%d", parport); // don't use %x, as Jeff Frohwein uses atoi()
- fal_argv[fal_argc++] = parport_str;
- if (ucon64.parport_mode == UCON64_EPP)
- fal_argv[fal_argc++] = "-m";
- }
- int
- fal_read_rom (const char *filename, unsigned int parport, int size)
- {
- char size_str[80];
- fal_args (parport);
- fal_argv[fal_argc++] = "-c";
- if (size != 8 && size != 16 && size != 32 && size != 64 && size != 128 &&
- size != 256)
- {
- fputs ("ERROR: Invalid argument for -xfalc=n\n"
- " n can be 8, 16, 32, 64, 128 or 256\n", stderr);
- exit (1);
- }
- sprintf (size_str, "%d", size);
- fal_argv[fal_argc++] = size_str;
- fal_argv[fal_argc++] = "-s";
- fal_argv[fal_argc++] = (char *) filename; // this is safe (FAL code
- // doesn't modify argv)
- if (!fal_main (fal_argc, fal_argv))
- return 0;
- return -1;
- }
- int
- fal_write_rom (const char *filename, unsigned int parport)
- {
- fal_args (parport);
- fal_argv[fal_argc++] = "-p";
- fal_argv[fal_argc++] = (char *) filename;
- if (!fal_main (fal_argc, fal_argv))
- return 0;
- return -1;
- }
- int
- fal_read_sram (const char *filename, unsigned int parport, int bank)
- {
- char bank_str[2];
- fal_args (parport);
- fal_argv[fal_argc++] = "-b";
- if (bank == UCON64_UNKNOWN)
- {
- fal_argv[fal_argc++] = "1";
- fal_argv[fal_argc++] = "4"; // 256 kB
- }
- else
- {
- if (bank < 1 || bank > 4)
- {
- fputs ("ERROR: Bank must be 1, 2, 3 or 4\n", stderr);
- exit (1);
- }
- bank_str[0] = (char) ('0' + bank);
- bank_str[1] = 0; // terminate string
- fal_argv[fal_argc++] = bank_str;
- fal_argv[fal_argc++] = "2"; // 64 kB
- }
- fal_argv[fal_argc++] = (char *) filename;
- if (!fal_main (fal_argc, fal_argv))
- return 0;
- return -1;
- }
- int
- fal_write_sram (const char *filename, unsigned int parport, int bank)
- {
- char bank_str[2];
- fal_args (parport);
- fal_argv[fal_argc++] = "-r";
- if (bank == UCON64_UNKNOWN)
- fal_argv[fal_argc++] = "1";
- else
- {
- if (bank < 1 || bank > 4)
- {
- fputs ("ERROR: Bank must be 1, 2, 3 or 4\n", stderr);
- exit (1);
- }
- bank_str[0] = (char) ('0' + bank);
- bank_str[1] = 0; // terminate string
- fal_argv[fal_argc++] = bank_str;
- }
- fal_argv[fal_argc++] = (char *) filename;
- if (!fal_main (fal_argc, fal_argv))
- return 0;
- return -1;
- }
- #endif // USE_PARALLEL
|