Пример #1
0
static void Init_SDL_Joysticks(int first, int second)
{
	if (first) {
		joystick0 = SDL_JoystickOpen(0);
		if (joystick0 == NULL)
			Log_print("joystick 0 not found");
		else {
			Log_print("joystick 0 found!");
			joystick0_nbuttons = SDL_JoystickNumButtons(joystick0);
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
			if (joystick0_nbuttons > OSK_MAX_BUTTONS)
				joystick0_nbuttons = OSK_MAX_BUTTONS;
#endif
		}
	}

	if (second) {
		joystick1 = SDL_JoystickOpen(1);
		if (joystick1 == NULL)
			Log_print("joystick 1 not found");
		else {
			Log_print("joystick 1 found!");
			joystick1_nbuttons = SDL_JoystickNumButtons(joystick1);
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
			if (joystick1_nbuttons > OSK_MAX_BUTTONS)
				joystick1_nbuttons = OSK_MAX_BUTTONS;
#endif
		}
	}
}
Пример #2
0
int VIDEOMODE_InitialiseDisplay(void)
{
	/* PLATFORM_Initialise must be called earlier! */
	resolutions = PLATFORM_AvailableResolutions(&resolutions_size);
	if (resolutions == NULL) {
		Log_print("Fatal error: System reports no display resolutions available");
		return FALSE;
	}

	qsort(resolutions, resolutions_size, sizeof(VIDEOMODE_resolution_t), &CompareResolutions);
	RemoveDuplicateResolutions();
	if (resolutions_size == 0) {
		Log_print("Fatal error: System reports no resolution higher than minimal %ux%u available",
		          display_modes[0].min_w, display_modes[0].min_h);
		return FALSE;
	}

	/* Find the resolution from config file/command line in RESOLUTIONS. */
	for (current_resolution = 0; current_resolution < resolutions_size; current_resolution ++) {
		if (resolutions[current_resolution].width >= init_fs_resolution.width &&
		    resolutions[current_resolution].height >= init_fs_resolution.height)
			break;
	}
	if (current_resolution >= resolutions_size) {
		/* No resolution found, using the biggest one. */
		current_resolution = resolutions_size - 1;
		Log_print("Requested resolution %ux%u is too big, using %ux%u instead.",
		          init_fs_resolution.width, init_fs_resolution.height,
		          resolutions[current_resolution].width, resolutions[current_resolution].height);
	} else if (resolutions[current_resolution].width != init_fs_resolution.width ||
	           resolutions[current_resolution].height != init_fs_resolution.height)
		Log_print("Requested resolution %ux%u is not available, using %ux%u instead.",
		          init_fs_resolution.width, init_fs_resolution.height,
		          resolutions[current_resolution].width, resolutions[current_resolution].height);
	/* Autodetect host display aspect ratio if requested. */
	if (VIDEOMODE_host_aspect_ratio_w == 0.0 || VIDEOMODE_host_aspect_ratio_h == 0.0)
		AutodetectHostAspect(&VIDEOMODE_host_aspect_ratio_w, &VIDEOMODE_host_aspect_ratio_h);

	UpdateTvSystemSettings();
	if (!VIDEOMODE_Update()) {
		Log_print("Fatal error: Cannot initialise video");
		return FALSE;
	}
#if SUPPORTS_PLATFORM_PALETTEUPDATE
	PLATFORM_PaletteUpdate();
#endif
	return TRUE;
}
Пример #3
0
void Log_print(struct Log* log,
               enum Log_Level logLevel,
               const char* file,
               int line,
               const char* format,
               ...)
{
    static int inLogger;
    static int droppedMessages;
    if (inLogger++) {
        // return prevent stack overflow.
        droppedMessages++;
        return;
    }

    va_list args;
    va_start(args, format);
    log->print(log, logLevel, file, line, format, args);
    va_end(args);

    inLogger--;

    if (droppedMessages && !inLogger) {
        Log_print(log, Log_Level_INFO, __FILE__, __LINE__, "There were [%d] dropped log messages.",
                  droppedMessages);
        droppedMessages = 0;
    }
}
Пример #4
0
static void init_mio(void)
{
	free(mio_rom);
	mio_rom = (UBYTE *)Util_malloc(mio_rom_size);
	if (!Atari800_LoadImage(mio_rom_filename, mio_rom, mio_rom_size)) {
		free(mio_rom);
		mio_rom = NULL;
		return;
	}
	D(printf("Loaded mio rom image\n"));
	PBI_MIO_enabled = TRUE;
	if (PBI_SCSI_disk != NULL) fclose(PBI_SCSI_disk);
	if (!Util_filenamenotset(mio_scsi_disk_filename)) {
		PBI_SCSI_disk = fopen(mio_scsi_disk_filename, "rb+");
		if (PBI_SCSI_disk == NULL) {
			Log_print("Error opening SCSI disk image:%s", mio_scsi_disk_filename);
		}
		else {
			D(printf("Opened SCSI disk image\n"));
			mio_scsi_enabled = TRUE;
		}
	}
	if (!mio_scsi_enabled) {
		PBI_SCSI_BSY = TRUE; /* makes MIO give up easier */
	}
	free(mio_ram);
	mio_ram = (UBYTE *)Util_malloc(mio_ram_size);
	memset(mio_ram, 0, mio_ram_size);
}
Пример #5
0
int main(int argc, char **argv)
{
#if HAVE_WINDOWS_H
	/* Handle Windows console signals myself. If not, then closing
	   the console window would cause emulator crash due to the sound
	   subsystem being active. */
	if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
		Log_print("ERROR: Could not set console control handler");
		return 1;
	}
#endif /* HAVE_WINDOWS_H */

	/* initialise Atari800 core */
	if (!Atari800_Initialise(&argc, argv))
		return 3;

	/* main loop */
	for (;;) {
		INPUT_key_code = PLATFORM_Keyboard();
		SDL_INPUT_Mouse();
		Atari800_Frame();
		if (Atari800_display_screen)
			PLATFORM_DisplayScreen();
	}
}
Пример #6
0
void PLATFORM_Initialise(int *argc, char *argv[])
{
    int i, j;
    int help_only = FALSE;
    int scale = 2;
    for (i = j = 1; i < *argc; i++) {
        if (strcmp(argv[i], "-scale") == 0) {
            scale = Util_sscandec(argv[++i]);
        }
        else {
            if (strcmp(argv[i], "-help") == 0) {
                help_only = TRUE;
                Log_print("\t-scale <n>       Scale width and height by <n>");
            }
            argv[j++] = argv[i];
        }
    }
    *argc = j;

    if(!help_only) {
        int config[JAVANVM_InitGraphicsSIZE];
        config[JAVANVM_InitGraphicsScalew] = scale;
        config[JAVANVM_InitGraphicsScaleh] = scale;
        config[JAVANVM_InitGraphicsScreen_WIDTH] = Screen_WIDTH;
        config[JAVANVM_InitGraphicsScreen_HEIGHT] = Screen_HEIGHT;
        config[JAVANVM_InitGraphicsATARI_VISIBLE_WIDTH] = 336;
        config[JAVANVM_InitGraphicsATARI_LEFT_MARGIN] = 24;
        JAVANVM_InitGraphics((void *)&config[0]);
        JAVANVM_InitPalette((void *)&Colours_table[0]);
#ifdef SOUND
        SoundSetup();
#endif
    }
    return;
}
Пример #7
0
void SDL_VIDEO_InitSDL(void)
{
	if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
			Log_print("SDL_INIT_VIDEO FAILED: %s", SDL_GetError());
			Log_flushlog();
			exit(-1);
	}
	/* SDL_WM_SetIcon("/usr/local/atari800/atarixe.ICO"), NULL); */
	SDL_WM_SetCaption(Atari800_TITLE, "Atari800");

	/* Get the desktop resolution */
	{
		SDL_VideoInfo const * const info = SDL_GetVideoInfo();
		desktop_resolution.width = info->current_w;
		desktop_resolution.height = info->current_h;
		SDL_VIDEO_native_bpp = info->vfmt->BitsPerPixel;
	}

#if HAVE_OPENGL
	SDL_VIDEO_GL_InitSDL();
	if (!SDL_VIDEO_opengl_available)
		currently_opengl = SDL_VIDEO_opengl = FALSE;
