/* dc.c - Dreamcast support for uCON64 Copyright (c) 2004 NoisyB 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 #include #include #ifdef HAVE_UNISTD_H #include #endif #include "misc/file.h" #include "misc/misc.h" #include "misc/property.h" #include "misc/string.h" #ifdef USE_ZLIB #include "misc/archive.h" #endif #include "misc/getopt2.h" // st_getopt2_t #include "ucon64.h" #include "ucon64_misc.h" #include "dc.h" const st_getopt2_t dc_usage[] = { { NULL, 0, 0, 0, NULL, "Dreamcast" /* "1998 SEGA http://www.sega.com" */, NULL }, { "dc", 0, 0, UCON64_DC, NULL, "force recognition", &ucon64_wf[WF_OBJ_DC_SWITCH] }, #if 0 { "vms", 1, 0, UCON64_VMS, "SAV", "convert NES SAV file to a VMS file for use with NesterDC", NULL }, #endif { "scr", 0, 0, UCON64_SCR, NULL, "scramble 1ST_READ.BIN for selfboot CDs", &ucon64_wf[WF_OBJ_DC_DEFAULT] }, { "unscr", 0, 0, UCON64_UNSCR, NULL, "unscramble 1ST_READ.BIN for non-selfboot CDs", &ucon64_wf[WF_OBJ_DC_DEFAULT] }, #if 0 { "ip", 1, 0, UCON64_IP, "FILE", "extract ip.bin FILE from IMAGE; " OPTION_LONG_S "rom=IMAGE", NULL }, #endif { "mkip", 0, 0, UCON64_MKIP, NULL, "generate IP.BIN file with default values", &ucon64_wf[WF_OBJ_DC_NO_ROM] }, { "parse", 1, 0, UCON64_PARSE, "TEMPLATE", "parse TEMPLATE file into a IP.BIN;\n" "creates an empty template when TEMPLATE does not exist", &ucon64_wf[WF_OBJ_DC_NO_ROM] }, {NULL, 0, 0, 0, NULL, NULL, NULL} }; static int calc_crc (const unsigned char *buf, int size) { int i, c, n = 0xffff; for (i = 0; i < size; i++) { n ^= (buf[i] << 8); for (c = 0; c < 8; c++) if (n & 0x8000) n = (n << 1) ^ 4129; else n = (n << 1); } return n & 0xffff; } static void update_crc (char *ip) { int n = calc_crc ((unsigned char *) (ip + 0x40), 16); char buf[5]; sprintf (buf, "%04X", n); if (memcmp (buf, ip + 0x20, 4)) { printf ("Setting CRC to %s (was %.4s)\n", buf, ip + 0x20); memcpy (ip + 0x20, buf, 4); } } static unsigned int seed; static void dc_srand (unsigned int n) { seed = n & 0xffff; } static unsigned int dc_rand () { seed = (seed * 2109 + 9273) & 0x7fff; return (seed + 0xc000) & 0xffff; } #if 0 // header for SAV -> VMS conversion static const uint8_t nstrsave_bin[1024] = { 0x4e, 0x45, 0x53, 0x52, 0x4f, 0x4d, 0x2e, 0x4e, // 0x8 (8) 0x45, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 (16) 0x4e, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x43, // 0x18 (24) 0x20, 0x53, 0x61, 0x76, 0x65, 0x52, 0x61, 0x6d, // 0x20 (32) 0x20, 0x46, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, // 0x28 (40) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 (48) 0x2a, 0x2a, 0x2a, 0x4e, 0x65, 0x73, 0x74, 0x65, // 0x38 (56) 0x72, 0x44, 0x43, 0x2a, 0x2a, 0x2a, 0x00, 0x00, // 0x40 (64) 0x01, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, // 0x48 (72) 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 (80) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 (88) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 (96) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 (104) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 (112) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 (120) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 (128) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 (136) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 (144) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 (152) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 (160) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa8 (168) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 (176) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb8 (184) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 (192) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc8 (200) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 (208) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd8 (216) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 (224) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe8 (232) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0 (240) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 (248) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x100 (256) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x108 (264) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x110 (272) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x118 (280) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x120 (288) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x128 (296) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x130 (304) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x138 (312) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x140 (320) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x148 (328) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x150 (336) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x158 (344) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x160 (352) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x168 (360) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x170 (368) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x178 (376) 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x180 (384) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x188 (392) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x190 (400) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x198 (408) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1a0 (416) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1a8 (424) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1b0 (432) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1b8 (440) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1c0 (448) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1c8 (456) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1d0 (464) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1d8 (472) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1e0 (480) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1e8 (488) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1f0 (496) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1f8 (504) 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x200 (512) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x208 (520) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x210 (528) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x218 (536) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x220 (544) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x228 (552) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x230 (560) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x238 (568) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x240 (576) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x248 (584) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x250 (592) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x258 (600) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x260 (608) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x268 (616) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x270 (624) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x278 (632) 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x280 (640) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x288 (648) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x290 (656) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x298 (664) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a0 (672) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a8 (680) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2b0 (688) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2b8 (696) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2c0 (704) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2c8 (712) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2d0 (720) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2d8 (728) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2e0 (736) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2e8 (744) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2f0 (752) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2f8 (760) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x300 (768) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x308 (776) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x310 (784) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x318 (792) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x320 (800) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x328 (808) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x330 (816) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x338 (824) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x340 (832) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x348 (840) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x350 (848) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x358 (856) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x360 (864) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x368 (872) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x370 (880) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x378 (888) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x380 (896) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x388 (904) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x390 (912) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x398 (920) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3a0 (928) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3a8 (936) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3b0 (944) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3b8 (952) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3c0 (960) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3c8 (968) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3d0 (976) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3d8 (984) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3e0 (992) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3e8 (1000) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3f0 (1008) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3f8 (1016) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x400 (1024) }; #endif int dc_init (st_rominfo_t *rominfo) { int result = -1; rominfo->console_usage = dc_usage[0].help; return result; } static int check_areasym (char *ptr, int len) { int i, a = 0; for (i = 0; i < len; i++) switch (ptr[i]) { case 'J': a |= (1<<0); break; case 'U': a |= (1<<1); break; case 'E': a |= (1<<2); break; case ' ': break; default: fprintf (stderr, "ERROR: Unknown area symbol '%c'\n", ptr[i]); return -1; } for (i = 0; i < len; i++) if ((a & (1< templ[i].len) { fprintf (stderr, "ERROR: Data for field \"%s\" is too long... stripping to %d chars\n", templ[i].name, templ[i].len); p[templ[i].len] = 0; } memcpy (ip + templ[i].pos, p, strlen (p)); if (templ[i].extra_check) if (templ[i].extra_check (ip + templ[i].pos, templ[i].len) == -1) return -1; filled_in[i] = 1; } for (i = 0; templ[i].name; i++) if (!filled_in[i]) { fprintf (stderr, "ERROR: Missing value for \"%s\"\n", templ[i].name); return -1; } return 0; } int dc_parse (const char *templ_file) { char ip[0x8000], dest_name[FILENAME_MAX]; if (access (templ_file, F_OK) == -1) { int i = 0; printf ("Creating empty template file: \"%s\"\n", templ_file); for (i = 0; templ[i].name; i++) set_property (templ_file, templ[i].name, templ[i].def, templ[i].comment); printf (ucon64_msg[WROTE], templ_file); } if (parse_templ (templ_file, ip) == -1) return -1; update_crc (ip); strcpy (dest_name, "ip.bin"); ucon64_file_handler (dest_name, NULL, 0); ucon64_fwrite (ip, 0, 0x8000, dest_name, "wb"); printf (ucon64_msg[WROTE], dest_name); return 0; } int dc_mkip (void) { dc_parse ("default"); return 0; } static int load_chunk (FILE * fh, unsigned char *ptr, int32_t sz) { #define MAXCHUNK (2048*1024) static int idx[MAXCHUNK / 32]; int32_t i; /* Convert chunk size to number of slices */ sz /= 32; /* Initialize index table with unity, so that each slice gets loaded exactly once */ for (i = 0; i < sz; i++) idx[i] = i; for (i = sz - 1; i >= 0; --i) { /* Select a replacement index */ int x = (dc_rand () * i) >> 16; /* Swap */ int tmp = idx[i]; idx[i] = idx[x]; idx[x] = tmp; /* Load resulting slice */ if (fread (ptr + 32 * idx[i], 1, 32, fh) != 32) return -1; } return 0; } static int load_file (FILE * fh, unsigned char *ptr, uint32_t filesz) { uint32_t chunksz; dc_srand (filesz); /* Descramble 2 meg blocks for as long as possible, then gradually reduce the window down to 32 bytes (1 slice) */ for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) while (filesz >= chunksz) { load_chunk (fh, ptr, chunksz); filesz -= chunksz; ptr += chunksz; } /* Load final incomplete slice */ if (filesz) if (fread (ptr, 1, filesz, fh) != filesz) return -1; return 0; } static int save_chunk (FILE * fh, unsigned char *ptr, int32_t sz) { static int idx[MAXCHUNK / 32]; int32_t i; /* Convert chunk size to number of slices */ sz /= 32; /* Initialize index table with unity, so that each slice gets saved exactly once */ for (i = 0; i < sz; i++) idx[i] = i; for (i = sz - 1; i >= 0; --i) { /* Select a replacement index */ int x = (dc_rand () * i) >> 16; /* Swap */ int tmp = idx[i]; idx[i] = idx[x]; idx[x] = tmp; /* Save resulting slice */ if (fwrite (ptr + 32 * idx[i], 1, 32, fh) != 32) return -1; } return 0; } static int save_file (FILE * fh, unsigned char *ptr, uint32_t filesz) { uint32_t chunksz; dc_srand (filesz); /* Descramble 2 meg blocks for as long as possible, then gradually reduce the window down to 32 bytes (1 slice) */ for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) while (filesz >= chunksz) { save_chunk (fh, ptr, chunksz); filesz -= chunksz; ptr += chunksz; } /* Save final incomplete slice */ if (filesz) if (fwrite (ptr, 1, filesz, fh) != filesz) return -1; return 0; } static int descramble (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; load_file (fh, ptr, sz); fclose (fh); if (!(fh = fopen (dst, "wb"))) return -1; if (fwrite (ptr, 1, sz, fh) != sz) return -1; fclose (fh); free (ptr); 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 dc_scramble (void) { char dest_name[FILENAME_MAX]; strcpy (dest_name, ucon64.rom); ucon64_file_handler (dest_name, NULL, 0); if (!scramble (ucon64.rom, dest_name)) printf (ucon64_msg[WROTE], dest_name); else fprintf (stderr, ucon64_msg[WRITE_ERROR], dest_name); return 0; } int dc_unscramble (void) { char dest_name[FILENAME_MAX]; strcpy (dest_name, ucon64.rom); ucon64_file_handler (dest_name, NULL, 0); if (!descramble (ucon64.rom, dest_name)) printf (ucon64_msg[WROTE], dest_name); else fprintf (stderr, ucon64_msg[WRITE_ERROR], dest_name); return 0; }