int ppf_set_fid (const char *ppf, const char *fidname) { int fidsize, ppfsize, pos; char ppfname[FILENAME_MAX], fidbuf[MAX_ID_SIZE + 34 + 1] = "@BEGIN_FILE_ID.DIZ"; // +1 for string terminator strcpy (ppfname, ppf); ucon64_file_handler (ppfname, NULL, 0); fcopy (ppf, 0, fsizeof (ppf), ppfname, "wb"); // no copy if one file printf ("Adding FILE_ID.DIZ (%s)...\n", fidname); fidsize = ucon64_fread (fidbuf + 18, 0, MAX_ID_SIZE, fidname); memcpy (fidbuf + 18 + fidsize, "@END_FILE_ID.DIZ", 16); ppfsize = fsizeof (ppfname); pos = ucon64_find (ppfname, 0, ppfsize, "@BEGIN_FILE_ID.DIZ", 18, MEMCMP2_CASE | UCON64_FIND_QUIET); if (pos == -1) pos = ppfsize; truncate (ppfname, pos); ucon64_fwrite (fidbuf, pos, fidsize + 18 + 16, ppfname, "r+b"); pos += fidsize + 18 + 16; #ifdef WORDS_BIGENDIAN fidsize = bswap_32 (fidsize); // Write file size in little-endian format #endif ucon64_fwrite (&fidsize, pos, 4, ppfname, "r+b"); printf (ucon64_msg[WROTE], ppfname); return 0; }
static int scramble (const char *src, char *dst) { unsigned char *ptr = NULL; uint32_t sz = 0; FILE *fh; if (!(fh = fopen (src, "rb"))) return -1; sz = fsizeof (src); if (!(ptr = (unsigned char *) malloc (sz))) return -1; if (fread (ptr, 1, sz, fh) != sz) return -1; fclose (fh); if (!(fh == fopen (dst, "wb"))) return -1; save_file (fh, ptr, sz); fclose (fh); free (ptr); return 0; }
int truncate2 (const char *filename, off_t new_size) { int size = fsizeof (filename); struct stat fstate; stat (filename, &fstate); if (chmod (filename, fstate.st_mode | S_IWUSR)) return -1; if (size < new_size) { FILE *file; unsigned char padbuffer[MAXBUFSIZE]; int n_bytes; if ((file = fopen (filename, "ab")) == NULL) return -1; memset (padbuffer, 0, MAXBUFSIZE); while (size < new_size) { n_bytes = new_size - size > MAXBUFSIZE ? MAXBUFSIZE : new_size - size; fwrite (padbuffer, 1, n_bytes, file); size += n_bytes; } fclose (file); } else truncate (filename, new_size); return 0; // success }
char * mkbak (const char *filename, backup_t type) { static char buf[FILENAME_MAX]; if (access (filename, R_OK) != 0) return (char *) filename; strcpy (buf, filename); set_suffix (buf, ".bak"); if (strcmp (filename, buf) != 0) { remove (buf); // *try* to remove or rename() will fail if (rename (filename, buf)) // keep file attributes like date, etc. { fprintf (stderr, "ERROR: Can't rename \"%s\" to \"%s\"\n", filename, buf); exit (1); } } else // handle the case where filename has the suffix ".bak". { char buf2[FILENAME_MAX]; if (!dirname2 (filename, buf)) { fprintf (stderr, "INTERNAL ERROR: dirname2() returned NULL\n"); exit (1); } if (buf[0] != 0) if (buf[strlen (buf) - 1] != FILE_SEPARATOR) strcat (buf, FILE_SEPARATOR_S); strcat (buf, basename2 (tmpnam2 (buf2))); if (rename (filename, buf)) { fprintf (stderr, "ERROR: Can't rename \"%s\" to \"%s\"\n", filename, buf); exit (1); } } switch (type) { case BAK_MOVE: return buf; case BAK_DUPE: default: if (fcopy (buf, 0, fsizeof (buf), filename, "wb")) { fprintf (stderr, "ERROR: Can't open \"%s\" for writing\n", filename); exit (1); } sync (); return buf; } }
int smd_write_rom (const char *filename, unsigned int parport) { FILE *file; unsigned char *buffer; int bytesread, bytessend, blocksdone = 0, fsize; time_t starttime; ffe_init_io (parport); if ((file = fopen (filename, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename); exit (1); } if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL) { fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE); exit (1); } fsize = fsizeof (filename); printf ("Send: %d Bytes (%.4f Mb)\n", fsize, (float) fsize / MBIT); fread (buffer, 1, SMD_HEADER_LEN, file); ffe_send_block (0xdc00, buffer, SMD_HEADER_LEN); // send header bytessend = SMD_HEADER_LEN; ffe_send_command0 (0x2001, 0); printf ("Press q to abort\n\n"); starttime = time (NULL); while ((bytesread = fread (buffer, 1, BUFFERSIZE, file))) { ffe_send_command (5, (unsigned short) blocksdone, 0); ffe_send_block (0x8000, buffer, bytesread); blocksdone++; bytessend += bytesread; ucon64_gauge (starttime, bytessend, fsize); ffe_checkabort (2); } // ROM dump > 128 16 KB blocks? (=16 Mb (=2 MB)) ffe_send_command0 (0x2001, (unsigned char) (blocksdone > 0x80 ? 7 : 3)); free (buffer); fclose (file); ffe_deinit_io (); return 0; }
int ppf_set_desc (const char *ppf, const char *description) { char desc[50], ppfname[FILENAME_MAX]; strcpy (ppfname, ppf); memset (desc, ' ', 50); strncpy (desc, description, strlen (description)); ucon64_file_handler (ppfname, NULL, 0); fcopy (ppf, 0, fsizeof (ppf), ppfname, "wb"); // no copy if one file ucon64_fwrite (desc, 6, 50, ppfname, "r+b"); printf (ucon64_msg[WROTE], ppfname); return 0; }
int smd_write_sram (const char *filename, unsigned int parport) { FILE *file; unsigned char *buffer; int bytesread, bytessend = 0, size; unsigned short address; time_t starttime; ffe_init_io (parport); if ((file = fopen (filename, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename); exit (1); } if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL) { fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE); exit (1); } size = fsizeof (filename) - SMD_HEADER_LEN; printf ("Send: %d Bytes\n", size); fseek (file, SMD_HEADER_LEN, SEEK_SET); // skip the header ffe_send_command0 (0x2001, 4); printf ("Press q to abort\n\n"); address = 0x4000; starttime = time (NULL); while ((bytesread = fread (buffer, 1, BUFFERSIZE, file))) { ffe_send_block (address, buffer, bytesread); address += 0x4000; bytessend += bytesread; ucon64_gauge (starttime, bytessend, size); ffe_checkabort (2); } free (buffer); fclose (file); ffe_deinit_io (); return 0; }
int smsgg_write_sram (const char *filename, unsigned int parport, int start_bank) { FILE *file; unsigned char buffer[0x4000]; int size, bytesread, bytessend = 0, address; time_t starttime; void (*write_block) (int *, unsigned char *) = write_ram_by_byte; // write_ram_by_page (void) write_ram_by_page; size = fsizeof (filename); if (start_bank == -1) address = 0; else { if (start_bank < 1 || start_bank > 4) { fputs ("ERROR: Bank must be a value 1 - 4\n", stderr); exit (1); } address = (start_bank - 1) * 32 * 1024; } if ((file = fopen (filename, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename); exit (1); } ttt_init_io (parport); printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT); starttime = time (NULL); while ((bytesread = fread (buffer, 1, 0x4000, file))) { write_block (&address, buffer); bytessend += bytesread; ucon64_gauge (starttime, bytessend, size); } fclose (file); ttt_deinit_io (); return 0; }
int smsgg_write_rom (const char *filename, unsigned int parport) { FILE *file; unsigned char buffer[0x4000]; int size, address = 0, bytesread, bytessend = 0; time_t starttime; void (*write_block) (int *, unsigned char *) = write_rom_by_page; // write_rom_by_byte (void) write_rom_by_byte; if ((file = fopen (filename, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename); exit (1); } ttt_init_io (parport); size = fsizeof (filename); printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT); eep_reset (); if (ttt_get_id () != 0xb0d0) { fputs ("ERROR: SMS-PRO/GG-PRO flash card (programmer) not detected\n", stderr); fclose (file); ttt_deinit_io (); exit (1); } starttime = time (NULL); eep_reset (); while ((bytesread = fread (buffer, 1, 0x4000, file))) { if ((address & 0xffff) == 0) ttt_erase_block (address); write_block (&address, buffer); bytessend += bytesread; ucon64_gauge (starttime, bytessend, size); } fclose (file); ttt_deinit_io (); return 0; }
// based on sourcecode of MakePPF v2.0 Linux/Unix by Icarus/Paradox int ppf_create (const char *orgname, const char *modname) { FILE *orgfile, *modfile, *ppffile; char ppfname[FILENAME_MAX], buffer[MAX_ID_SIZE], obuf[512], mbuf[512]; #if 0 char *fidname = "FILE_ID.DIZ"; #endif int x, osize, msize, blocksize, n_changes, total_changes = 0; unsigned int seekpos = 0, pos; osize = fsizeof (orgname); msize = fsizeof (modname); #ifndef DIFF_FSIZE if (osize != msize) { fprintf (stderr, "ERROR: File sizes do not match\n"); return -1; } #endif if ((orgfile = fopen (orgname, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], orgname); exit (1); } if ((modfile = fopen (modname, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], modname); exit (1); } strcpy (ppfname, modname); set_suffix (ppfname, ".ppf"); ucon64_file_handler (ppfname, NULL, 0); if ((ppffile = fopen (ppfname, "wb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], ppfname); exit (1); } // creating PPF 2.0 header fwrite ("PPF20", 5, 1, ppffile); // magic fputc (1, ppffile); // encoding method memset (buffer, ' ', 50); fwrite (buffer, 50, 1, ppffile); // description line #ifdef WORDS_BIGENDIAN x = bswap_32 (osize); fwrite (&x, 4, 1, ppffile); #else fwrite (&osize, 4, 1, ppffile); // orgfile size #endif fseek (orgfile, 0x9320, SEEK_SET); memset (buffer, 0, 1024); // one little hack that makes PPF fread (buffer, 1024, 1, orgfile); // suitable for files < 38688 bytes fwrite (buffer, 1024, 1, ppffile); // 1024 byte block printf ("Writing patch data, please wait...\n"); // finding changes fseek (orgfile, 0, SEEK_SET); fseek (modfile, 0, SEEK_SET); while ((blocksize = fread (obuf, 1, 255, orgfile))) { blocksize = fread (mbuf, 1, blocksize, modfile); #ifdef DIFF_FSIZE if (blocksize == 0) break; #endif pos = seekpos; x = 0; while (x != blocksize) { if (obuf[x] != mbuf[x]) { pos = seekpos + x; n_changes = 0; do { buffer[n_changes] = mbuf[x]; n_changes++; x++; } while (x != blocksize && obuf[x] != mbuf[x]); total_changes += n_changes; #ifdef WORDS_BIGENDIAN pos = bswap_32 (pos); #endif fwrite (&pos, 4, 1, ppffile); fputc (n_changes, ppffile); fwrite (buffer, n_changes, 1, ppffile); } else x++; } seekpos += blocksize; } #ifdef DIFF_FSIZE if (msize > osize) { pos = seekpos; while ((blocksize = fread (buffer, 1, 255, modfile))) { total_changes += blocksize; #ifdef WORDS_BIGENDIAN x = bswap_32 (pos); fwrite (&x, 4, 1, ppffile); #else fwrite (&pos, 4, 1, ppffile); #endif fputc (blocksize, ppffile); fwrite (buffer, blocksize, 1, ppffile); pos += blocksize; } } else if (msize < osize) printf ("WARNING: %s is smaller than %s\n" " PPF can't store information about that fact\n", modname, orgname); #endif fclose (orgfile); fclose (modfile); if (total_changes == 0) { printf ("%s and %s are identical\n" "Removing: %s\n", orgname, modname, ppfname); fclose (ppffile); remove (ppfname); return -1; } #if 0 if (fidname) { int fsize = fsizeof (fidname); if (fsize > MAX_ID_SIZE) fsize = MAX_ID_SIZE; // File id only up to 3072 bytes! printf ("Adding FILE_ID.DIZ (%s)...\n", fidname); ucon64_fread (buffer, 0, fsize, fidname); fwrite ("@BEGIN_FILE_ID.DIZ", 18, 1, ppffile); fwrite (buffer, fsize, 1, ppffile); fwrite ("@END_FILE_ID.DIZ", 16, 1, ppffile); #ifdef WORDS_BIGENDIAN fsize = bswap_32 (fsize); // Write file size in little-endian format #endif fwrite (&fsize, 4, 1, ppffile); } #endif fclose (ppffile); printf (ucon64_msg[WROTE], ppfname); return 0; }
// based on source code of ApplyPPF v2.0 for Linux/Unix by Icarus/Paradox int ppf_apply (const char *mod, const char *ppfname) { FILE *modfile, *ppffile; char desc[50 + 1], diz[MAX_ID_SIZE + 1], buffer[1024], ppfblock[1024], modname[FILENAME_MAX]; int x, method, dizlen = 0, modlen, ppfsize, bytes_to_skip = 0, n_changes; unsigned int pos; strcpy (modname, mod); ucon64_file_handler (modname, NULL, 0); fcopy (mod, 0, fsizeof (mod), modname, "wb"); // no copy if one file if ((modfile = fopen (modname, "r+b")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], modname); exit (1); } if ((ppffile = fopen (ppfname, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], ppfname); exit (1); } // Is it a PPF File? fread (buffer, 3, 1, ppffile); if (strncmp ("PPF", buffer, 3)) { fprintf (stderr, "ERROR: %s is not a valid PPF file\n", ppfname); exit (1); } // What encoding method? PPF 1.0 or PPF 2.0? fseek (ppffile, 5, SEEK_SET); method = fgetc (ppffile); if (method != 0 && method != 1) { fprintf (stderr, "ERROR: Unknown encoding method! Check for updates\n"); exit (1); } ppfsize = fsizeof (ppfname); // Show PPF information fseek (ppffile, 6, SEEK_SET); // Read description line fread (desc, 50, 1, ppffile); desc[50] = 0; // terminate string printf ("\n" // print a newline between "Filename : %s\n", ppfname); // backup message and PPF info printf ("Encoding method : %d (PPF %d.0)\n", method, method + 1); printf ("Description : %s\n", desc); if (method == 0) // PPF 1.0 { printf ("FILE_ID.DIZ : No\n\n"); x = 56; // file pointer is at right position (56) } else // method == 1 // PPF 2.0 { fseek (ppffile, ppfsize - 8, SEEK_SET); fread (buffer, 4, 1, ppffile); // Is there a file id? if (strncmp (".DIZ", buffer, 4)) printf ("FILE_ID.DIZ : No\n\n"); else { printf ("FILE_ID.DIZ : Yes, showing...\n"); fread (&dizlen, 4, 1, ppffile); #ifdef WORDS_BIGENDIAN dizlen = bswap_32 (dizlen); // FILE_ID.DIZ size is in little-endian format #endif fseek (ppffile, ppfsize - dizlen - (16 + 4), SEEK_SET); bytes_to_skip = dizlen + 18 + 16 + 4; // +4 for FILE_ID.DIZ size integer if (dizlen > MAX_ID_SIZE) dizlen = MAX_ID_SIZE; // do this after setting bytes_to_skip! fread (diz, dizlen, 1, ppffile); diz[dizlen] = 0; // terminate string puts (diz); } // Do the file size check fseek (ppffile, 56, SEEK_SET); fread (&x, 4, 1, ppffile); #ifdef WORDS_BIGENDIAN x = bswap_32 (x); // file size is stored in little-endian format #endif modlen = fsizeof (modname); if (x != modlen) { fprintf (stderr, "ERROR: The size of %s is not %d bytes\n", modname, x); exit (1); } // Do the binary block check fseek (ppffile, 60, SEEK_SET); fread (ppfblock, 1024, 1, ppffile); fseek (modfile, 0x9320, SEEK_SET); memset (buffer, 0, 1024); // one little hack that makes PPF fread (buffer, 1024, 1, modfile); // suitable for files < 38688 bytes if (memcmp (ppfblock, buffer, 1024)) { fprintf (stderr, "ERROR: This patch does not belong to this image\n"); exit (1); } fseek (ppffile, 1084, SEEK_SET); x = 1084; } // Patch the image printf ("Patching...\n"); for (; x < ppfsize - bytes_to_skip; x += 4 + 1 + n_changes) { fread (&pos, 4, 1, ppffile); // Get position for modfile #ifdef WORDS_BIGENDIAN pos = bswap_32 (pos); #endif n_changes = fgetc (ppffile); // How many bytes do we have to write? fread (buffer, n_changes, 1, ppffile); // And this is what we have to write fseek (modfile, pos, SEEK_SET); // Go to the right position in the modfile fwrite (buffer, n_changes, 1, modfile); // Write n_changes bytes to that pos } printf ("Done\n"); fclose (ppffile); fclose (modfile); printf (ucon64_msg[WROTE], modname); return 0; }
int bsl_apply (const char *mod, const char *bslname) { FILE *modfile, *bslfile; unsigned char byte; char buf[4096], modname[FILENAME_MAX]; int data, nbytes, offset; strcpy (modname, mod); ucon64_file_handler (modname, NULL, 0); fcopy (mod, 0, fsizeof (mod), modname, "wb"); // no copy if one file if ((modfile = fopen (modname, "r+b")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], modname); return -1; } if ((bslfile = fopen (bslname, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], bslname); return -1; } printf ("Applying BSL/Baseline patch...\n"); while (!feof (bslfile)) // we could use 1, but feof() makes it fail-safe { fscanf (bslfile, "%d\n", &offset); fscanf (bslfile, "%d\n", &data); if ((offset == -1) && (data == -1)) break; fseek (modfile, offset, SEEK_SET); fputc (data, modfile); } fscanf (bslfile, "%d\n", &offset); fscanf (bslfile, "%d\n", &nbytes); fseek (modfile, offset, SEEK_SET); if (nbytes > 0) { while (nbytes > 4096) { fread (buf, 4096, 1, bslfile); fwrite (buf, 4096, 1, modfile); nbytes -= 4096; } while (nbytes-- >= 0) // yes, one byte more than the { // _value_ read from the BSL file byte = (unsigned char) fgetc (bslfile); fputc (byte, modfile); } } printf ("Patching complete\n\n"); printf (ucon64_msg[WROTE], modname); printf ("\n" "NOTE: Sometimes you have to add/strip a 512 bytes header when you patch a ROM\n" " This means you must modify for example a SNES ROM with -swc or -stp or\n" " the patch will not work\n"); fclose (bslfile); fclose (modfile); return 0; }
int pce_multi (int truncate_size, char *fname) { #define BUFSIZE (32 * 1024) int n, n_files, file_no, bytestowrite, byteswritten, done, truncated = 0, totalsize = 0, size, org_do_not_calc_crc = ucon64.do_not_calc_crc; struct stat fstate; FILE *srcfile, *destfile; char destname[FILENAME_MAX]; unsigned char buffer[BUFSIZE]; if (truncate_size == 0) { fprintf (stderr, "ERROR: Cannot make multi-game file of 0 bytes\n"); return -1; } if (fname != NULL) { strcpy (destname, fname); n_files = ucon64.argc; } else { strcpy (destname, ucon64.argv[ucon64.argc - 1]); n_files = ucon64.argc - 1; } ucon64_file_handler (destname, NULL, OF_FORCE_BASENAME); if ((destfile = fopen (destname, "wb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], destname); return -1; } printf ("Creating multi-game file for PCE-PRO: %s\n", destname); file_no = 0; for (n = 1; n < n_files; n++) { if (access (ucon64.argv[n], F_OK)) continue; // "file" does not exist (option) stat (ucon64.argv[n], &fstate); if (!S_ISREG (fstate.st_mode)) continue; if (file_no == 32) // loader + 31 games { printf ("WARNING: A multi-game file can contain a maximum of 31 games. The other files\n" " are ignored.\n"); break; } ucon64.console = UCON64_UNKNOWN; ucon64.fname = ucon64.argv[n]; ucon64.file_size = fsizeof (ucon64.fname); // DON'T use fstate.st_size, because file could be compressed ucon64.do_not_calc_crc = 1; if (pce_init (ucon64.nfo) != 0) printf ("WARNING: %s does not appear to be a PC-Engine ROM\n", ucon64.fname); if ((srcfile = fopen (ucon64.fname, "rb")) == NULL) { fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], ucon64.fname); continue; } if (ucon64.nfo->backup_header_len) fseek (srcfile, ucon64.nfo->backup_header_len, SEEK_SET); size = ucon64.file_size - ucon64.nfo->backup_header_len; if (file_no == 0) { printf ("Loader: %s\n", ucon64.fname); if (size != PCE_PRO_LOADER_SIZE) printf ("WARNING: Are you sure %s is a loader binary?\n", ucon64.fname); } else { printf ("ROM%d: %s\n", file_no, ucon64.fname); write_game_table_entry (destfile, file_no, totalsize, size); } file_no++; done = 0; byteswritten = 0; // # of bytes written per file while (!done) { bytestowrite = fread (buffer, 1, BUFSIZE, srcfile); if (totalsize + bytestowrite > truncate_size) { bytestowrite = truncate_size - totalsize; done = 1; truncated = 1; printf ("Output file needs %d Mbit on flash card, truncating %s, skipping %d bytes\n", truncate_size / MBIT, ucon64.fname, size - (byteswritten + bytestowrite)); } totalsize += bytestowrite; if (bytestowrite == 0) done = 1; fwrite (buffer, 1, bytestowrite, destfile); byteswritten += bytestowrite; } // Be sure the ROM size is a multiple of the buffer size used in // pce_write_rom(), which is 0x4000 (16 kB, so using "buffer" is OK). bytestowrite = ((size + 0x3fff) & ~0x3fff) - size; if (bytestowrite) { memset (buffer, 0xff, bytestowrite); totalsize += bytestowrite; fwrite (buffer, 1, bytestowrite, destfile); } // pce_write_rom() handles alignment. Games have to be aligned to a Mbit // boundary. totalsize = (totalsize + MBIT - 1) & ~(MBIT - 1); if (size == 3 * MBIT || size == 4 * MBIT) totalsize += 2 * MBIT; fclose (srcfile); if (truncated) break; } // fill the next game table entry fseek (destfile, 0xb000 + (file_no - 1) * 0x20, SEEK_SET); fputc (0, destfile); // indicate no next game // Make it possible for pce_write_rom() to detect that the file is a // multi-game file. fseek (destfile, 0xb3f4, SEEK_SET); strncpy ((char *) buffer, "uCON64 " UCON64_VERSION_S, 12); buffer[12] = 0; fwrite (buffer, 1, strlen ((char *) buffer), destfile); fclose (destfile); ucon64.console = UCON64_PCE; ucon64.do_not_calc_crc = org_do_not_calc_crc; return 0; }
int ucon64_rom_handling (void) { int no_rom = 0; static st_rominfo_t rominfo; struct stat fstate; ucon64_rom_flush (&rominfo); // a ROM (file)? if (!ucon64.rom) no_rom = 1; else if (!ucon64.rom[0]) no_rom = 1; else if (access (ucon64.rom, F_OK | R_OK) == -1 && (!(ucon64.flags & WF_NO_ROM))) { fprintf (stderr, "ERROR: Could not open %s\n", ucon64.rom); no_rom = 1; } else if (stat (ucon64.rom, &fstate) == -1) no_rom = 1; else if (S_ISREG (fstate.st_mode) != TRUE) no_rom = 1; #if 0 // printing the no_rom error message for files of 0 bytes only confuses people else if (!fstate.st_size) no_rom = 1; #endif if (no_rom) { if (!(ucon64.flags & WF_NO_ROM)) { fputs ("ERROR: This option requires a file argument (ROM/image/SRAM file/directory)\n", stderr); return -1; } return 0; } // The next statement is important and should be executed as soon as // possible (and sensible) in this function ucon64.file_size = fsizeof (ucon64.rom); // We have to do this here, because we don't know the file size until now if (ucon64.buheader_len > ucon64.file_size) { fprintf (stderr, "ERROR: A backup unit header length was specified that is larger than the file\n" " size (%d > %d)\n", ucon64.buheader_len, ucon64.file_size); return -1; } if (!(ucon64.flags & WF_INIT)) return 0; // "walk through" <console>_init() if (ucon64.flags & WF_PROBE) { if (ucon64.rominfo) { // Restore any overrides from st_ucon64_t // We have to do this *before* calling ucon64_probe(), *not* afterwards if (UCON64_ISSET (ucon64.buheader_len)) rominfo.buheader_len = ucon64.buheader_len; if (UCON64_ISSET (ucon64.interleaved)) rominfo.interleaved = ucon64.interleaved; // ucon64.rominfo = (st_rominfo_t *) &rominfo; } ucon64.rominfo = ucon64_probe (&rominfo); // determines console type #ifdef USE_DISCMAGE // check for disc image only if ucon64_probe() failed or --disc was used if (ucon64.discmage_enabled) // if (!ucon64.rominfo || ucon64.force_disc) if (ucon64.force_disc) ucon64.image = dm_reopen (ucon64.rom, 0, (dm_image_t *) ucon64.image); #endif } // end of WF_PROBE // Does the option allow split ROMs? if (ucon64.flags & WF_NO_SPLIT) /* Test for split files only if the console type knows about split files at all. However we only know the console type after probing. */ if (ucon64.console == UCON64_NES || ucon64.console == UCON64_SNES || ucon64.console == UCON64_GEN || ucon64.console == UCON64_NG) if ((UCON64_ISSET (ucon64.split)) ? ucon64.split : ucon64_testsplit (ucon64.rom)) { fprintf (stderr, "ERROR: %s seems to be split. You have to join it first\n", basename2 (ucon64.rom)); return -1; } /* CRC32 Calculating the CRC32 checksum for the ROM data of a UNIF file (NES) shouldn't be done with ucon64_fcrc32(). nes_init() uses crc32(). The CRC32 checksum is used to search in the DAT files, but at the time of this writing (Februari the 7th 2003) all DAT files contain checksums of files in only one format. This matters for SNES and Genesis ROMs in interleaved format and Nintendo 64 ROMs in non-interleaved format. The corresponding initialization functions calculate the CRC32 checksum of the data in the format of which the checksum is stored in the DAT files. For these "problematic" files, their "real" checksum is stored in ucon64.fcrc32. */ if (ucon64.crc32 == 0) if (!ucon64.force_disc) // NOT for disc images if (!(ucon64.flags & WF_NO_CRC32) && ucon64.file_size <= MAXROMSIZE) ucon64_chksum (NULL, NULL, &ucon64.crc32, ucon64.rom, ucon64.rominfo ? ucon64.rominfo->buheader_len : 0); // DATabase ucon64.dat = NULL; if (ucon64.crc32 != 0 && ucon64.dat_enabled) { ucon64.dat = ucon64_dat_search (ucon64.crc32, NULL); if (ucon64.dat) { // detected file size must match DAT file size int size = ucon64.rominfo ? UCON64_ISSET (ucon64.rominfo->data_size) ? ucon64.rominfo->data_size : ucon64.file_size - ucon64.rominfo->buheader_len : ucon64.file_size; if ((int) (((st_ucon64_dat_t *) ucon64.dat)->fsize) != size) ucon64.dat = NULL; } if (ucon64.dat) switch (ucon64.console) { case UCON64_SNES: case UCON64_GEN: case UCON64_GB: case UCON64_GBA: case UCON64_N64: // These ROMs have internal headers with name, country, maker, etc. break; default: // Use ucon64.dat instead of ucon64.dat_enabled in case the index // file could not be created/opened -> no segmentation fault if (ucon64.dat && ucon64.rominfo) { if (!ucon64.rominfo->name[0]) strcpy (ucon64.rominfo->name, NULL_TO_EMPTY (((st_ucon64_dat_t *) ucon64.dat)->name)); else if (ucon64.console == UCON64_NES) { // override the three-character FDS or FAM name int t = nes_get_file_type (); if (t == FDS || t == FAM) strcpy (ucon64.rominfo->name, NULL_TO_EMPTY (((st_ucon64_dat_t *) ucon64.dat)->name)); } if (!ucon64.rominfo->country) ucon64.rominfo->country = NULL_TO_EMPTY (((st_ucon64_dat_t *) ucon64.dat)->country); } break; } } // display info if ((ucon64.flags & WF_NFO || ucon64.flags & WF_NFO_AFTER) && ucon64.quiet < 1) ucon64_nfo (); return 0; }