#endif

	SDL_EnableUNICODE(1);
}
Пример #8
0
static void GetGZErrorText(void)
{
#ifdef GZERROR
	const char *error = GZERROR(StateFile, &nFileError);
	if (nFileError == Z_ERRNO) {
#ifdef HAVE_STRERROR
		Log_print("The following general file I/O error occurred:");
		Log_print(strerror(errno));
#else
		Log_print("A file I/O error occurred");
#endif
		return;
	}
	Log_print("ZLIB returned the following error: %s", error);
#endif /* GZERROR */
	Log_print("State file I/O failed.");
}
Пример #9
0
int Atari800_LoadImage(const char *filename, UBYTE *buffer, int nbytes)
{
	FILE *f;
	int len;

	f = fopen(filename, "rb");
	if (f == NULL) {
		Log_print("Error loading ROM image: %s", filename);
		return FALSE;
	}
	len = fread(buffer, 1, nbytes, f);
	fclose(f);
	if (len != nbytes) {
		Log_print("Error reading %s", filename);
		return FALSE;
	}
	return TRUE;
}
Пример #10
0
void Android_SoundInit(int rate, int bufsizems, int bit16, int hq, int disableOSL)
{
	Log_print("SoundInit for android initializing with %dHz, %d bufsize, OSL %s",
				rate, bufsizems, (disableOSL) ? "off" : "on");
	POKEYSND_bienias_fix = 0;
	POKEYSND_enable_new_pokey = hq;
	at_sixteenbit = bit16;
	snd_bufsizems = bufsizems;
	snd_mixrate = rate;
	osl_bufnum = snd_bufsizems / OSL_BUFSIZE_MS;
	osl_bufszbytes = OSL_BUFSIZE_MS * (at_sixteenbit ? 2 : 1) * snd_mixrate / 1000;
	osl_disable = disableOSL;
	if (disableOSL)
		Android_osl_sound = FALSE;
	Log_print("Initializing POKEY");
	POKEYSND_Init(POKEYSND_FREQ_17_EXACT, rate, 1, bit16 ? POKEYSND_BIT16 : 0);
	Log_print("POKEY init done");
}
Пример #11
0
void Screen_Initialise(int *argc, char *argv[])
{
	int i;
	int j;
	int help_only = FALSE;

	for (i = j = 1; i < *argc; i++) {
		if (strcmp(argv[i], "-screenshots") == 0) {
			Screen_SetScreenshotFilenamePattern(argv[++i]);
		}
		if (strcmp(argv[i], "-showspeed") == 0) {
			Screen_show_atari_speed = TRUE;
		}
		else {
			if (strcmp(argv[i], "-help") == 0) {
				help_only = TRUE;
				Log_print("\t-screenshots <p> Set filename pattern for screenshots");
				Log_print("\t-showspeed       Show percentage of actual speed");
			}
			argv[j++] = argv[i];
		}
	}
	*argc = j;

	/* don't bother mallocing Screen_atari with just "-help" */
	if (help_only)
		return;

	if (Screen_atari == NULL) { /* platform-specific code can initialize it in theory */
		Screen_atari = (ULONG *) Util_malloc(Screen_HEIGHT * Screen_WIDTH);
		memset(Screen_atari, 0, (Screen_HEIGHT * Screen_WIDTH));
#ifdef DIRTYRECT
		Screen_dirty = (UBYTE *) Util_malloc(Screen_HEIGHT * Screen_WIDTH / 8);
		memset(Screen_dirty, 0, (Screen_HEIGHT * Screen_WIDTH));
		Screen_EntireDirty();
#endif
#ifdef BITPL_SCR
		Screen_atari_b = (ULONG *) Util_malloc(Screen_HEIGHT * Screen_WIDTH);
		memset(Screen_atari_b, 0, (Screen_HEIGHT * Screen_WIDTH));
		Screen_atari1 = Screen_atari;
		Screen_atari2 = Screen_atari_b;
#endif
	}
}
Пример #12
0
int AFILE_OpenFile(const char *filename, int reboot, int diskno, int readonly)
{
	int type = AFILE_DetectFileType(filename);
	switch (type) {
	case AFILE_ATR:
	case AFILE_ATX:
	case AFILE_XFD:
	case AFILE_ATR_GZ:
	case AFILE_XFD_GZ:
	case AFILE_DCM:
	case AFILE_PRO:
		if (!SIO_Mount(diskno, filename, readonly))
			return AFILE_ERROR;
		if (reboot)
			Atari800_Coldstart();
		break;
	case AFILE_XEX:
	case AFILE_BAS:
	case AFILE_LST:
		if (!BINLOAD_Loader(filename))
			return AFILE_ERROR;
		break;
	case AFILE_CART:
	case AFILE_ROM:
		/* TODO: select format for ROMs; switch 5200 ? */
		if (CARTRIDGE_Insert(filename) != 0)
			return AFILE_ERROR;
		if (reboot)
			Atari800_Coldstart();
		break;
	case AFILE_CAS:
	case AFILE_BOOT_TAPE:
		if (!CASSETTE_Insert(filename))
			return AFILE_ERROR;
		if (reboot) {
			CASSETTE_hold_start = TRUE;
			Atari800_Coldstart();
		}
		break;
	case AFILE_STATE:
	case AFILE_STATE_GZ:
#ifdef BASIC
		Log_print("State files are not supported in BASIC version");
		return AFILE_ERROR;
#else
		if (!StateSav_ReadAtariState(filename, "rb"))
			return AFILE_ERROR;
		/* Don't press Option */
		GTIA_consol_table[1] = GTIA_consol_table[2] = 0xf;
		break;
#endif
	default:
		break;
	}
	return type;
}
Пример #13
0
void StateSav_ReadFNAME(char *filename)
{
	UWORD namelen = 0;

	StateSav_ReadUWORD(&namelen, 1);
	if (namelen >= FILENAME_MAX) {
		Log_print("Filenames of %d characters not supported on this platform", (int) namelen);
		return;
	}
	StateSav_ReadUBYTE((UBYTE *) filename, namelen);
	filename[namelen] = 0;
}
Пример #14
0
static void Init_SDL_Joysticks(int first, int second)
{
	if (first) {
		joystick0 = SDL_JoystickOpen(0);
		if (joystick0 == NULL)
			Log_print("joystick 0 not found");
		else {
			Log_print("joystick 0 found!");
			joystick0_nbuttons = SDL_JoystickNumButtons(joystick0);
		}
	}

	if (second) {
		joystick1 = SDL_JoystickOpen(1);
		if (joystick1 == NULL)
			Log_print("joystick 1 not found");
		else {
			Log_print("joystick 1 found!");
			joystick1_nbuttons = SDL_JoystickNumButtons(joystick1);
		}
	}
}
Пример #15
0
/* Read a word from file */
static int read_word(void)
{
	UBYTE buf[2];
	if (fread(buf, 1, 2, BINLOAD_bin_file) != 2) {
		fclose(BINLOAD_bin_file);
		BINLOAD_bin_file = NULL;
		if (BINLOAD_start_binloading) {
			BINLOAD_start_binloading = FALSE;
			Log_print("binload: not valid BIN file");
			return -1;
		}
		CPU_regPC = MEMORY_dGetWordAligned(0x2e0);
		return -1;
	}
	return buf[0] + (buf[1] << 8);
}
Пример #16
0
static void UpdateModeDependentPointers(int tv_mode)
{
	/* Set pointers to the current setup and external palette. */
	if (tv_mode == Atari800_TV_NTSC) {
		Colours_setup = &COLOURS_NTSC_setup;
		Colours_external = &COLOURS_NTSC_external;
	}
       	else if (tv_mode == Atari800_TV_PAL) {
		Colours_setup = &COLOURS_PAL_setup;
		Colours_external = &COLOURS_PAL_external;
	}
	else {
		Atari800_ErrExit();
		Log_print("Interal error: Invalid Atari800_tv_mode\n");
		exit(1);
	}
}
Пример #17
0
int PBI_MIO_Initialise(int *argc, char *argv[])
{
	int i, j;
	for (i = j = 1; i < *argc; i++) {
		if (strcmp(argv[i], "-mio") == 0) {
			init_mio();
		}
		else {
		 	if (strcmp(argv[i], "-help") == 0) {
				Log_print("\t-mio             Emulate the ICD MIO board");
			}
			argv[j++] = argv[i];
		}
	}
	*argc = j;

	return TRUE;
}
Пример #18
0
int PLATFORM_Initialise(int *argc, char *argv[])
{
	int i, j;
	int help_only = FALSE;

	for (i = j = 1; i < *argc; i++) {
		if (strcmp(argv[i], "-help") == 0) {
			help_only = TRUE;
		}
		argv[j++] = argv[i];
	}
	*argc = j;

	if (!help_only) {
		i = SDL_INIT_JOYSTICK
#ifdef SOUND
		    | SDL_INIT_AUDIO
#endif
#if HAVE_WINDOWS_H
/* Timers are used to avoid one Windows 7 glitch, see src/sdl/input.c */
		    | SDL_INIT_TIMER
#endif /* HAVE_WINDOWS_H */
		;
		if (SDL_Init(i) != 0) {
			Log_print("SDL_Init FAILED: %s", SDL_GetError());
			Log_flushlog();
			exit(-1);
		}
		atexit(SDL_Quit);
	}

	if (!SDL_VIDEO_Initialise(argc, argv)
#ifdef SOUND
	    || !SDL_SOUND_Initialise(argc, argv)
#endif
	    || !SDL_INPUT_Initialise(argc, argv))
		return FALSE;

	return TRUE;
}
Пример #19
0
/* converts "foo%bar##.pcx" to "foo%%bar%02d.pcx" */
static void Screen_SetScreenshotFilenamePattern(const char *p)
{
	char *f = screenshot_filename_format;
	char no_width = '0';
	screenshot_no_max = 1;
	/* 9 because sprintf'ed "no" can be 9 digits */
	while (f < screenshot_filename_format + FILENAME_MAX - 9) {
		/* replace a sequence of hashes with e.g. "%05d" */
		if (*p == '#') {
			if (no_width > '0') /* already seen a sequence of hashes */
				break;          /* invalid */
			/* count hashes */
			do {
				screenshot_no_max *= 10;
				p++;
				no_width++;
				/* now no_width is the number of hashes seen so far
				   and p points after the counted hashes */
			} while (no_width < '9' && *p == '#'); /* no more than 9 hashes */
			*f++ = '%';
			*f++ = '0';
			*f++ = no_width;
			*f++ = 'd';
			continue;
		}
		if (*p == '%')
			*f++ = '%'; /* double the percents */
		*f++ = *p;
		if (*p == '\0')
			return; /* ok */
		p++;
	}
	Log_print("Invalid filename pattern for screenshots, using default.");
	strcpy(screenshot_filename_format, DEFAULT_SCREENSHOT_FILENAME_FORMAT);
	screenshot_no_max = 1000;
}
Пример #20
0
int AFILE_OpenFile(const char *filename, int reboot, int diskno, int readonly)
{
	int type = AFILE_DetectFileType(filename);
	switch (type) {
	case AFILE_ATR:
	case AFILE_ATX:
	case AFILE_XFD:
	case AFILE_ATR_GZ:
	case AFILE_XFD_GZ:
	case AFILE_DCM:
	case AFILE_PRO:
		if (!SIO_Mount(diskno, filename, readonly))
			return AFILE_ERROR;
		if (reboot)
			Atari800_Coldstart();
		break;
	case AFILE_XEX:
	case AFILE_BAS:
	case AFILE_LST:
		if (!BINLOAD_Loader(filename))
			return AFILE_ERROR;
		break;
	case AFILE_CART:
	case AFILE_ROM:
		{
			int r;
			if (reboot)
				r = CARTRIDGE_InsertAutoReboot(filename);
			else
				r = CARTRIDGE_Insert(filename);
			switch (r) {
			case CARTRIDGE_CANT_OPEN:
			case CARTRIDGE_BAD_FORMAT:
				return AFILE_ERROR;
			case CARTRIDGE_BAD_CHECKSUM:
			case 0:
				/* ok */
				break;
			default:
#ifdef BASIC
				Log_print("Raw cartridge images are not supported in BASIC version.");
				return AFILE_ERROR;
#else /* BASIC */
				/* r > 0 */
#ifndef ANDROID
				CARTRIDGE_SetTypeAutoReboot(&CARTRIDGE_main, UI_SelectCartType(r));
#else
				return (r << 8) | AFILE_ROM;
#endif /* ANDROID */
				break;
#endif /* BASIC */
			}
		}
		break;
	case AFILE_CAS:
	case AFILE_BOOT_TAPE:
		if (!CASSETTE_Insert(filename))
			return AFILE_ERROR;
		if (reboot) {
			CASSETTE_hold_start = TRUE;
			Atari800_Coldstart();
		}
		break;
	case AFILE_STATE:
	case AFILE_STATE_GZ:
#ifdef BASIC
		Log_print("State files are not supported in BASIC version");
		return AFILE_ERROR;
#else
		if (!StateSav_ReadAtariState(filename, "rb"))
			return AFILE_ERROR;
		/* Don't press Start nor Option */
		GTIA_consol_override = 0;
		break;
#endif
	default:
		break;
	}
	return type;
}
Пример #21
0
int PLATFORM_Keyboard(void)
{
	int shiftctrl = 0;
	SDL_Event event;

#if HAVE_WINDOWS_H
	/* Used to delay resize events on Windows 7, see above. */
	enum { RESIZE_INTERVAL = 500 };
	static int resize_delayed = FALSE;
	static int resize_needed = FALSE;
	static int resize_w, resize_h;
#endif /* HAVE_WINDOWS_H */

	/* Very ugly fix for SDL CAPSLOCK brokenness.  This will let the user
	 * press CAPSLOCK and get a brief keypress on the Atari but it is not
	 * possible to emulate holding down CAPSLOCK for longer periods with
	 * the broken SDL*/
	if (lastkey == SDLK_CAPSLOCK) {
		lastkey = SDLK_UNKNOWN;
	   	key_pressed = 0;
 		lastuni = 0;
	}

	if (SDL_PollEvent(&event)) {
		switch (event.type) {
		case SDL_KEYDOWN:
			lastkey = event.key.keysym.sym;
 			lastuni = event.key.keysym.unicode;
			key_pressed = 1;
			break;
		case SDL_KEYUP:
			lastkey = event.key.keysym.sym;
 			lastuni = 0; /* event.key.keysym.unicode is not defined for KEYUP */
			key_pressed = 0;
			/* ugly hack to fix broken SDL CAPSLOCK*/
			/* Because SDL is only sending Keydown and keyup for every change
			 * of state of the CAPSLOCK status, rather than the actual key.*/
			if(lastkey == SDLK_CAPSLOCK) {
				key_pressed = 1;
			}
			break;
		case SDL_VIDEORESIZE:
#if HAVE_WINDOWS_H
			/* Delay resize events on Windows 7, see above. */
			if (resize_delayed) {
				resize_w = event.resize.w;
				resize_h = event.resize.h;
				resize_needed = TRUE;
			} else {
				VIDEOMODE_SetWindowSize(event.resize.w, event.resize.h);
				resize_delayed = TRUE;
				if (SDL_AddTimer(RESIZE_INTERVAL, &ResizeDelayCallback, NULL) == NULL) {
					Log_print("Error: SDL_AddTimer failed: %s", SDL_GetError());
					Log_flushlog();
					exit(-1);
				}
			}
#else
			VIDEOMODE_SetWindowSize(event.resize.w, event.resize.h);
#endif /* HAVE_WINDOWS_H */
			break;
		case SDL_VIDEOEXPOSE:
			/* When window is "uncovered", and we are in the emulator's menu,
			   we need to refresh display manually. */
			PLATFORM_DisplayScreen();
			break;
		case SDL_QUIT:
			return AKEY_EXIT;
			break;
#if HAVE_WINDOWS_H
		case SDL_USEREVENT:
			/* Process delayed video resize on Windows 7, see above. */
			if (event.user.code == USER_EVENT_RESIZE_DELAY) {
				if (resize_needed) {
					SDL_Event events[1];
					resize_needed = FALSE;
					/* If there's a resize event in the queue,
					   wait for it and don't resize now. */
					if (SDL_PeepEvents(events, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_VIDEORESIZE)) != 0)
						resize_delayed = FALSE;
					else {
						VIDEOMODE_SetWindowSize(resize_w, resize_h);
						if (SDL_AddTimer(RESIZE_INTERVAL, &ResizeDelayCallback, NULL) == NULL) {
							Log_print("Error: SDL_AddTimer failed: %s", SDL_GetError());
							Log_flushlog();
							exit(-1);
						}
					}
				} else
					resize_delayed = FALSE;
			}
			break;
#endif /* HAVE_WINDOWS_H */
		}
	}
	else if (!key_pressed)
		return AKEY_NONE;

	kbhits = SDL_GetKeyState(NULL);

	if (kbhits == NULL) {
		Log_print("oops, kbhits is NULL!");
		Log_flushlog();
		exit(-1);
	}

	UI_alt_function = -1;
	if (kbhits[SDLK_LALT]) {
		if (key_pressed) {
			switch (lastkey) {
			case SDLK_f:
				key_pressed = 0;
				VIDEOMODE_ToggleWindowed();
				break;
			case SDLK_x:
				if (INPUT_key_shift) {
					key_pressed = 0;
					VIDEOMODE_Toggle80Column();
				}
				break;
			case SDLK_g:
				key_pressed = 0;
				VIDEOMODE_ToggleHorizontalArea();
				break;
			case SDLK_j:
				key_pressed = 0;
				SwapJoysticks();
				break;
			case SDLK_r:
				UI_alt_function = UI_MENU_RUN;
				break;
			case SDLK_y:
				UI_alt_function = UI_MENU_SYSTEM;
				break;
			case SDLK_o:
				UI_alt_function = UI_MENU_SOUND;
				break;
			case SDLK_w:
				UI_alt_function = UI_MENU_SOUND_RECORDING;
				break;
			case SDLK_a:
				UI_alt_function = UI_MENU_ABOUT;
				break;
			case SDLK_s:
				UI_alt_function = UI_MENU_SAVESTATE;
				break;
			case SDLK_d:
				UI_alt_function = UI_MENU_DISK;
				break;
			case SDLK_l:
				UI_alt_function = UI_MENU_LOADSTATE;
				break;
			case SDLK_c:
				UI_alt_function = UI_MENU_CARTRIDGE;
				break;
			case SDLK_BACKSLASH:
				return AKEY_PBI_BB_MENU;
			case SDLK_m:
				grab_mouse = !grab_mouse;
				SDL_WM_GrabInput(grab_mouse ? SDL_GRAB_ON : SDL_GRAB_OFF);
				key_pressed = 0;
				break;
			case SDLK_1:
				key_pressed = 0;
				if (Atari800_tv_mode == Atari800_TV_NTSC) {
					if (kbhits[SDLK_LSHIFT]) {
						if (COLOURS_NTSC_specific_setup.hue > COLOURS_NTSC_HUE_MIN)
							COLOURS_NTSC_specific_setup.hue -= 0.02;
					} else {
						if (COLOURS_NTSC_specific_setup.hue < COLOURS_NTSC_HUE_MAX)
							COLOURS_NTSC_specific_setup.hue += 0.02;
					}
					Colours_Update();
				}
				break;
			case SDLK_2:
				key_pressed = 0;
				if (kbhits[SDLK_LSHIFT]) {
					if (Colours_setup->saturation > COLOURS_SATURATION_MIN)
						Colours_setup->saturation -= 0.02;
				} else {
					if (Colours_setup->saturation < COLOURS_SATURATION_MAX)
						Colours_setup->saturation += 0.02;
				}
				Colours_Update();
				break;
			case SDLK_3:
				key_pressed = 0;
				if (kbhits[SDLK_LSHIFT]) {
					if (Colours_setup->contrast > COLOURS_CONTRAST_MIN)
						Colours_setup->contrast -= 0.04;
				} else {
					if (Colours_setup->contrast < COLOURS_CONTRAST_MAX)
					Colours_setup->contrast += 0.04;
				}
				Colours_Update();
				break;
			case SDLK_4:
				key_pressed = 0;
				if (kbhits[SDLK_LSHIFT]) {
					if (Colours_setup->brightness > COLOURS_BRIGHTNESS_MIN)
						Colours_setup->brightness -= 0.04;
				} else {
					if (Colours_setup->brightness < COLOURS_BRIGHTNESS_MAX)
						Colours_setup->brightness += 0.04;
				}
				Colours_Update();
				break;
			case SDLK_5:
				key_pressed = 0;
				if (kbhits[SDLK_LSHIFT]) {
					if (Colours_setup->gamma > COLOURS_GAMMA_MIN)
						Colours_setup->gamma -= 0.02;
				} else {
					if (Colours_setup->gamma < COLOURS_GAMMA_MAX)
						Colours_setup->gamma += 0.02;
				}
				Colours_Update();
				break;
			case SDLK_6:
				key_pressed = 0;
				if (Atari800_tv_mode == Atari800_TV_NTSC) {
					if (kbhits[SDLK_LSHIFT]) {
						if (COLOURS_NTSC_specific_setup.color_delay > COLOURS_NTSC_DELAY_MIN)
							COLOURS_NTSC_specific_setup.color_delay -= 0.1;
					} else {
						if (COLOURS_NTSC_specific_setup.color_delay < COLOURS_NTSC_DELAY_MAX)
							COLOURS_NTSC_specific_setup.color_delay += 0.1;
					}
					Colours_Update();
				}
				break;
			case SDLK_LEFTBRACKET:
				key_pressed = 0;
				if (kbhits[SDLK_LSHIFT])
					SDL_VIDEO_SetScanlinesPercentage(SDL_VIDEO_scanlines_percentage - 5);
				else
					SDL_VIDEO_SetScanlinesPercentage(SDL_VIDEO_scanlines_percentage + 5);
				break;
			default:
				if(FILTER_NTSC_emu != NULL){
					switch(lastkey){
					case SDLK_7:
						key_pressed = 0;
						if (kbhits[SDLK_LSHIFT]) {
							if (FILTER_NTSC_setup.sharpness > FILTER_NTSC_SHARPNESS_MIN)
								FILTER_NTSC_setup.sharpness -= 0.02;
						} else {
							if (FILTER_NTSC_setup.sharpness < FILTER_NTSC_SHARPNESS_MAX)
								FILTER_NTSC_setup.sharpness += 0.02;
						}
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					case SDLK_8:
						key_pressed = 0;
						if (kbhits[SDLK_LSHIFT]) {
							if (FILTER_NTSC_setup.resolution > FILTER_NTSC_RESOLUTION_MIN)
								FILTER_NTSC_setup.resolution -= 0.02;
						} else {
							if (FILTER_NTSC_setup.resolution < FILTER_NTSC_RESOLUTION_MAX)
								FILTER_NTSC_setup.resolution += 0.02;
						}
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					case SDLK_9:
						key_pressed = 0;
						if (kbhits[SDLK_LSHIFT]) {
							if (FILTER_NTSC_setup.artifacts > FILTER_NTSC_ARTIFACTS_MIN)
								FILTER_NTSC_setup.artifacts -= 0.02;
						} else {
							if (FILTER_NTSC_setup.artifacts < FILTER_NTSC_ARTIFACTS_MAX)
								FILTER_NTSC_setup.artifacts += 0.02;
						}
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					case SDLK_0:
						key_pressed = 0;
						if (kbhits[SDLK_LSHIFT]) {
							if (FILTER_NTSC_setup.fringing > FILTER_NTSC_FRINGING_MIN)
								FILTER_NTSC_setup.fringing -= 0.02;
						} else {
							if (FILTER_NTSC_setup.fringing < FILTER_NTSC_FRINGING_MAX)
								FILTER_NTSC_setup.fringing += 0.02;
						}
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					case SDLK_MINUS:
						key_pressed = 0;
						if (kbhits[SDLK_LSHIFT]) {
							if (FILTER_NTSC_setup.bleed > FILTER_NTSC_BLEED_MIN)
								FILTER_NTSC_setup.bleed -= 0.02;
						} else {
							if (FILTER_NTSC_setup.bleed < FILTER_NTSC_BLEED_MAX)
								FILTER_NTSC_setup.bleed += 0.02;
						}
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					case SDLK_EQUALS:
						key_pressed = 0;
						if (kbhits[SDLK_LSHIFT]) {
							if (FILTER_NTSC_setup.burst_phase > FILTER_NTSC_BURST_PHASE_MIN)
								FILTER_NTSC_setup.burst_phase -= 0.02;
						} else {
							if (FILTER_NTSC_setup.burst_phase < FILTER_NTSC_BURST_PHASE_MAX)
								FILTER_NTSC_setup.burst_phase += 0.02;
						}
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					case SDLK_RIGHTBRACKET:
						key_pressed = 0;
						FILTER_NTSC_NextPreset();
						FILTER_NTSC_Update(FILTER_NTSC_emu);
						break;
					}
				}
			break;
			}
		}
	}

	/* SHIFT STATE */
	if ((kbhits[SDLK_LSHIFT]) || (kbhits[SDLK_RSHIFT]))
		INPUT_key_shift = 1;
	else
		INPUT_key_shift = 0;

    /* CONTROL STATE */
	if ((kbhits[SDLK_LCTRL]) || (kbhits[SDLK_RCTRL]))
		key_control = 1;
	else
		key_control = 0;

	/*
	if (event.type == 2 || event.type == 3) {
		Log_print("E:%x S:%x C:%x K:%x U:%x M:%x",event.type,INPUT_key_shift,key_control,lastkey,event.key.keysym.unicode,event.key.keysym.mod);
	}
	*/

	/* OPTION / SELECT / START keys */
	INPUT_key_consol = INPUT_CONSOL_NONE;
	if (kbhits[SDLK_F2])
		INPUT_key_consol &= (~INPUT_CONSOL_OPTION);
	if (kbhits[SDLK_F3])
		INPUT_key_consol &= (~INPUT_CONSOL_SELECT);
	if (kbhits[SDLK_F4])
		INPUT_key_consol &= (~INPUT_CONSOL_START);

	if (key_pressed == 0)
		return AKEY_NONE;

	/* Handle movement and special keys. */
	switch (lastkey) {
	case SDLK_F1:
		key_pressed = 0;
		return AKEY_UI;
	case SDLK_F5:
		key_pressed = 0;
		return INPUT_key_shift ? AKEY_COLDSTART : AKEY_WARMSTART;
	case SDLK_F8:
		UI_alt_function = UI_MENU_MONITOR;
		break;
	case SDLK_F9:
		return AKEY_EXIT;
	case SDLK_F10:
		key_pressed = 0;
		return INPUT_key_shift ? AKEY_SCREENSHOT_INTERLACE : AKEY_SCREENSHOT_INTERLACE;
	case SDLK_F12:
		key_pressed = 0;
		return AKEY_TURBO;
	}

	if (UI_alt_function != -1) {
		key_pressed = 0;
		return AKEY_UI;
	}

	/* keyboard joysticks: don't pass the keypresses to emulation
	 * as some games pause on a keypress (River Raid, Bruce Lee)
	 */
	if (!UI_is_active && PLATFORM_kbd_joy_0_enabled) {
		if (lastkey == KBD_STICK_0_LEFT || lastkey == KBD_STICK_0_RIGHT ||
			lastkey == KBD_STICK_0_UP || lastkey == KBD_STICK_0_DOWN || lastkey == KBD_TRIG_0) {
			key_pressed = 0;
			return AKEY_NONE;
		}
	}

	if (!UI_is_active && PLATFORM_kbd_joy_1_enabled) {
		if (lastkey == KBD_STICK_1_LEFT || lastkey == KBD_STICK_1_RIGHT ||
			lastkey == KBD_STICK_1_UP || lastkey == KBD_STICK_1_DOWN || lastkey == KBD_TRIG_1) {
			key_pressed = 0;
			return AKEY_NONE;
		}
	}

	if (INPUT_key_shift)
		shiftctrl ^= AKEY_SHFT;

	if (Atari800_machine_type == Atari800_MACHINE_5200 && !UI_is_active) {
		if (lastkey == SDLK_F4)
			return AKEY_5200_START ^ shiftctrl;
		switch (lastuni) {
		case 'p':
			return AKEY_5200_PAUSE ^ shiftctrl;
		case 'r':
			return AKEY_5200_RESET ^ shiftctrl;
		case '0':
			return AKEY_5200_0 ^ shiftctrl;
		case '1':
			return AKEY_5200_1 ^ shiftctrl;
		case '2':
			return AKEY_5200_2 ^ shiftctrl;
		case '3':
			return AKEY_5200_3 ^ shiftctrl;
		case '4':
			return AKEY_5200_4 ^ shiftctrl;
		case '5':
			return AKEY_5200_5 ^ shiftctrl;
		case '6':
			return AKEY_5200_6 ^ shiftctrl;
		case '7':
			return AKEY_5200_7 ^ shiftctrl;
		case '8':
			return AKEY_5200_8 ^ shiftctrl;
		case '9':
			return AKEY_5200_9 ^ shiftctrl;
		case '#':
		case '=':
			return AKEY_5200_HASH ^ shiftctrl;
		case '*':
			return AKEY_5200_ASTERISK ^ shiftctrl;
		}
		return AKEY_NONE;
	}

	if (key_control)
		shiftctrl ^= AKEY_CTRL;

	switch (lastkey) {
	case SDLK_BACKQUOTE: /* fallthrough */
		/* These are the "Windows" keys, but they don't work on Windows*/
	case SDLK_LSUPER:
		return AKEY_ATARI ^ shiftctrl;
	case SDLK_RSUPER:
		if (INPUT_key_shift)
			return AKEY_CAPSLOCK;
		else
			return AKEY_CAPSTOGGLE;
	case SDLK_END:
	case SDLK_F6:
		return AKEY_HELP ^ shiftctrl;
	case SDLK_PAGEDOWN:
		return AKEY_F2 | AKEY_SHFT;
	case SDLK_PAGEUP:
		return AKEY_F1 | AKEY_SHFT;
	case SDLK_HOME:
		return key_control ? AKEY_LESS|shiftctrl : AKEY_CLEAR;
	case SDLK_PAUSE:
	case SDLK_F7:
		return AKEY_BREAK;
	case SDLK_CAPSLOCK:
		if (INPUT_key_shift)
			return AKEY_CAPSLOCK|shiftctrl;
		else
			return AKEY_CAPSTOGGLE|shiftctrl;
	case SDLK_SPACE:
		return AKEY_SPACE ^ shiftctrl;
	case SDLK_BACKSPACE:
		return AKEY_BACKSPACE|shiftctrl;
	case SDLK_RETURN:
		return AKEY_RETURN ^ shiftctrl;
	case SDLK_LEFT:
		return (INPUT_key_shift ? AKEY_PLUS : AKEY_LEFT) ^ shiftctrl;
	case SDLK_RIGHT:
		return (INPUT_key_shift ? AKEY_ASTERISK : AKEY_RIGHT) ^ shiftctrl;
	case SDLK_UP:
		return (INPUT_key_shift ? AKEY_MINUS : AKEY_UP) ^ shiftctrl;
	case SDLK_DOWN:
		return (INPUT_key_shift ? AKEY_EQUAL : AKEY_DOWN) ^ shiftctrl;
	case SDLK_ESCAPE:
		/* Windows takes ctrl+esc and ctrl+shift+esc */
		return AKEY_ESCAPE ^ shiftctrl;
	case SDLK_TAB:
#if HAVE_WINDOWS_H
		/* On Windows, when an SDL window has focus and LAlt+Tab is pressed,
		   a window-switching menu appears, but the LAlt+Tab key sequence is
		   still forwarded to the SDL window. In the effect the user cannot
		   switch with LAlt+Tab without the emulator registering unwanted key
		   presses. On other operating systems (e.g. GNU/Linux/KDE) everything
		   is OK, the key sequence is not registered by the emulator. This
		   hack fixes the behaviour on Windows. */
		if (kbhits[SDLK_LALT]) {
			key_pressed = 0;
			/* 1. In fullscreen software (non-OpenGL) mode, user presses LAlt, then presses Tab.
			      Atari800 window gets minimised and the window-switching menu appears.
			   2. User switches back to Atari800 without releasing LAlt.
			   3. User releases LAlt. Atari800 gets switched back to fullscreen.
			   In the above situation, the emulator would register pressing of LAlt but
			   would not register releasing of the key. It would think that LAlt is still
			   pressed. The hack below fixes the issue by causing SDL to assume LAlt is
			   not pressed. */
#if HAVE_OPENGL
			if (!VIDEOMODE_windowed && !SDL_VIDEO_opengl)
#else
			if (!VIDEOMODE_windowed)
#endif /* HAVE_OPENGL */
				kbhits[SDLK_LALT] = 0;
			return AKEY_NONE;
		}
#endif /* HAVE_WINDOWS_H */
		return AKEY_TAB ^ shiftctrl;
	case SDLK_DELETE:
		if (INPUT_key_shift)
			return AKEY_DELETE_LINE|shiftctrl;
		else
			return AKEY_DELETE_CHAR;
	case SDLK_INSERT:
		if (INPUT_key_shift)
			return AKEY_INSERT_LINE|shiftctrl;
		else
			return AKEY_INSERT_CHAR;
	}
	if (INPUT_cx85) switch (lastkey) {
	case SDLK_KP1:
		return AKEY_CX85_1;
	case SDLK_KP2:
		return AKEY_CX85_2;
	case SDLK_KP3:
		return AKEY_CX85_3;
	case SDLK_KP4:
		return AKEY_CX85_4;
	case SDLK_KP5:
		return AKEY_CX85_5;
	case SDLK_KP6:
		return AKEY_CX85_6;
	case SDLK_KP7:
		return AKEY_CX85_7;
	case SDLK_KP8:
		return AKEY_CX85_8;
	case SDLK_KP9:
		return AKEY_CX85_9;
	case SDLK_KP0:
		return AKEY_CX85_0;
	case SDLK_KP_PERIOD:
		return AKEY_CX85_PERIOD;
	case SDLK_KP_MINUS:
		return AKEY_CX85_MINUS;
	case SDLK_KP_ENTER:
		return AKEY_CX85_PLUS_ENTER;
	case SDLK_KP_DIVIDE:
		return (key_control ? AKEY_CX85_ESCAPE : AKEY_CX85_NO);
	case SDLK_KP_MULTIPLY:
		return AKEY_CX85_DELETE;
	case SDLK_KP_PLUS:
		return AKEY_CX85_YES;
	}

	/* Handle CTRL-0 to CTRL-9 and other control characters */
	if (key_control) {
		switch(lastuni) {
		case '.':
			return AKEY_FULLSTOP|shiftctrl;
		case ',':
			return AKEY_COMMA|shiftctrl;
		case ';':
			return AKEY_SEMICOLON|shiftctrl;
		}
		switch (lastkey) {
		case SDLK_PERIOD:
			return AKEY_FULLSTOP|shiftctrl;
		case SDLK_COMMA:
			return AKEY_COMMA|shiftctrl;
		case SDLK_SEMICOLON:
			return AKEY_SEMICOLON|shiftctrl;
		case SDLK_SLASH:
			return AKEY_SLASH|shiftctrl;
		case SDLK_BACKSLASH:
			/* work-around for Windows */
			return AKEY_ESCAPE|shiftctrl;
		case SDLK_0:
			return AKEY_CTRL_0|shiftctrl;
		case SDLK_1:
			return AKEY_CTRL_1|shiftctrl;
		case SDLK_2:
			return AKEY_CTRL_2|shiftctrl;
		case SDLK_3:
			return AKEY_CTRL_3|shiftctrl;
		case SDLK_4:
			return AKEY_CTRL_4|shiftctrl;
		case SDLK_5:
			return AKEY_CTRL_5|shiftctrl;
		case SDLK_6:
			return AKEY_CTRL_6|shiftctrl;
		case SDLK_7:
			return AKEY_CTRL_7|shiftctrl;
		case SDLK_8:
			return AKEY_CTRL_8|shiftctrl;
		case SDLK_9:
			return AKEY_CTRL_9|shiftctrl;
		}
	}

	/* Host Caps Lock will make lastuni switch case, so prevent this*/
    if(lastuni>='A' && lastuni <= 'Z' && !INPUT_key_shift) lastuni += 0x20;
    if(lastuni>='a' && lastuni <= 'z' && INPUT_key_shift) lastuni -= 0x20;
	/* Uses only UNICODE translation, no shift states (this was added to
	 * support non-US keyboard layouts)*/
	/* input.c takes care of removing invalid shift+control keys */
	switch (lastuni) {
	case 1:
		return AKEY_CTRL_a|shiftctrl;
	case 2:
		return AKEY_CTRL_b|shiftctrl;
	case 3:
		return AKEY_CTRL_c|shiftctrl;
	case 4:
		return AKEY_CTRL_d|shiftctrl;
	case 5:
		return AKEY_CTRL_e|shiftctrl;
	case 6:
		return AKEY_CTRL_f|shiftctrl;
	case 7:
		return AKEY_CTRL_g|shiftctrl;
	case 8:
		return AKEY_CTRL_h|shiftctrl;
	case 9:
		return AKEY_CTRL_i|shiftctrl;
	case 10:
		return AKEY_CTRL_j|shiftctrl;
	case 11:
		return AKEY_CTRL_k|shiftctrl;
	case 12:
		return AKEY_CTRL_l|shiftctrl;
	case 13:
		return AKEY_CTRL_m|shiftctrl;
	case 14:
		return AKEY_CTRL_n|shiftctrl;
	case 15:
		return AKEY_CTRL_o|shiftctrl;
	case 16:
		return AKEY_CTRL_p|shiftctrl;
	case 17:
		return AKEY_CTRL_q|shiftctrl;
	case 18:
		return AKEY_CTRL_r|shiftctrl;
	case 19:
		return AKEY_CTRL_s|shiftctrl;
	case 20:
		return AKEY_CTRL_t|shiftctrl;
	case 21:
		return AKEY_CTRL_u|shiftctrl;
	case 22:
		return AKEY_CTRL_v|shiftctrl;
	case 23:
		return AKEY_CTRL_w|shiftctrl;
	case 24:
		return AKEY_CTRL_x|shiftctrl;
	case 25:
		return AKEY_CTRL_y|shiftctrl;
	case 26:
		return AKEY_CTRL_z|shiftctrl;
	case 'A':
		return AKEY_A;
	case 'B':
		return AKEY_B;
	case 'C':
		return AKEY_C;
	case 'D':
		return AKEY_D;
	case 'E':
		return AKEY_E;
	case 'F':
		return AKEY_F;
	case 'G':
		return AKEY_G;
	case 'H':
		return AKEY_H;
	case 'I':
		return AKEY_I;
	case 'J':
		return AKEY_J;
	case 'K':
		return AKEY_K;
	case 'L':
		return AKEY_L;
	case 'M':
		return AKEY_M;
	case 'N':
		return AKEY_N;
	case 'O':
		return AKEY_O;
	case 'P':
		return AKEY_P;
	case 'Q':
		return AKEY_Q;
	case 'R':
		return AKEY_R;
	case 'S':
		return AKEY_S;
	case 'T':
		return AKEY_T;
	case 'U':
		return AKEY_U;
	case 'V':
		return AKEY_V;
	case 'W':
		return AKEY_W;
	case 'X':
		return AKEY_X;
	case 'Y':
		return AKEY_Y;
	case 'Z':
		return AKEY_Z;
	case ':':
		return AKEY_COLON;
	case '!':
		return AKEY_EXCLAMATION;
	case '@':
		return AKEY_AT;
	case '#':
		return AKEY_HASH;
	case '$':
		return AKEY_DOLLAR;
	case '%':
		return AKEY_PERCENT;
	case '^':
		return AKEY_CARET;
	case '&':
		return AKEY_AMPERSAND;
	case '*':
		return AKEY_ASTERISK;
	case '(':
		return AKEY_PARENLEFT;
	case ')':
		return AKEY_PARENRIGHT;
	case '+':
		return AKEY_PLUS;
	case '_':
		return AKEY_UNDERSCORE;
	case '"':
		return AKEY_DBLQUOTE;
	case '?':
		return AKEY_QUESTION;
	case '<':
		return AKEY_LESS;
	case '>':
		return AKEY_GREATER;
	case 'a':
		return AKEY_a;
	case 'b':
		return AKEY_b;
	case 'c':
		return AKEY_c;
	case 'd':
		return AKEY_d;
	case 'e':
		return AKEY_e;
	case 'f':
		return AKEY_f;
	case 'g':
		return AKEY_g;
	case 'h':
		return AKEY_h;
	case 'i':
		return AKEY_i;
	case 'j':
		return AKEY_j;
	case 'k':
		return AKEY_k;
	case 'l':
		return AKEY_l;
	case 'm':
		return AKEY_m;
	case 'n':
		return AKEY_n;
	case 'o':
		return AKEY_o;
	case 'p':
		return AKEY_p;
	case 'q':
		return AKEY_q;
	case 'r':
		return AKEY_r;
	case 's':
		return AKEY_s;
	case 't':
		return AKEY_t;
	case 'u':
		return AKEY_u;
	case 'v':
		return AKEY_v;
	case 'w':
		return AKEY_w;
	case 'x':
		return AKEY_x;
	case 'y':
		return AKEY_y;
	case 'z':
		return AKEY_z;
	case ';':
		return AKEY_SEMICOLON;
	case '0':
		return AKEY_0;
	case '1':
		return AKEY_1;
	case '2':
		return AKEY_2;
	case '3':
		return AKEY_3;
	case '4':
		return AKEY_4;
	case '5':
		return AKEY_5;
	case '6':
		return AKEY_6;
	case '7':
		return AKEY_7;
	case '8':
		return AKEY_8;
	case '9':
		return AKEY_9;
	case ',':
		return AKEY_COMMA;
	case '.':
		return AKEY_FULLSTOP;
	case '=':
		return AKEY_EQUAL;
	case '-':
		return AKEY_MINUS;
	case '\'':
		return AKEY_QUOTE;
	case '/':
		return AKEY_SLASH;
	case '\\':
		return AKEY_BACKSLASH;
	case '[':
		return AKEY_BRACKETLEFT;
	case ']':
		return AKEY_BRACKETRIGHT;
	case '|':
		return AKEY_BAR;
	}

	return AKEY_NONE;
}
Пример #22
0
int SDL_INPUT_Initialise(int *argc, char *argv[])
{
	/* TODO check for errors! */
#ifdef LPTJOY
	char *lpt_joy0 = NULL;
	char *lpt_joy1 = NULL;
#endif /* LPTJOY */
	int i;
	int j;
	int no_joystick = FALSE;
	int help_only = FALSE;

	for (i = j = 1; i < *argc; i++) {
#ifdef LPTJOY
		int i_a = (i + 1 < *argc);		/* is argument available? */
#endif /* LPTJOY */
		int a_m = FALSE;			/* error, argument missing! */
		if (strcmp(argv[i], "-nojoystick") == 0) {
			no_joystick = TRUE;
			Log_print("no joystick");
		}
		else if (strcmp(argv[i], "-grabmouse") == 0) {
			grab_mouse = TRUE;
		}
#ifdef LPTJOY
		else if (strcmp(argv[i], "-joy0") == 0) {
			if (i_a) {
				lpt_joy0 = argv[++i];
			}
			else a_m = TRUE;
		}
		else if (!strcmp(argv[i], "-joy1")) {
			if (i_a) {
				lpt_joy1 = argv[++i];
			}
			else a_m = TRUE;
		}
#endif /* LPTJOY */
		else {
			if (strcmp(argv[i], "-help") == 0) {
				help_only = TRUE;
				Log_print("\t-nojoystick      Disable joystick");
#ifdef LPTJOY
				Log_print("\t-joy0 <pathname> Select LPTjoy0 device");
				Log_print("\t-joy1 <pathname> Select LPTjoy1 device");
#endif /* LPTJOY */
				Log_print("\t-grabmouse       Prevent mouse pointer from leaving window");
			}
			argv[j++] = argv[i];
		}

		if (a_m) {
			Log_print("Missing argument for '%s'", argv[i]);
			return FALSE;
		}
	}
	*argc = j;

	if (help_only || no_joystick)
		return TRUE;

#ifdef LPTJOY
	if (lpt_joy0 != NULL) {				/* LPT1 joystick */
		fd_joystick0 = open(lpt_joy0, O_RDONLY);
		if (fd_joystick0 == -1)
			perror(lpt_joy0);
	}
	if (lpt_joy1 != NULL) {				/* LPT2 joystick */
		fd_joystick1 = open(lpt_joy1, O_RDONLY);
		if (fd_joystick1 == -1)
			perror(lpt_joy1);
	}
#endif /* LPTJOY */
	Init_SDL_Joysticks(fd_joystick0 == -1, fd_joystick1 == -1);
	if (INPUT_cx85) { /* disable keyboard joystick if using CX85 numpad */
		PLATFORM_kbd_joy_0_enabled = 0;
	}
	if(grab_mouse)
		SDL_WM_GrabInput(SDL_GRAB_ON);

	return TRUE;
}
Пример #23
0
int CFG_LoadConfig(const char *alternate_config_filename)
{
	FILE *fp;
	const char *fname = rtconfig_filename;
	char string[256];
#ifndef BASIC
	int was_obsolete_dir = FALSE;
#endif

#ifdef SUPPORTS_PLATFORM_CONFIGINIT
	PLATFORM_ConfigInit();
#endif

	/* if alternate config filename is passed then use it */
	if (alternate_config_filename != NULL && *alternate_config_filename > 0) {
		Util_strlcpy(rtconfig_filename, alternate_config_filename, FILENAME_MAX);
	}
	/* else use the default config name under the HOME folder */
	else {
		char *home = getenv("HOME");
		if (home != NULL)
			Util_catpath(rtconfig_filename, home, DEFAULT_CFG_NAME);
		else
			strcpy(rtconfig_filename, DEFAULT_CFG_NAME);
	}

	fp = fopen(fname, "r");
	if (fp == NULL) {
		Log_print("User config file '%s' not found.", rtconfig_filename);

#ifdef SYSTEM_WIDE_CFG_FILE
		/* try system wide config file */
		fname = SYSTEM_WIDE_CFG_FILE;
		Log_print("Trying system wide config file: %s", fname);
		fp = fopen(fname, "r");
#endif
		if (fp == NULL) {
			Log_print("No configuration file found, will create fresh one from scratch:");
			return FALSE;
		}
	}

	if (fgets(string, sizeof(string), fp) != NULL) {
		Log_print("Using Atari800 config file: %s\nCreated by %s", fname, string);
	}

	while (fgets(string, sizeof(string), fp)) {
		char *ptr;
		Util_chomp(string);
		ptr = strchr(string, '=');
		if (ptr != NULL) {
			*ptr++ = '\0';
			Util_trim(string);
			Util_trim(ptr);

			if (SYSROM_ReadConfig(string, ptr)) {
			}
#ifdef BASIC
			else if (strcmp(string, "ATARI_FILES_DIR") == 0
				  || strcmp(string, "SAVED_FILES_DIR") == 0
				  || strcmp(string, "DISK_DIR") == 0 || strcmp(string, "ROM_DIR") == 0
				  || strcmp(string, "EXE_DIR") == 0 || strcmp(string, "STATE_DIR") == 0)
				/* do nothing */;
#else
			else if (strcmp(string, "ATARI_FILES_DIR") == 0) {
				if (UI_n_atari_files_dir >= UI_MAX_DIRECTORIES)
					Log_print("All ATARI_FILES_DIR slots used!");
				else
					Util_strlcpy(UI_atari_files_dir[UI_n_atari_files_dir++], ptr, FILENAME_MAX);
			}
			else if (strcmp(string, "SAVED_FILES_DIR") == 0) {
				if (UI_n_saved_files_dir >= UI_MAX_DIRECTORIES)
					Log_print("All SAVED_FILES_DIR slots used!");
				else
					Util_strlcpy(UI_saved_files_dir[UI_n_saved_files_dir++], ptr, FILENAME_MAX);
			}
			else if (strcmp(string, "DISK_DIR") == 0 || strcmp(string, "ROM_DIR") == 0
				  || strcmp(string, "EXE_DIR") == 0 || strcmp(string, "STATE_DIR") == 0) {
				/* ignore blank and "." values */
				if (ptr[0] != '\0' && (ptr[0] != '.' || ptr[1] != '\0'))
					was_obsolete_dir = TRUE;
			}
#endif
			else if (strcmp(string, "H1_DIR") == 0)
				Util_strlcpy(Devices_atari_h_dir[0], ptr, FILENAME_MAX);
			else if (strcmp(string, "H2_DIR") == 0)
				Util_strlcpy(Devices_atari_h_dir[1], ptr, FILENAME_MAX);
			else if (strcmp(string, "H3_DIR") == 0)
				Util_strlcpy(Devices_atari_h_dir[2], ptr, FILENAME_MAX);
			else if (strcmp(string, "H4_DIR") == 0)
				Util_strlcpy(Devices_atari_h_dir[3], ptr, FILENAME_MAX);
			else if (strcmp(string, "HD_READ_ONLY") == 0)
				Devices_h_read_only = Util_sscandec(ptr);

			else if (strcmp(string, "PRINT_COMMAND") == 0) {
				if (!Devices_SetPrintCommand(ptr))
					Log_print("Unsafe PRINT_COMMAND ignored");
			}

			else if (strcmp(string, "SCREEN_REFRESH_RATIO") == 0)
				Atari800_refresh_rate = Util_sscandec(ptr);
			else if (strcmp(string, "DISABLE_BASIC") == 0)
				Atari800_disable_basic = Util_sscanbool(ptr);

			else if (strcmp(string, "ENABLE_SIO_PATCH") == 0) {
				ESC_enable_sio_patch = Util_sscanbool(ptr);
			}
			else if (strcmp(string, "ENABLE_H_PATCH") == 0) {
				Devices_enable_h_patch = Util_sscanbool(ptr);
			}
			else if (strcmp(string, "ENABLE_P_PATCH") == 0) {
				Devices_enable_p_patch = Util_sscanbool(ptr);
			}
			else if (strcmp(string, "ENABLE_R_PATCH") == 0) {
				Devices_enable_r_patch = Util_sscanbool(ptr);
			}

			else if (strcmp(string, "ENABLE_NEW_POKEY") == 0) {
#ifdef SOUND
				POKEYSND_enable_new_pokey = Util_sscanbool(ptr);
#endif /* SOUND */
			}
			else if (strcmp(string, "STEREO_POKEY") == 0) {
#ifdef STEREO_SOUND
				POKEYSND_stereo_enabled = Util_sscanbool(ptr);
#ifdef SOUND_THIN_API
				Sound_desired.channels = POKEYSND_stereo_enabled ? 2 : 1;
#endif /* SOUND_THIN_API */
#endif /* STEREO_SOUND */
			}
			else if (strcmp(string, "SPEAKER_SOUND") == 0) {
#ifdef CONSOLE_SOUND
				POKEYSND_console_sound_enabled = Util_sscanbool(ptr);
#endif
			}
			else if (strcmp(string, "SERIO_SOUND") == 0) {
#ifdef SERIO_SOUND
				POKEYSND_serio_sound_enabled = Util_sscanbool(ptr);
#endif
			}
			else if (strcmp(string, "MACHINE_TYPE") == 0) {
				if (strcmp(ptr, "Atari 400/800") == 0 ||
				    /* Also recognise legacy values of this parameter */
				    strcmp(ptr, "Atari OS/A") == 0 ||
				    strcmp(ptr, "Atari OS/B") == 0)
					Atari800_machine_type = Atari800_MACHINE_800;
				else if (strcmp(ptr, "Atari XL/XE") == 0)
					Atari800_machine_type = Atari800_MACHINE_XLXE;
				else if (strcmp(ptr, "Atari 5200") == 0)
					Atari800_machine_type = Atari800_MACHINE_5200;
				else
					Log_print("Invalid machine type: %s", ptr);
			}
			else if (strcmp(string, "RAM_SIZE") == 0) {
				if (strcmp(ptr, "320 (RAMBO)") == 0)
					MEMORY_ram_size = MEMORY_RAM_320_RAMBO;
				else if (strcmp(ptr, "320 (COMPY SHOP)") == 0)
					MEMORY_ram_size = MEMORY_RAM_320_COMPY_SHOP;
				else {
					int size = Util_sscandec(ptr);
					if (MEMORY_SizeValid(size))
						MEMORY_ram_size = size;
					else
						Log_print("Invalid RAM size: %s", ptr);
				}
			}
			else if (strcmp(string, "DEFAULT_TV_MODE") == 0) {
				if (strcmp(ptr, "PAL") == 0)
					Atari800_tv_mode = Atari800_TV_PAL;
				else if (strcmp(ptr, "NTSC") == 0)
					Atari800_tv_mode = Atari800_TV_NTSC;
				else
					Log_print("Invalid TV Mode: %s", ptr);
			}
			else if (strcmp(string, "MOSAIC_RAM_NUM_BANKS") == 0) {
				int num = Util_sscandec(ptr);
				if (num >= 0 && num <= 64)
					MEMORY_mosaic_num_banks = num;
				else
					Log_print("Invalid Mosaic RAM number of banks: %s", ptr);
			}
			else if (strcmp(string, "AXLON_RAM_NUM_BANKS") == 0) {
				int num = Util_sscandec(ptr);
				if (num == 0 || num == 8 || num == 16 || num == 32 || num == 64 || num == 128 || num == 256)
					MEMORY_axlon_num_banks = num;
				else
					Log_print("Invalid Mosaic RAM number of banks: %s", ptr);
			}
			else if (strcmp(string, "ENABLE_MAPRAM") == 0)
				MEMORY_enable_mapram = Util_sscanbool(ptr);
			else if (strcmp(string, "BUILTIN_BASIC") == 0)
				Atari800_builtin_basic = Util_sscanbool(ptr);
			else if (strcmp(string, "KEYBOARD_LEDS") == 0)
				Atari800_keyboard_leds = Util_sscanbool(ptr);
			else if (strcmp(string, "F_KEYS") == 0)
				Atari800_f_keys = Util_sscanbool(ptr);
			else if (strcmp(string, "BUILTIN_GAME") == 0)
				Atari800_builtin_game = Util_sscanbool(ptr);
			else if (strcmp(string, "KEYBOARD_DETACHED") == 0)
				Atari800_keyboard_detached = Util_sscanbool(ptr);
			else if (strcmp(string, "1200XL_JUMPER") == 0)
				Atari800_jumper = Util_sscanbool(ptr);
			else if (strcmp(string, "CFG_SAVE_ON_EXIT") == 0) {
				CFG_save_on_exit = Util_sscanbool(ptr);
			}
			/* Add module-specific configurations here */
			else if (PBI_ReadConfig(string,ptr)) {
			}
			else if (CARTRIDGE_ReadConfig(string, ptr)) {
			}
			else if (CASSETTE_ReadConfig(string, ptr)) {
			}
			else if (RTIME_ReadConfig(string, ptr)) {
			}
#ifdef XEP80_EMULATION
			else if (XEP80_ReadConfig(string, ptr)) {
			}
#endif
#ifdef AF80
			else if (AF80_ReadConfig(string,ptr)) {
			}
#endif
#if !defined(BASIC) && !defined(CURSES_BASIC)
			else if (Colours_ReadConfig(string, ptr)) {
			}
			else if (ARTIFACT_ReadConfig(string, ptr)) {
			}
			else if (Screen_ReadConfig(string, ptr)) {
			}
#endif
#ifdef NTSC_FILTER
			else if (FILTER_NTSC_ReadConfig(string, ptr)) {
			}
#endif
#if SUPPORTS_CHANGE_VIDEOMODE
			else if (VIDEOMODE_ReadConfig(string, ptr)) {
			}
#endif
#if defined(SOUND) && defined(SOUND_THIN_API)
			else if (Sound_ReadConfig(string, ptr)) {
			}
#endif /* defined(SOUND) && defined(SOUND_THIN_API) */
			else {
#ifdef SUPPORTS_PLATFORM_CONFIGURE
				if (!PLATFORM_Configure(string, ptr)) {
					Log_print("Unrecognized variable or bad parameters: '%s=%s'", string, ptr);
				}
#else
				Log_print("Unrecognized variable: %s", string);
#endif
			}
		}
		else {
			Log_print("Ignored config line: %s", string);
		}
	}

	fclose(fp);
#ifndef BASIC
	if (was_obsolete_dir) {
		Log_print(
			"DISK_DIR, ROM_DIR, EXE_DIR and STATE_DIR configuration options\n"
			"are no longer supported. Please use ATARI_FILES_DIR\n"
			"and SAVED_FILES_DIR in your Atari800 configuration file.");
	}
#endif
	return TRUE;
}
Пример #24
0
int COLOURS_PAL_Initialise(int *argc, char *argv[])
{
	int i;
	int j;

	for (i = j = 1; i < *argc; i++) {
		int i_a = (i + 1 < *argc);		/* is argument available? */
		int a_m = FALSE;			/* error, argument missing! */
		
		if (strcmp(argv[i], "-pal-saturation") == 0) {
			if (i_a)
				COLOURS_PAL_setup.saturation = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-pal-contrast") == 0) {
			if (i_a)
				COLOURS_PAL_setup.contrast = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-pal-brightness") == 0) {
			if (i_a)
				COLOURS_PAL_setup.brightness = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-pal-gamma") == 0) {
			if (i_a)
				COLOURS_PAL_setup.gamma = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-palettep") == 0) {
			if (i_a) {
				Util_strlcpy(COLOURS_PAL_external.filename, argv[++i], sizeof(COLOURS_PAL_external.filename));
				/* Use the "loaded" flag to indicate that the palette must be loaded later. */
				COLOURS_PAL_external.loaded = TRUE;
			} else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-palettep-adjust") == 0)
			COLOURS_PAL_external.adjust = TRUE;
		else {
			if (strcmp(argv[i], "-help") == 0) {
				Log_print("\t-pal-saturation <num>  Set PAL color saturation");
				Log_print("\t-pal-contrast <num>    Set PAL contrast");
				Log_print("\t-pal-brightness <num>  Set PAL brightness");
				Log_print("\t-pal-gamma <num>       Set PAL color gamma factor");
				Log_print("\t-palettep <filename>   Load PAL external palette");
				Log_print("\t-palettep-adjust       Apply adjustments to PAL external palette");
			}
			argv[j++] = argv[i];
		}

		if (a_m) {
			Log_print("Missing argument for '%s'", argv[i]);
			return FALSE;
		}
	}
	*argc = j;

	/* Try loading an external palette if needed. */
	if (COLOURS_PAL_external.loaded && !COLOURS_EXTERNAL_Read(&COLOURS_PAL_external))
		Log_print("Cannot read PAL palette from %s", COLOURS_PAL_external.filename);

	return TRUE;
}
Пример #25
0
int WINAPI WinMain(HINSTANCE hinstance,
		   HINSTANCE hprevinstance,
		   LPSTR lpcmdline,
		   int nshowcmd)
{
	//***********************************************
	// Convert WinMain() style command line arguments
	// to main() style arguments (argc, *argv[])
	// This maintains compatibility with the former
	// main() entry point's parameters.
	//***********************************************

	char **argv = NULL;
   	int argc = 1;

	char *app_path = new char[MAX_PATH];
   	strcpy(app_path, GetCommandLine());
   	if (app_path[0] == '\"')
   	{
		app_path = (app_path+1);
		char *lastdit = strchr(app_path, '\"');
		*lastdit = '\x0';
   	}

   	if ( *lpcmdline != '\x0' )
   	{
		char *cmdlinecopy = new char[strlen(lpcmdline)+1];
		strcpy(cmdlinecopy, lpcmdline);

		char *c = cmdlinecopy;
		while(c)
		{
			++argc;
			c = strchr((c+1),' ');
		}

		argv = new char*[argc];
		argv[0] = app_path;

		if(argc > 1)
		{
			argv[1] = cmdlinecopy;
			char *c = strchr(cmdlinecopy, ' ');
			int n = 2;
			while(c)
			{
					*c = '\x0';
					argv [n] = (c+1);
					++n;
					c = strchr((c+1), ' ');
			}
		}
   	}
   	else
   	{
		argv = new char *[1];
		argv[0] = app_path;
   	}
	
	//*********************************************
	// Process commandline and activate console
	// if -console switch is set.
	//*********************************************
	int i,j;

	for (i = j = 1; i < argc; i++) {
		if (strcmp(argv[i], "-console") == 0) {
			useconsole = TRUE;
		}
		else if (strcmp(argv[i], "-help") == 0) {	

			help_only = TRUE;
		}
	}

	if (useconsole || help_only) {
		AllocConsole(); 				// start a console window
		freopen("CONIN$","rb",stdin);   // reopen stdin handle as console window input
		freopen("CONOUT$","wb",stdout); // reopen stout handle as console window output
		freopen("CONOUT$","wb",stderr); // reopen stderr handle as console window output
	}
	else // not using console
	{
	    // console is supressed, so stream console output to a file
		stdout_stream = freopen("atari800.txt", "w", stdout);
		
		if (stdout_stream == NULL)
		  fprintf(stdout, "Error opening atari800.txt\n");
	} 	
	
	//*********************************************
	// Begin main processing
	//*********************************************
	
	MSG msg;
	POINT mouse;
	
	Win32_Init();
	myInstance = GetModuleHandle(NULL);
	
	if (help_only) {
	    /* initialize the Atari800 for help only */
		Atari800_Initialise(&argc, argv);
		Log_print("\t-console         Show the Atari800 console window");
		Log_print("\n");
		system("PAUSE");
		return 0;
	}
	
	/* initialise Atari800 core for use */
	if (!Atari800_Initialise(&argc, argv))
		return 3;

	msg.message = WM_NULL;

	/* main loop */
	for (;;) {

		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if (msg.message == WM_QUIT)
			break;

		if (!bActive)
			continue;

		INPUT_key_code = PLATFORM_Keyboard();

		// support mouse device modes 
		// only supported in fullscreen modes for now
		if (GetScreenMode() == FULLSCREEN)
		{
			GetCursorPos(&mouse);
			INPUT_mouse_delta_x = mouse.x - MOUSE_CENTER_X;
			INPUT_mouse_delta_y = mouse.y - MOUSE_CENTER_Y;
			if (INPUT_mouse_delta_x | INPUT_mouse_delta_y)
				SetCursorPos(MOUSE_CENTER_X, MOUSE_CENTER_Y);
		}
			
		Atari800_Frame();
		if (Atari800_display_screen)
			PLATFORM_DisplayScreen();
	}

	return msg.wParam;
}
Пример #26
0
int AFILE_DetectFileType(const char *filename)
{
	UBYTE header[4];
	int file_length;
	FILE *fp = fopen(filename, "rb");
	if (fp == NULL)
		return AFILE_ERROR;
	if (fread(header, 1, 4, fp) != 4) {
		fclose(fp);
		return AFILE_ERROR;
	}
	switch (header[0]) {
	case 0:
		if (header[1] == 0 && (header[2] != 0 || header[3] != 0) /* && file_length < 37 * 1024 */) {
			fclose(fp);
			return AFILE_BAS;
		}
		break;
	case 0x1f:
		if (header[1] == 0x8b) {
#ifndef HAVE_LIBZ
			fclose(fp);
			Log_print("\"%s\" is a compressed file.", filename);
			Log_print("This executable does not support compressed files. You can uncompress this file");
			Log_print("with an external program that supports gzip (*.gz) files (e.g. gunzip)");
			Log_print("and then load into this emulator.");
			return AFILE_ERROR;
#else /* HAVE_LIBZ */
			gzFile gzf;
			fclose(fp);
			gzf = gzopen(filename, "rb");
			if (gzf == NULL)
				return AFILE_ERROR;
			if (gzread(gzf, header, 4) != 4) {
				gzclose(gzf);
				return AFILE_ERROR;
			}
			gzclose(gzf);
			if (header[0] == 0x96 && header[1] == 0x02)
				return AFILE_ATR_GZ;
			if (header[0] == 'A' && header[1] == 'T' && header[2] == 'A' && header[3] == 'R')
				return AFILE_STATE_GZ;
			return AFILE_XFD_GZ;
#endif /* HAVE_LIBZ */
		}
		break;
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
		if ((header[1] >= '0' && header[1] <= '9') || header[1] == ' ') {
			fclose(fp);
			return AFILE_LST;
		}
		break;
	case 'A':
		if (header[1] == 'T' && header[2] == 'A' && header[3] == 'R') {
			fclose(fp);
			return AFILE_STATE;
		}
		if (header[1] == 'T' && header[2] == '8' && header[3] == 'X') {
			fclose(fp);
			return AFILE_ATX;
		}
		break;
	case 'C':
		if (header[1] == 'A' && header[2] == 'R' && header[3] == 'T') {
			fclose(fp);
			return AFILE_CART;
		}
		break;
	case 0x96:
		if (header[1] == 0x02) {
			fclose(fp);
			return AFILE_ATR;
		}
		break;
	case 0xf9:
	case 0xfa:
		fclose(fp);
		return AFILE_DCM;
	case 0xff:
		if (header[1] == 0xff && (header[2] != 0xff || header[3] != 0xff)) {
			fclose(fp);
			return AFILE_XEX;
		}
		break;
	default:
		break;
	}
	file_length = Util_flen(fp);
	fclose(fp);
	/* Detect .pro images */
	/* # of sectors is in header */
	if ((file_length-16)%(128+12) == 0 &&
			header[0]*256 + header[1] == (file_length-16)/(128+12) &&
			header[2] == 'P') {
#ifdef DEBUG_PRO
		Log_print(".pro file detected");
#endif
		return AFILE_PRO;
	}
	/* 40K or a-power-of-two between 4K and CARTRIDGE_MAX_SIZE */
	if (file_length >= 4 * 1024 && file_length <= CARTRIDGE_MAX_SIZE
	 && ((file_length & (file_length - 1)) == 0 || file_length == 40 * 1024))
		return AFILE_ROM;
	/* BOOT_TAPE is a raw file containing a program booted from a tape */
	if ((header[1] << 7) == file_length)
		return AFILE_BOOT_TAPE;
	if ((file_length & 0x7f) == 0)
		return AFILE_XFD;
	if (IMG_TAPE_FileSupported(header))
		return AFILE_CAS;
	return AFILE_ERROR;
}
Пример #27
0
int Atari800_Initialise(int *argc, char *argv[])
{
	int i, j;
	const char *rom_filename = NULL;
	const char *rom2_filename = NULL;
	const char *run_direct = NULL;
#ifndef BASIC
	const char *state_file = NULL;
#endif
#ifdef __PLUS
	/* Atari800Win PLus doesn't use configuration files,
	   it reads configuration from the Registry */
#ifndef _WX_
	int bUpdateRegistry = (*argc > 1);
#endif
	int bTapeFile = FALSE;
	int nCartType = CARTRIDGE_type;

	/* It is necessary because of the CARTRIDGE_Start (there must not be the
	   registry-read value available at startup) */
	CARTRIDGE_type = CARTRIDGE_NONE;

#ifndef _WX_
	/* Print the time info in the "Log file" window */
	Misc_PrintTime();

	/* Force screen refreshing */
	g_nTestVal = _GetRefreshRate() - 1;

	g_ulAtariState = ATARI_UNINITIALIZED;
#endif /* _WX_ */
#elif defined(MACOSX)

#else /* __PLUS */
	const char *rtconfig_filename = NULL;
	int got_config;
	int help_only = FALSE;

	if (*argc > 1) {
		for (i = j = 1; i < *argc; i++) {
			if (strcmp(argv[i], "-config") == 0) {
				rtconfig_filename = argv[++i];
			}
			else if (strcmp(argv[i], "-v") == 0 ||
					 strcmp(argv[i], "-version") == 0 ||
					 strcmp(argv[i], "--version") == 0) {
				printf("%s\n", Atari800_TITLE);
				return FALSE;
			}
			else if (strcmp(argv[i], "--usage") == 0 ||
					 strcmp(argv[i], "--help") == 0) {
				argv[j++] = "-help";
			}
			else if (strcmp(argv[i], "-verbose") == 0) {
				verbose = TRUE;
			}
			else {
				argv[j++] = argv[i];
			}
		}
		*argc = j;
	}
	got_config = CFG_LoadConfig(rtconfig_filename);

	/* try to find ROM images if the configuration file is not found
	   or it does not specify some ROM paths (blank paths count as specified) */
	CFG_FindROMImages("", TRUE); /* current directory */
#if defined(unix) || defined(__unix__) || defined(__linux__)
	CFG_FindROMImages("/usr/share/atari800", TRUE);
#endif
	if (*argc > 0 && argv[0] != NULL) {
		char atari800_exe_dir[FILENAME_MAX];
		char atari800_exe_rom_dir[FILENAME_MAX];
		/* the directory of the Atari800 program */
		Util_splitpath(argv[0], atari800_exe_dir, NULL);
		CFG_FindROMImages(atari800_exe_dir, TRUE);
		/* "rom" and "ROM" subdirectories of this directory */
		Util_catpath(atari800_exe_rom_dir, atari800_exe_dir, "rom");
		CFG_FindROMImages(atari800_exe_rom_dir, TRUE);
/* skip "ROM" on systems that are known to be case-insensitive */
#if !defined(DJGPP) && !defined(WIN32)
		Util_catpath(atari800_exe_rom_dir, atari800_exe_dir, "ROM");
		CFG_FindROMImages(atari800_exe_rom_dir, TRUE);
#endif
	}
	/* finally if nothing is found, set some defaults to make
	   the configuration file easier to edit */
	if (Util_filenamenotset(CFG_osa_filename))
		strcpy(CFG_osa_filename, "atariosa.rom");
	if (Util_filenamenotset(CFG_osb_filename))
		strcpy(CFG_osb_filename, "atariosb.rom");
	if (Util_filenamenotset(CFG_xlxe_filename))
		strcpy(CFG_xlxe_filename, "atarixl.rom");
	if (Util_filenamenotset(CFG_5200_filename))
		strcpy(CFG_5200_filename, "5200.rom");
	if (Util_filenamenotset(CFG_basic_filename))
		strcpy(CFG_basic_filename, "ataribas.rom");

	/* if no configuration file read, try to save one with the defaults */
	if (!got_config)
		CFG_WriteConfig();

#endif /* __PLUS */

	for (i = j = 1; i < *argc; i++) {
		if (strcmp(argv[i], "-atari") == 0) {
			if (Atari800_machine_type != Atari800_MACHINE_OSA) {
				Atari800_machine_type = Atari800_MACHINE_OSB;
				MEMORY_ram_size = 48;
			}
		}
		else if (strcmp(argv[i], "-xl") == 0) {
			Atari800_machine_type = Atari800_MACHINE_XLXE;
			MEMORY_ram_size = 64;
		}
		else if (strcmp(argv[i], "-xe") == 0) {
			Atari800_machine_type = Atari800_MACHINE_XLXE;
			MEMORY_ram_size = 128;
		}
		else if (strcmp(argv[i], "-320xe") == 0) {
			Atari800_machine_type = Atari800_MACHINE_XLXE;
			MEMORY_ram_size = MEMORY_RAM_320_COMPY_SHOP;
		}
		else if (strcmp(argv[i], "-rambo") == 0) {
			Atari800_machine_type = Atari800_MACHINE_XLXE;
			MEMORY_ram_size = MEMORY_RAM_320_RAMBO;
		}
		else if (strcmp(argv[i], "-5200") == 0) {
			Atari800_machine_type = Atari800_MACHINE_5200;
			MEMORY_ram_size = 16;
		}
		else if (strcmp(argv[i], "-nobasic") == 0)
			Atari800_disable_basic = TRUE;
		else if (strcmp(argv[i], "-basic") == 0)
			Atari800_disable_basic = FALSE;
		else if (strcmp(argv[i], "-nopatch") == 0)
			ESC_enable_sio_patch = FALSE;
		else if (strcmp(argv[i], "-nopatchall") == 0)
#ifdef D_PATCH			
			ESC_enable_sio_patch = Devices_enable_h_patch = Devices_enable_d_patch = Devices_enable_p_patch = Devices_enable_r_patch = FALSE;
#else
			ESC_enable_sio_patch = Devices_enable_h_patch = Devices_enable_p_patch = Devices_enable_r_patch = FALSE;
#endif
		else if (strcmp(argv[i], "-pal") == 0)
			Atari800_tv_mode = Atari800_TV_PAL;
		else if (strcmp(argv[i], "-ntsc") == 0)
			Atari800_tv_mode = Atari800_TV_NTSC;
		else if (strcmp(argv[i], "-a") == 0) {
			Atari800_machine_type = Atari800_MACHINE_OSA;
			MEMORY_ram_size = 48;
		}
		else if (strcmp(argv[i], "-b") == 0) {
			Atari800_machine_type = Atari800_MACHINE_OSB;
			MEMORY_ram_size = 48;
		}
		else if (strcmp(argv[i], "-emuos") == 0)
			emuos_mode = 2;
		else if (strcmp(argv[i], "-c") == 0) {
			if (MEMORY_ram_size == 48)
				MEMORY_ram_size = 52;
		}
		else {
			/* parameters that take additional argument follow here */
			int i_a = (i + 1 < *argc);		/* is argument available? */
			int a_m = FALSE;			/* error, argument missing! */

			if (strcmp(argv[i], "-osa_rom") == 0) {
				if (i_a) Util_strlcpy(CFG_osa_filename, argv[++i], sizeof(CFG_osa_filename)); else a_m = TRUE;
			}
#if 0  /* TBD what to do with R device */
#ifdef R_IO_DEVICE
			else if (strcmp(argv[i], "-rdevice") == 0) {
				Devices_enable_r_patch = TRUE;
#ifdef R_SERIAL
				if (i_a && i + 2 < *argc && *argv[i + 1] != '-') {  /* optional serial device name */
					struct stat statbuf;
					if (! stat(argv[i + 1], &statbuf)) {
						if (S_ISCHR(statbuf.st_mode)) { /* only accept devices as serial device */
							Util_strlcpy(RDevice_serial_device, argv[++i], FILENAME_MAX);
							RDevice_serial_enabled = TRUE;
						}
					}
				}
#endif /* R_SERIAL */
			}
#endif
#endif
			else if (strcmp(argv[i], "-osb_rom") == 0) {
				if (i_a) Util_strlcpy(CFG_osb_filename, argv[++i], sizeof(CFG_osb_filename)); else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-xlxe_rom") == 0) {
				if (i_a) Util_strlcpy(CFG_xlxe_filename, argv[++i], sizeof(CFG_xlxe_filename)); else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-5200_rom") == 0) {
				if (i_a) Util_strlcpy(CFG_5200_filename, argv[++i], sizeof(CFG_5200_filename)); else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-basic_rom") == 0) {
				if (i_a) Util_strlcpy(CFG_basic_filename, argv[++i], sizeof(CFG_basic_filename)); else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-cart") == 0) {
				if (i_a) rom_filename = argv[++i]; else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-cart2") == 0) {
				if (i_a) rom2_filename = argv[++i]; else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-run") == 0) {
				if (i_a) run_direct = argv[++i]; else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-mosaic") == 0) {
				int total_ram = Util_sscandec(argv[++i]);
				MEMORY_mosaic_enabled = TRUE;
				MEMORY_mosaic_maxbank = (total_ram - 48)/4 - 1;
				if (((total_ram - 48) % 4 != 0) || (MEMORY_mosaic_maxbank > 0x3e) || (MEMORY_mosaic_maxbank < 0)) {
					Log_print("Invalid Mosaic total RAM size");
					return FALSE;
				}
				if (MEMORY_axlon_enabled) {
					Log_print("Axlon and Mosaic can not both be enabled, because they are incompatible");
					return FALSE;
				}
			}
			else if (strcmp(argv[i], "-axlon") == 0) {
				int total_ram = Util_sscandec(argv[++i]);
				int banks = ((total_ram) - 32) / 16;
				MEMORY_axlon_enabled = TRUE;
				if (((total_ram - 32) % 16 != 0) || ((banks != 8) && (banks != 16) && (banks != 32) && (banks != 64) && (banks != 128) && (banks != 256))) {
					Log_print("Invalid Axlon total RAM size");
					return FALSE;
				}
				if (MEMORY_mosaic_enabled) {
					Log_print("Axlon and Mosaic can not both be enabled, because they are incompatible");
					return FALSE;
				}
				MEMORY_axlon_bankmask = banks - 1;
			}
			else if (strcmp(argv[i], "-axlon0f") == 0) {
				MEMORY_axlon_0f_mirror = TRUE;
			}
#ifndef BASIC
			/* The BASIC version does not support state files, because:
			   1. It has no ability to save state files, because of lack of UI.
			   2. It uses a simplified emulation, so the state files would be
			      incompatible with other versions.
			   3. statesav is not compiled in to make the executable smaller. */
			else if (strcmp(argv[i], "-state") == 0) {
				if (i_a) state_file = argv[++i]; else a_m = TRUE;
			}
			else if (strcmp(argv[i], "-refresh") == 0) {
				if (i_a) {
					Atari800_refresh_rate = Util_sscandec(argv[++i]);
					if (Atari800_refresh_rate < 1) {
						Log_print("Invalid refresh rate, using 1");
						Atari800_refresh_rate = 1;
					}
				}
				else
					a_m = TRUE;
			}
#endif /* BASIC */
#ifdef STEREO_SOUND
			else if (strcmp(argv[i], "-stereo") == 0) {
				POKEYSND_stereo_enabled = TRUE;
			}
			else if (strcmp(argv[i], "-nostereo") == 0) {
				POKEYSND_stereo_enabled = FALSE;
			}
#endif /* STEREO_SOUND */
			else {
				/* all options known to main module tried but none matched */

				if (strcmp(argv[i], "-help") == 0) {
#if !defined(__PLUS) && !defined(MACOSX)
					help_only = TRUE;
					Log_print("\t-config <file>   Specify Alternate Configuration File");
#endif
					Log_print("\t-atari           Emulate Atari 800");
					Log_print("\t-xl              Emulate Atari 800XL");
					Log_print("\t-xe              Emulate Atari 130XE");
					Log_print("\t-320xe           Emulate Atari 320XE (COMPY SHOP)");
					Log_print("\t-rambo           Emulate Atari 320XE (RAMBO)");
					Log_print("\t-5200            Emulate Atari 5200 Games System");
					Log_print("\t-nobasic         Turn off Atari BASIC ROM");
					Log_print("\t-basic           Turn on Atari BASIC ROM");
					Log_print("\t-pal             Enable PAL TV mode");
					Log_print("\t-ntsc            Enable NTSC TV mode");
					Log_print("\t-osa_rom <file>  Load OS A ROM from file");
					Log_print("\t-osb_rom <file>  Load OS B ROM from file");
					Log_print("\t-xlxe_rom <file> Load XL/XE ROM from file");
					Log_print("\t-5200_rom <file> Load 5200 ROM from file");
					Log_print("\t-basic_rom <fil> Load BASIC ROM from file");
					Log_print("\t-cart <file>     Install cartridge (raw or CART format)");
					Log_print("\t-run <file>      Run Atari program (COM, EXE, XEX, BAS, LST)");
#ifndef BASIC
					Log_print("\t-state <file>    Load saved-state file");
					Log_print("\t-refresh <rate>  Specify screen refresh rate");
#endif
					Log_print("\t-nopatch         Don't patch SIO routine in OS");
					Log_print("\t-nopatchall      Don't patch OS at all, H: device won't work");
					Log_print("\t-a               Use OS A");
					Log_print("\t-b               Use OS B");
					Log_print("\t-c               Enable RAM between 0xc000 and 0xcfff in Atari 800");
					Log_print("\t-axlon <n>       Use Atari 800 Axlon memory expansion: <n> k total RAM");
					Log_print("\t-axlon0f         Use Axlon shadow at 0x0fc0-0x0fff");
					Log_print("\t-mosaic <n>      Use 400/800 Mosaic memory expansion: <n> k total RAM");
#ifdef R_IO_DEVICE
					Log_print("\t-rdevice [<dev>] Enable R: emulation (using serial device <dev>)");
#endif
					Log_print("\t-v               Show version/release number");
				}

				/* copy this option for platform/module specific evaluation */
				argv[j++] = argv[i];
			}

			/* this is the end of the additional argument check */
			if (a_m) {
				printf("Missing argument for '%s'\n", argv[i]);
				return FALSE;
			}
		}
	}
Пример #28
0
int Colours_Initialise(int *argc, char *argv[])
{
	int i;
	int j;

	for (i = j = 1; i < *argc; i++) {
		int i_a = (i + 1 < *argc);		/* is argument available? */
		int a_m = FALSE;			/* error, argument missing! */
		
		if (strcmp(argv[i], "-saturation") == 0) {
			if (i_a)
				COLOURS_NTSC_setup.saturation = COLOURS_PAL_setup.saturation = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-contrast") == 0) {
			if (i_a)
				COLOURS_NTSC_setup.contrast = COLOURS_PAL_setup.contrast = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-brightness") == 0) {
			if (i_a)
				COLOURS_NTSC_setup.brightness = COLOURS_PAL_setup.brightness = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-gamma") == 0) {
			if (i_a)
				COLOURS_NTSC_setup.gamma = COLOURS_PAL_setup.gamma = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-tint") == 0) {
			if (i_a)
				COLOURS_NTSC_setup.hue = COLOURS_PAL_setup.hue = atof(argv[++i]);
			else a_m = TRUE;
		}
		else if (strcmp(argv[i], "-colors-preset") == 0) {
			if (i_a) {
				int idx = CFG_MatchTextParameter(argv[++i], preset_cfg_strings, COLOURS_PRESET_SIZE);
				if (idx < 0) {
					Log_print("Invalid value for -colors-preset");
					return FALSE;
				}
				COLOURS_NTSC_setup = COLOURS_PAL_setup = presets[idx];
				COLOURS_NTSC_RestoreDefaults();
				COLOURS_PAL_RestoreDefaults();
			} else a_m = TRUE;
		}

		else {
			if (strcmp(argv[i], "-help") == 0) {
				Log_print("\t-colors-preset standard|deep-black|vibrant");
				Log_print("\t                       Use one of predefined color adjustments");
				Log_print("\t-saturation <num>      Set color saturation");
				Log_print("\t-contrast <num>        Set contrast");
				Log_print("\t-brightness <num>      Set brightness");
				Log_print("\t-gamma <num>           Set color gamma factor");
				Log_print("\t-tint <num>            Set tint");
			}
			argv[j++] = argv[i];
		}

		if (a_m) {
			Log_print("Missing argument for '%s'", argv[i]);
			return FALSE;
		}
	}
	*argc = j;

	if (!COLOURS_NTSC_Initialise(argc, argv) ||
	    !COLOURS_PAL_Initialise(argc, argv))
		return FALSE;

	/* Assume that Atari800_tv_mode has been already initialised. */
	UpdateModeDependentPointers(Atari800_tv_mode);
	UpdatePalette();
	return TRUE;
}
Пример #29
0
void REMEZ_CreateFilter(double h[], int numtaps, int numband, double bands[],
           const double des[], const double weight[], int type)
{
	double *Grid, *W, *D, *E;
	int    i, iter, gridsize, r, *Ext;
	double *taps, c;
	double *x, *y, *ad;
	int    symmetry;

	if (type == REMEZ_BANDPASS)
		symmetry = POSITIVE;
	else
		symmetry = NEGATIVE;

	r = numtaps / 2;                  /* number of extrema */
	if ((numtaps % 2) && (symmetry == POSITIVE))
		r++;

	/* Predict dense grid size in advance for memory allocation
	 *   .5 is so we round up, not truncate */
	gridsize = 0;
	for (i = 0; i < numband; i++) {
		gridsize += (int) (2 * r * GRIDDENSITY *
		                   (bands[2 * i + 1] - bands[2 * i]) + .5);
	}
	if (symmetry == NEGATIVE) {
		gridsize--;
	}

	/* Dynamically allocate memory for arrays with proper sizes */
	Grid = (double *) Util_malloc(gridsize * sizeof(double));
	D = (double *) Util_malloc(gridsize * sizeof(double));
	W = (double *) Util_malloc(gridsize * sizeof(double));
	E = (double *) Util_malloc(gridsize * sizeof(double));
	Ext = (int *) Util_malloc((r + 1) * sizeof(int));
	taps = (double *) Util_malloc((r + 1) * sizeof(double));
	x = (double *) Util_malloc((r + 1) * sizeof(double));
	y = (double *) Util_malloc((r + 1) * sizeof(double));
	ad = (double *) Util_malloc((r + 1) * sizeof(double));

	/* Create dense frequency grid */
	CreateDenseGrid(r, numtaps, numband, bands, des, weight,
	                &gridsize, Grid, D, W, symmetry);
	InitialGuess(r, Ext, gridsize);

	/* For Differentiator: (fix grid) */
	if (type == REMEZ_DIFFERENTIATOR) {
		for (i = 0; i < gridsize; i++) {
			/* D[i] = D[i] * Grid[i]; */
			if (D[i] > 0.0001)
				W[i] = W[i] / Grid[i];
		}
	}

	/* For odd or Negative symmetry filters, alter the
	 * D[] and W[] according to Parks McClellan */
	if (symmetry == POSITIVE) {
		if (numtaps % 2 == 0) {
			for (i = 0; i < gridsize; i++) {
				c = cos(Pi * Grid[i]);
				D[i] /= c;
				W[i] *= c;
			}
		}
	}
	else {
		if (numtaps % 2) {
			for (i = 0; i < gridsize; i++) {
				c = sin(Pi2 * Grid[i]);
				D[i] /= c;
				W[i] *= c;
			}
		}
		else {
			for (i = 0; i < gridsize; i++) {
				c = sin(Pi * Grid[i]);
				D[i] /= c;
				W[i] *= c;
			}
		}
	}

	/* Perform the Remez Exchange algorithm */
	for (iter = 0; iter < MAXITERATIONS; iter++) {
		CalcParms(r, Ext, Grid, D, W, ad, x, y);
		CalcError(r, ad, x, y, gridsize, Grid, D, W, E);
		Search(r, Ext, gridsize, E);
		if (isDone(r, Ext, E))
			break;
	}
#ifndef ASAP
	if (iter == MAXITERATIONS) {
		Log_print("remez(): reached maximum iteration count. Results may be bad.");
	}
#endif

	CalcParms(r, Ext, Grid, D, W, ad, x, y);

	/* Find the 'taps' of the filter for use with Frequency
	 * Sampling.  If odd or Negative symmetry, fix the taps
	 * according to Parks McClellan */
	for (i = 0; i <= numtaps / 2; i++) {
		if (symmetry == POSITIVE) {
			if (numtaps % 2)
				c = 1;
			else
				c = cos(Pi * (double) i / numtaps);
		}
		else {
			if (numtaps % 2)
				c = sin(Pi2 * (double) i / numtaps);
			else
				c = sin(Pi * (double) i / numtaps);
		}
		taps[i] = ComputeA((double) i / numtaps, r, ad, x, y) * c;
	}

	/* Frequency sampling design with calculated taps */
	FreqSample(numtaps, taps, h, symmetry);

	/* Delete allocated memory */
	free(Grid);
	free(W);
	free(D);
	free(E);
	free(Ext);
	free(taps);
	free(x);
	free(y);
	free(ad);
}
Пример #30
0
int CFG_WriteConfig(void)
{
	FILE *fp;
	int i;
	static const char * const machine_type_string[Atari800_MACHINE_SIZE] = {
		"400/800", "XL/XE", "5200"
	};

	fp = fopen(rtconfig_filename, "w");
	if (fp == NULL) {
		perror(rtconfig_filename);
		Log_print("Cannot write to config file: %s", rtconfig_filename);
		return FALSE;
	}
	Log_print("Writing config file: %s", rtconfig_filename);

	fprintf(fp, "%s\n", Atari800_TITLE);
	SYSROM_WriteConfig(fp);
#ifndef BASIC
	for (i = 0; i < UI_n_atari_files_dir; i++)
		fprintf(fp, "ATARI_FILES_DIR=%s\n", UI_atari_files_dir[i]);
	for (i = 0; i < UI_n_saved_files_dir; i++)
		fprintf(fp, "SAVED_FILES_DIR=%s\n", UI_saved_files_dir[i]);
#endif
	for (i = 0; i < 4; i++)
		fprintf(fp, "H%c_DIR=%s\n", '1' + i, Devices_atari_h_dir[i]);
	fprintf(fp, "HD_READ_ONLY=%d\n", Devices_h_read_only);

#ifdef HAVE_SYSTEM
	fprintf(fp, "PRINT_COMMAND=%s\n", Devices_print_command);
#endif

#ifndef BASIC
	fprintf(fp, "SCREEN_REFRESH_RATIO=%d\n", Atari800_refresh_rate);
#endif

	fprintf(fp, "MACHINE_TYPE=Atari %s\n", machine_type_string[Atari800_machine_type]);

	fprintf(fp, "RAM_SIZE=");
	switch (MEMORY_ram_size) {
	case MEMORY_RAM_320_RAMBO:
		fprintf(fp, "320 (RAMBO)\n");
		break;
	case MEMORY_RAM_320_COMPY_SHOP:
		fprintf(fp, "320 (COMPY SHOP)\n");
		break;
	default:
		fprintf(fp, "%d\n", MEMORY_ram_size);
		break;
	}

	fprintf(fp, (Atari800_tv_mode == Atari800_TV_PAL) ? "DEFAULT_TV_MODE=PAL\n" : "DEFAULT_TV_MODE=NTSC\n");
	fprintf(fp, "MOSAIC_RAM_NUM_BANKS=%d\n", MEMORY_mosaic_num_banks);
	fprintf(fp, "AXLON_RAM_NUM_BANKS=%d\n", MEMORY_axlon_num_banks);
	fprintf(fp, "ENABLE_MAPRAM=%d\n", MEMORY_enable_mapram);

	fprintf(fp, "DISABLE_BASIC=%d\n", Atari800_disable_basic);
	fprintf(fp, "ENABLE_SIO_PATCH=%d\n", ESC_enable_sio_patch);
	fprintf(fp, "ENABLE_H_PATCH=%d\n", Devices_enable_h_patch);
	fprintf(fp, "ENABLE_P_PATCH=%d\n", Devices_enable_p_patch);
#ifdef R_IO_DEVICE
	fprintf(fp, "ENABLE_R_PATCH=%d\n", Devices_enable_r_patch);
#endif

#ifdef SOUND
	fprintf(fp, "ENABLE_NEW_POKEY=%d\n", POKEYSND_enable_new_pokey);
#ifdef STEREO_SOUND
	fprintf(fp, "STEREO_POKEY=%d\n", POKEYSND_stereo_enabled);
#endif
#ifdef CONSOLE_SOUND
	fprintf(fp, "SPEAKER_SOUND=%d\n", POKEYSND_console_sound_enabled);
#endif
#ifdef SERIO_SOUND
	fprintf(fp, "SERIO_SOUND=%d\n", POKEYSND_serio_sound_enabled);
#endif
#endif /* SOUND */
	fprintf(fp, "BUILTIN_BASIC=%d\n", Atari800_builtin_basic);
	fprintf(fp, "KEYBOARD_LEDS=%d\n", Atari800_keyboard_leds);
	fprintf(fp, "F_KEYS=%d\n", Atari800_f_keys);
	fprintf(fp, "BUILTIN_GAME=%d\n", Atari800_builtin_game);
	fprintf(fp, "KEYBOARD_DETACHED=%d\n", Atari800_keyboard_detached);
	fprintf(fp, "1200XL_JUMPER=%d\n", Atari800_jumper);
	fprintf(fp, "CFG_SAVE_ON_EXIT=%d\n", CFG_save_on_exit);
	/* Add module-specific configurations here */
	PBI_WriteConfig(fp);
	CARTRIDGE_WriteConfig(fp);
	CASSETTE_WriteConfig(fp);
	RTIME_WriteConfig(fp);
#ifdef XEP80_EMULATION
	XEP80_WriteConfig(fp);
#endif
#ifdef AF80
	AF80_WriteConfig(fp);
#endif
#if !defined(BASIC) && !defined(CURSES_BASIC)
	Colours_WriteConfig(fp);
	ARTIFACT_WriteConfig(fp);
	Screen_WriteConfig(fp);
#endif
#ifdef NTSC_FILTER
	FILTER_NTSC_WriteConfig(fp);
#endif
#if SUPPORTS_CHANGE_VIDEOMODE
	VIDEOMODE_WriteConfig(fp);
#endif
#if defined(SOUND) && defined(SOUND_THIN_API)
	Sound_WriteConfig(fp);
#endif /* defined(SOUND) && defined(SOUND_THIN_API) */
#ifdef SUPPORTS_PLATFORM_CONFIGSAVE
	PLATFORM_ConfigSave(fp);
#endif
	fclose(fp);
	return TRUE;
}