Beispiel #1
0
int sdcard_init ( const char *fn, const char *extd81fn )
{
	char fnbuf[PATH_MAX + 1];
	atexit(sdcard_shutdown);
	sd_status = 0;
	sd_is_read_only = 1;
	d81_is_read_only = 1;
	mounted = 0;
	memset(sd_sector_bytes, 0, sizeof sd_sector_bytes);
	memset(sd_d81_img1_start, 0, sizeof sd_d81_img1_start);
	sdfd = emu_load_file(fn, fnbuf, -1);    // get the file descriptor only ...
	if (sdfd < 0) {
		ERROR_WINDOW("Cannot open SD-card image %s, SD-card access won't work! ERROR: %s", fn, strerror(errno));
		DEBUG("SDCARD: cannot open image %s" NL, fn);
	} else {
		// try to open in R/W mode ...
		int tryfd = open(fnbuf, O_RDWR | O_BINARY);
		if (tryfd >= 0) {
			// use R/W mode descriptor if it was OK!
			close(sdfd);
			sdfd = tryfd;
			DEBUG("SDCARD: image file re-opened in RD/WR mode, good" NL);
			sd_is_read_only = 0;
		} else
			INFO_WINDOW("Image file %s could be open only in R/O mode", fnbuf);
		// Check size!
		DEBUG("SDCARD: cool, SD-card image %s (as %s) is open" NL, fn, fnbuf);
		sd_card_size = lseek(sdfd, 0, SEEK_END);
		if (sd_card_size == (off_t)-1) {
			ERROR_WINDOW("Cannot query the size of the SD-card image %s, SD-card access won't work! ERROR: %s", fn, strerror(errno));
			close(sdfd);
			sdfd = -1;
			return sdfd;
		}
		if (sd_card_size > 2147483648UL) {
			ERROR_WINDOW("SD-card image is too large! Max allowed size is 2Gbytes!");
			close(sdfd);
			sdfd = -1;
			return sdfd;
		}
		if (sd_card_size < 67108864) {
			ERROR_WINDOW("SD-card image is too small! Min required size is 64Mbytes!");
			close(sdfd);
			sdfd = -1;
			return sdfd;
		}
		DEBUG("SDCARD: detected size in Mbytes: %d" NL, (int)(sd_card_size >> 20));
		if (sd_card_size & (off_t)511) {
			ERROR_WINDOW("SD-card image size is not multiple of 512 bytes!!");
			close(sdfd);
			sdfd = -1;
			return sdfd;
		}
	}
	if (sdfd >= 0)
		open_external_d81(extd81fn);
	return sdfd;
}
Beispiel #2
0
static void save_sample_config ( const char *name )
{
#ifdef __EMSCRIPTEN__
	DEBUGPRINT("CONFIG: no configuration is saved in case of emscripten." NL);
#else
	char path[PATH_MAX + 1];
	FILE *f = open_emu_file(name, "r", path);
	if (f) {
		fclose(f);
		DEBUGPRINT("CONFIG: sample configuration %s (%s) already exists, skipping to create." NL, name, path);
		return;
	}
	f = open_emu_file(name, "w", path);
	if (f) {
		dump_config(f);
		fclose(f);
		INFO_WINDOW("Note: created sample config file %s", path);
	} else
		INFO_WINDOW("Note: cannot create sample config file %s", path);
#endif
}
Beispiel #3
0
int geos_load_kernal ( void )
{
	Uint8 buffer[0xB000];
	int len = emu_load_file(GEOS_KERNAL_NAME, buffer, sizeof buffer);
	int addr;
	if (len < 0) {
		INFO_WINDOW("Cannot open GEOS kernal (%s), or I/O error", GEOS_KERNAL_NAME);
		return 1;	// file not found, or I/O error
	}
	if (len < 0x1000) {
		INFO_WINDOW("Abnormally short GEOS kernal (%s)", GEOS_KERNAL_NAME);
		return 1;
	}
	if (len == sizeof buffer) {
		INFO_WINDOW("Abnormally large GEOS kernal (%s)", GEOS_KERNAL_NAME);
		return 1;
	}
	addr = buffer[0] | (buffer[1] << 8);	// load address
	if (addr == 0x5000) {
		cpu_pc = 0x5000;
	} else if (addr == 0x801) {
		int sys = check_basic_stub(buffer + 6, addr);
		if (sys < 0) {
			INFO_WINDOW("Invalid BASIC stub for the GEOS kernal (%s)", GEOS_KERNAL_NAME);
			return 1;
		}
		cpu_pc = sys;
		inject_screencoded_message(6 * 40, "*** Basic stub, you need to wait now ***");
	} else {
		INFO_WINDOW("Invalid GEOS kernal load address ($%04X) in (%s)", addr, GEOS_KERNAL_NAME);
		return 1;
	}
	// OK. Everything seems to be so okey ...
	memcpy(memory + addr, buffer + 2, len - 2);
	return 0;
}
Beispiel #4
0
static int open_external_d81 ( const char *fn )
{
	char fnbuf[PATH_MAX + 1];
	if (!fn)
		return -1;
	d81_is_read_only = 1;
	d81fd = emu_load_file(fn, fnbuf, -1);	// get the file descriptor only ...
	if (d81fd < 0) {
		ERROR_WINDOW("External D81 image was specified (%s) but it cannot be opened: %s", fn, strerror(errno));
		DEBUG("SDCARD: cannot open external D81 image %s" NL, fn);
	} else {
		off_t d81_size;
		// try to open in R/W mode
		int tryfd = open(fnbuf, O_RDWR | O_BINARY);
		if (tryfd >= 0) {
			close(d81fd);
			d81fd = tryfd;
			DEBUG("SDCARD: exernal D81 image file re-opened in RD/WR mode, good" NL);
			d81_is_read_only = 0;
		} else {
			INFO_WINDOW("External D81 image file %s could be open only in R/O mode", fnbuf);
		}
		d81_size = lseek(d81fd, 0, SEEK_END);
		if (d81_size == (off_t)-1) {
			ERROR_WINDOW("Cannot query the size of external D81 image %s, using on-SD images! ERROR: %s", fn, strerror(errno));
			close(d81fd);
			d81fd = -1;
			return d81fd;
		}
		if (d81_size != D81_SIZE) {
			ERROR_WINDOW("Bad external D81 image size " PRINTF_LLD " for %s, should be %d bytes!", (long long)d81_size, fnbuf, D81_SIZE);
			close(d81fd);
			d81fd = -1;
			return d81fd;
		}
	}
	return d81fd;
}
Beispiel #5
0
int config_init ( int argc, char **argv )
{
	const char *config_name = DEFAULT_CONFIG_FILE;	// name of the used config file, can be overwritten via CLI
	const struct configOption_st *opt;
	const char *exe = argv[0];
	int default_config = 1;
	int testparsing = 0;
	argc--; argv++;
#ifdef __EMSCRIPTEN__
	exe = strdup("/files/emscripten-virtual-executable");
#endif
#ifdef _WIN32
	console_open_window();
#endif
	SDL_VERSION(&sdlver_compiled);
	SDL_GetVersion(&sdlver_linked);
	if (sdlver_linked.major < 2 || (sdlver_linked.minor == 0 && sdlver_linked.patch < 4)) {
		ERROR_WINDOW("Too old SDL library linked, at least version 2.0.4 is required.");
		return 1;
	}
	/* SDL info on paths */
	if (get_path_info())
		return 1;
	/* ugly hack: pre-parse comand line to find debug statement (to be worse, it does not handle single argument options too well ... */
#ifdef DISABLE_DEBUG
	printf("DEBUG: disabled at compilation time." NL);
#else
	while (testparsing < argc) {
		if (!strcmp(argv[testparsing], "-" DEBUGFILE_OPT) && testparsing != argc - 1 && strcmp(argv[testparsing + 1], "none")) {
			debug_fp = fopen(argv[testparsing + 1], "w");
			DEBUGPRINT("DEBUG: enable logging into file: %s" NL, argv[testparsing + 1]);
			if (debug_fp == NULL)
				fprintf(stderr, "Cannot open debug logging file: %s" NL, argv[testparsing + 1]);
			break;
		}
		testparsing++;
	}
	testparsing = 0;
#endif
	/* end of ugly hack */
	/* let's continue with the info block ... */
	DEBUGPRINT("%s %s v%s %s %s" NL
		"GIT %s compiled by (%s) at (%s) with (%s)-(%s)" NL
		"Platform: (%s) (%d-bit), video: (%s), audio: (%s), "
		"SDL version compiled: (%d.%d.%d) and linked: (%d.%d.%d) rev (%s)" NL NL,
		WINDOW_TITLE, DESCRIPTION, VERSION, COPYRIGHT, PROJECT_PAGE,
		XEMU_BUILDINFO_GIT, XEMU_BUILDINFO_ON, XEMU_BUILDINFO_AT, CC_TYPE, XEMU_BUILDINFO_CC,
		SDL_GetPlatform(), ARCH_BITS, SDL_GetCurrentVideoDriver(), SDL_GetCurrentAudioDriver(),
		sdlver_compiled.major, sdlver_compiled.minor, sdlver_compiled.patch,
		sdlver_linked.major, sdlver_linked.minor, sdlver_linked.patch, SDL_GetRevision()
	);
	DEBUGPRINT("PATH: executable: %s" NL, exe);
	/* SDL path info block printout */
	DEBUGPRINT("PATH: SDL base path: %s" NL, app_base_path);
	DEBUGPRINT("PATH: SDL pref path: %s" NL, app_pref_path);
#ifndef _WIN32
	DEBUGPRINT("PATH: data directory: %s/" NL, DATADIR);
#endif
	DEBUGPRINT("PATH: Current directory: %s" NL NL, current_directory);
	/* Look the very basic command line switches first */
	if (argc && is_help_request_option(argv[0])) {
		opt = configOptions;
		printf("USAGE:" NL NL
			"\t%s -optname optval -optname2 optval2 ..." NL NL "OPTIONS:" NL NL
			"-config" NL "\tUse config file (or do not use the default one, if \"none\" is specified). This must be the first option if used! [default: @config]" NL,
			exe
		);
		while (opt->name) {
			printf("-%s" NL "\t%s [default: %s]" NL, opt->name, opt->help, opt->defval ? opt->defval : "-");
			opt++;
		}
		printf(NL "%s" NL, disclaimer);
#ifdef _WIN32
		if (!console_is_open)
			ERROR_WINDOW("Could not dump help, since console couldn't be allocated.");
#endif
		XEMUEXIT(0);
	}
	DEBUGPRINT("%s" NL NL, disclaimer);
	if (argc && !strcasecmp(argv[0], "-testparsing")) {
		testparsing = 1;
		argc--; argv++;
	}
	if (argc & 1) {
		fprintf(stderr, "FATAL: Bad command line: should be even number of parameters (two for an option as key and its value)" NL);
		return 1;
	}
	if (argc > 1 && !strcmp(argv[0], "-config")) {
		default_config = 0;
		config_name = argv[1];
		argc -= 2;
		argv += 2;
	}
	/* Set default (built-in) values */
	opt = configOptions;
	while (opt->name) {
		if (opt->defval)
			config_set_internal(opt->name, -1, opt->defval);
		opt++;
	}
	config_set_internal("rom", 0, COMBINED_ROM_FN);	// set default "combined" ROM image set (from segment 0, starting with EXOS)
	/* Default values for the keyboard follows ... */
	keymap_preinit_config_internal();
	/* check if we have written sample config file, if there is not, let's create one */
	save_sample_config(DEFAULT_CONFIG_SAMPLE_FILE);
	/* now parse config file (not the sample one!) if there is any */
	if (strcasecmp(config_name, "none")) {
		char path[PATH_MAX + 1];
		FILE *f = open_emu_file(config_name, "r", path);
		DEBUGPRINT("CONFIG: config file: %s (%s)" NL, config_name, f ? path : "*** CANNOT OPEN, NOT USING CONFIG FILE ***");
		if (f) {
			if (load_config_file_stream(f, path)) {
				fclose(f);
				return 1;
			}
			fclose(f);
		} else if (!default_config) {
			fprintf(stderr, "FATAL: Cannot open requested config file: %s" NL, config_name);
			return 1;
		} else
			DEBUGPRINT("CONFIG: Skipping default config file (cannot open), using built-in defaults." NL);
	} else
		DEBUGPRINT("CONFIG: Using config file: DISABLED in command line" NL);
	/* parse command line ... */
	if (parse_command_line(argc, argv))
		return -1;
	/* open debug file, if it was not requested via command line at the beginning ... */
	if (!debug_fp && strcmp(config_getopt_str(DEBUGFILE_OPT), "none")) {
		debug_fp = fopen(config_getopt_str(DEBUGFILE_OPT), "w");
		DEBUGPRINT("DEBUG: enable logging into file: %s" NL, config_getopt_str(DEBUGFILE_OPT));
		if (!debug_fp)
                	ERROR_WINDOW("Cannot open debug messages log file requested: %s", config_getopt_str(DEBUGFILE_OPT));
	}
	if (debug_fp)
		INFO_WINDOW("DEBUG: Debug messages logging is active");
	else
		printf("DEBUG: No debug messages logging is active." NL);
	/* test parsing mode? */
	if (testparsing) {
		printf(NL "--- TEST DUMP OF *PARSED* CONFIGURATION (requested)" NL NL);
		dump_config(stdout);
		printf(NL "--- END OF TEST PARSING MODE (requested)" NL);
		XEMUEXIT(0);
	}
	DEBUG("CONFIG: End of configuration step." NL NL);
	/* Close console, unless user requested it with the -console option */
#ifdef _WIN32
	if (!config_getopt_int("console"))
		console_close_window();
#else
	if (config_getopt_int("console"))
		console_open_window();	// on non-windows, it only will mark console as open for monitor to be used ..
#endif
	return 0;
}
Beispiel #6
0
static int download_file_by_db ( const char *filename, const char *storepath )
{
	char *p;
	int i;
	if (!xemu_installer_db)
		return -1;
	strcpy(installer_store_to, storepath);
	p = xemu_installer_db;
	i = strlen(filename);
	while (*p) {
		while (*p && *p <= 32)
			p++;
		if (!strncmp(filename, p, i) && (p[i] == '\t' || p[i] == ' ')) {
			p += i + 1;
			while (*p == ' ' || *p == '\t')
				p++;
			if (*p > 32) {
				long int sizereq;
				char *q;
				if (strncasecmp(p, "http://", 7) && strncasecmp(p, "https://", 8) && strncasecmp(p, "ftp://", 6)) {
					ERROR_WINDOW("Bad download descriptor file at URL field (bar protocol) for record \"%s\"", filename);
					return -1;
				}
				q = installer_fetch_url;
				sizereq = 0;
				while (*p > 32) {
					if (sizereq == sizeof(installer_fetch_url) - 2) {
						ERROR_WINDOW("Bad download descriptor file at URL field (too long) for record \"%s\"", filename);
						return -1;
					}
					*q++ = *p++;
					sizereq++;
				}
				*q = 0;
				sizereq = strtol(p, &p, 0);
				if (*p > 32)
					sizereq = -1;
				if (sizereq > 0 && sizereq <= 4194304) {
					int ret;
					char msgbuffer[sizeof(installer_fetch_url) + 256];
					if (legal_warning) {
						INFO_WINDOW("Legal-warning blah-blah ...");
						legal_warning = 0;
					}
					sprintf(msgbuffer, "Downloading file \"%s\". Do you agree?\nSource: %s", filename, installer_fetch_url);
					if (QUESTION_WINDOW("YES|NO", msgbuffer))
						return -1;
					ret = download_file(sizereq);
					if (!ret)
						INFO_WINDOW("File %s seems to be downloaded nicely with %s", filename, *downloader_utility_spec_start_p);
					return ret;
				} else {
					ERROR_WINDOW("Bad download descriptor file at size field for record \"%s\" (or this file is not auto-installable)", filename);
					return -1;
				}
			}
		}
		while (*p && *p != '\n' && *p != '\r')
			p++;
	}
	DEBUGPRINT("INSTALLER: file-key %s cannot be found in the download description file" NL, filename);
	return -1;
}
Beispiel #7
0
/* This function also re-initializes the whole memory! Do not call it after you defined RAM for the system, but only before! */
int roms_load ( void )
{
	int seg, last = 0;
	char path[PATH_MAX + 1];
	if (reloading)	// in case of already defined (reloading) memory model, we want to back our SRAM segments up - if any at all ...
		sram_save_all_segments();
	for (seg = 0; seg < 0x100; seg++ ) {
		memory_segment_map[seg] = (seg >= 0xFC ? VRAM_SEGMENT : UNUSED_SEGMENT);	// 64K VRAM is default, you cannot override that!
		if (reloading && rom_name_tab[seg])
			free((void*)rom_name_tab[seg]); // already defined (reloading) situation, we want to free used memory as well
		rom_name_tab[seg] = NULL;
	}
	reloading = 1;	// set reloading flag, in next invocation of roms_load(), it will be done in config reload mode!
	memset(memory, 0xFF, 0x400000);
	xep_rom_seg = -1;
	for (seg = 0; seg < 0x100; seg++ ) {
		void *option = config_getopt("rom", seg, NULL);
		if (option) {
			const char *name;
			int lseg = seg;
			FILE *f;
			config_getopt_pointed(option, &name);
			if (!strcasecmp(name, "XEP") && seg) {
				if (memory_segment_map[seg] == UNUSED_SEGMENT) {
					DEBUG("CONFIG: ROM: segment %02Xh assigned to internal XEP ROM" NL, seg);
					xep_rom_seg = seg;
					memory_segment_map[seg] = XEPROM_SEGMENT;
				} else
					ERROR_WINDOW("XEP ROM forced segment assignment cannot be done since segment %02X is not unused", seg);
				continue;
			}
			DEBUG("CONFIG: ROM: segment %02Xh file %s" NL, seg, name);
			f = open_emu_file(name, "rb", path);
			if (f == NULL) {
				ERROR_WINDOW("Cannot open ROM image \"%s\" (to be used from segment %02Xh): %s", name, seg, ERRSTR());
				if (!strcmp(name, COMBINED_ROM_FN)) { // this should be the auto-install functionality, with downloading stuff?
				}
				return -1;
			}
			DEBUG("CONFIG: ROM: ... file path is %s" NL, path);
			rom_name_tab[seg] = SDL_strdup(path);
			CHECK_MALLOC(rom_name_tab[seg]);
			for (;;) {
				int ret;
				// Note: lseg overflow is not needed to be tested, as VRAM marks will stop reading of ROM image in the worst case ...
				if (memory_segment_map[lseg] != UNUSED_SEGMENT) {
					fclose(f);
					forget_emu_file(path);
					ERROR_WINDOW("While reading ROM image \"%s\" into segment %02Xh: already used segment (\"%s\")!", path, lseg, memory_segment_map[lseg]);
					return -1;
				}
				ret = fread(memory + (lseg << 14), 1, 0x4000, f);
				if (ret)
					DEBUG("CONFIG: ROM: ... trying read 0x4000 bytes in segment %02Xh, result is %d" NL, lseg, ret);
				if (ret < 0) {
					ERROR_WINDOW("Cannot read ROM image \"%s\" (to be used in segment %02Xh): %s", path, lseg, ERRSTR());
					fclose(f);
					forget_emu_file(path);
					return -1;
				} else if (ret == 0) {
					if (lseg == seg) {
						fclose(f);
						forget_emu_file(path);
						ERROR_WINDOW("Null-sized ROM image \"%s\" (to be used in segment %02Xh).", path, lseg);
						return -1;
					}
					break;
				} else if (ret != 0x4000) {
					fclose(f);
					forget_emu_file(path);
					ERROR_WINDOW("Bad ROM image \"%s\": not multiple of 16K bytes!", path);
					return -1;
				}
				// check if ROM image contains XEP128_ROM segment signature, if so, try to use XEP ROM from here
				if (!memcmp(memory + (lseg << 14), "XEP__ROM", 8) && xep_rom_seg == -1) {
					xep_rom_seg = lseg;
					memory_segment_map[lseg] = XEPROM_SEGMENT;
				} else
					memory_segment_map[lseg] = ROM_SEGMENT;
				if (lseg > last)
					last = lseg;
				if (ret != 0x4000)
					break;
				lseg++;
			}
			fclose(f);
			forget_emu_file(path);
		} else if (!seg) {
			ERROR_WINDOW("Fatal ROM image error: No ROM defined for segment 00h, no EXOS is requested!");
			return -1;
		}
	}
	/* XEP ROM: guess where to place it, or disable it ... */
	if (config_getopt_int("xeprom")) {
		// XEP ROM is enabled with 'xeprom' directive
		if (xep_rom_seg == -1) {	// not assigned manually, try to find a place for it ...
			xep_rom_seg = last + 1;	// ... with simply using the segment after the last used ROM segment
			DEBUGPRINT("CONFIG: ROM: automatic XEP ROM image placer selected segment is %02Xh" NL, xep_rom_seg);
		}
	} else {
		// XEP ROM is disabled (with 'xeprom' directive), _IF_ it was not assigned manually
		if (xep_rom_seg == -1) {
			DEBUGPRINT("CONFIG: ROM: XEP ROM is disabled by configuration!" NL);
			INFO_WINDOW("XEP internal ROM image is disabled by configuration.\nXep128 will work, but no XEP feature will be available.");
		}
	}
	/* XEP ROM: now install our internal ROM, if it's allowed/OK to do so */
	if (xep_rom_seg > 0) {
		if (memory_segment_map[xep_rom_seg] == UNUSED_SEGMENT || memory_segment_map[xep_rom_seg] == XEPROM_SEGMENT) {
			xep_rom_addr = xep_rom_seg << 14;
			memset(memory + xep_rom_addr, 0, 0x4000);
			memcpy(memory + xep_rom_addr, xep_rom_image, sizeof xep_rom_image);
			memory_segment_map[xep_rom_seg] = XEPROM_SEGMENT;
			xep_set_default_device_name(NULL);
			DEBUGPRINT("CONFIG: ROM: XEP internal ROM image has been installed in segment %02Xh" NL, xep_rom_seg);
		} else {
			DEBUGPRINT("CONFIG: ROM: XEP internal ROM image CANNOT be installed because segment %02Xh is used!!" NL, xep_rom_seg);
			ERROR_WINDOW("XEP internal ROM image cannot be installed.\nXep128 will work, but no XEP feature will be available.");
			xep_rom_seg = -1;
		}
	} else
		xep_rom_seg = -1;
	return 0;
}