Exemple #1
0
bool ReGBA_SaveSettings(char *cfg_name, bool PerGame)
{
	char fname[MAX_PATH + 1];
	if (strlen(main_path) + strlen(cfg_name) + 5 /* / .cfg */ > MAX_PATH)
	{
		ReGBA_Trace("E: Somehow you hit the filename size limit :o\n");
		return false;
	}
	sprintf(fname, "%s/%s.cfg", main_path, cfg_name);
	FILE_TAG_TYPE fd;

	ReGBA_ProgressInitialise(PerGame ? FILE_ACTION_SAVE_GAME_SETTINGS : FILE_ACTION_SAVE_GLOBAL_SETTINGS);

	FILE_OPEN(fd, fname, WRITE);
	if(FILE_CHECK_VALID(fd)) {
		Menu_SaveIterateRecurse(fd, PerGame ? MainMenu.AlternateVersion : &MainMenu);
		ReGBA_ProgressUpdate(1, 1);
		ReGBA_ProgressFinalise();
	}
	else
	{
		ReGBA_Trace("E: Couldn't open file %s for writing.\n", fname);
		ReGBA_ProgressFinalise();
		return false;
	}

	FILE_CLOSE(fd);
	return true;
}
Exemple #2
0
static void DefaultDisplayTitleFunction(struct Menu* ActiveMenu)
{
	uint32_t TextWidth = GetRenderedWidth(ActiveMenu->Title);
	if (TextWidth <= GCW0_SCREEN_WIDTH - 2)
		print_string_outline(ActiveMenu->Title, COLOR_TITLE_TEXT, COLOR_TITLE_OUTLINE, (GCW0_SCREEN_WIDTH - TextWidth) / 2, 1);
	else
		ReGBA_Trace("W: Hid title '%s' from the menu due to it being too long", ActiveMenu->Title);
}
Exemple #3
0
static void DefaultDisplayValueFunction(struct MenuEntry* DrawnMenuEntry, struct MenuEntry* ActiveMenuEntry)
{
	if (DrawnMenuEntry->Kind == KIND_OPTION || DrawnMenuEntry->Kind == KIND_DISPLAY)
	{
		char* Value;
		char Temp[21];
		bool Error = false;
		if (DrawnMenuEntry->Kind == KIND_OPTION)
		{
			if (*(uint32_t*) DrawnMenuEntry->Target < DrawnMenuEntry->ChoiceCount)
				Value = DrawnMenuEntry->Choices[*(uint32_t*) DrawnMenuEntry->Target].Pretty;
			else
			{
				Value = "Out of bounds";
				Error = true;
			}
		}
		else if (DrawnMenuEntry->Kind == KIND_DISPLAY)
		{
			switch (DrawnMenuEntry->DisplayType)
			{
				case TYPE_STRING:
					Value = (char*) DrawnMenuEntry->Target;
					break;
				case TYPE_INT32:
					sprintf(Temp, "%" PRIi32, *(int32_t*) DrawnMenuEntry->Target);
					Value = Temp;
					break;
				case TYPE_UINT32:
					sprintf(Temp, "%" PRIu32, *(uint32_t*) DrawnMenuEntry->Target);
					Value = Temp;
					break;
				case TYPE_INT64:
					print_i64(Temp, *(int64_t*) DrawnMenuEntry->Target);
					Value = Temp;
					break;
				case TYPE_UINT64:
					print_u64(Temp, *(uint64_t*) DrawnMenuEntry->Target);
					Value = Temp;
					break;
				default:
					Value = "Unknown type";
					Error = true;
					break;
			}
		}
		uint32_t TextWidth = GetRenderedWidth(Value);
		if (TextWidth <= GCW0_SCREEN_WIDTH - 2)
		{
			bool IsActive = (DrawnMenuEntry == ActiveMenuEntry);
			uint16_t TextColor = Error ? COLOR_ERROR_TEXT : (IsActive ? COLOR_ACTIVE_TEXT : COLOR_INACTIVE_TEXT);
			uint16_t OutlineColor = Error ? COLOR_ERROR_OUTLINE : (IsActive ? COLOR_ACTIVE_OUTLINE : COLOR_INACTIVE_OUTLINE);
			print_string_outline(Value, TextColor, OutlineColor, GCW0_SCREEN_WIDTH - TextWidth - 1, GetRenderedHeight(" ") * (DrawnMenuEntry->Position + 2) + 1);
		}
		else
			ReGBA_Trace("W: Hid value '%s' from the menu due to it being too long", Value);
	}
}
Exemple #4
0
static void EnsureJoystick()
{
	if (!JoystickInitialised)
	{
		JoystickInitialised = true;
		Joystick = SDL_JoystickOpen(0);
		if (Joystick == NULL)
		{
			ReGBA_Trace("I: Joystick #0 could not be opened");
		}
	}
}
Exemple #5
0
static void DefaultLoadFunction(struct MenuEntry* ActiveMenuEntry, char* Value)
{
	uint32_t i;
	for (i = 0; i < ActiveMenuEntry->ChoiceCount; i++)
	{
		if (strcasecmp(ActiveMenuEntry->Choices[i].Persistent, Value) == 0)
		{
			*(uint32_t*) ActiveMenuEntry->Target = i;
			return;
		}
	}
	ReGBA_Trace("W: Value '%s' for option '%s' not valid; ignored", Value, ActiveMenuEntry->PersistentName);
}
Exemple #6
0
static void DefaultDisplayNameFunction(struct MenuEntry* DrawnMenuEntry, struct MenuEntry* ActiveMenuEntry)
{
	uint32_t TextWidth = GetRenderedWidth(DrawnMenuEntry->Name);
	if (TextWidth <= GCW0_SCREEN_WIDTH - 2)
	{
		bool IsActive = (DrawnMenuEntry == ActiveMenuEntry);
		uint16_t TextColor = IsActive ? COLOR_ACTIVE_TEXT : COLOR_INACTIVE_TEXT;
		uint16_t OutlineColor = IsActive ? COLOR_ACTIVE_OUTLINE : COLOR_INACTIVE_OUTLINE;
		print_string_outline(DrawnMenuEntry->Name, TextColor, OutlineColor, 1, GetRenderedHeight(" ") * (DrawnMenuEntry->Position + 2) + 1);
	}
	else
		ReGBA_Trace("W: Hid name '%s' from the menu due to it being too long", DrawnMenuEntry->Name);
}
Exemple #7
0
static enum OpenDingux_Buttons GrabButtons(struct Menu* ActiveMenu, char* Lines[4])
{
	enum OpenDingux_Buttons Buttons;
	// Wait for the buttons that triggered the action to be released.
	while (GetPressedOpenDinguxButtons() != 0)
	{
		DefaultDisplayBackgroundFunction(ActiveMenu);
		SDL_Flip(OutputSurface);
		usleep(5000); // for platforms that don't sync their flips
	}
	// Wait until a button is pressed.
	while ((Buttons = GetPressedOpenDinguxButtons()) == 0)
	{
		DefaultDisplayBackgroundFunction(ActiveMenu);
		uint32_t Line;
		for (Line = 0; Line < 4; Line++)
		{
			uint32_t TextWidth = GetRenderedWidth(Lines[Line]);
			if (TextWidth <= GCW0_SCREEN_WIDTH - 2)
				print_string_outline(Lines[Line], COLOR_ACTIVE_TEXT, COLOR_ACTIVE_OUTLINE, (GCW0_SCREEN_WIDTH - TextWidth) / 2, (GCW0_SCREEN_HEIGHT - GetRenderedHeight(" ") * 4) / 2 + GetRenderedHeight(" ") * Line);
			else
				ReGBA_Trace("E: '%s' doesn't fit the screen! Fix this, Nebuleon!", Lines[Line]);
		}
		SDL_Flip(OutputSurface);
		usleep(5000); // for platforms that don't sync their flips
	}
	// Accumulate buttons until they're all released.
	enum OpenDingux_Buttons ButtonTotal = Buttons;
	while ((Buttons = GetPressedOpenDinguxButtons()) != 0)
	{
		// a) If the old buttons are a strict subset of the new buttons,
		//    add the new buttons.
		if ((Buttons | ButtonTotal) == Buttons)
			ButtonTotal |= Buttons;
		// b) If the new buttons are a strict subset of the old buttons,
		//    do nothing. (The user is releasing the buttons to return.)
		else if ((Buttons | ButtonTotal) == ButtonTotal)
			;
		// c) If the new buttons are on another path, replace the buttons
		//    completely, for example, R+X turning into R+Y.
		else
			ButtonTotal = Buttons;
		DefaultDisplayBackgroundFunction(ActiveMenu);
		SDL_Flip(OutputSurface);
		usleep(5000); // for platforms that don't sync their flips
	}
	return ButtonTotal;
}
Exemple #8
0
static void DisplayHotkeyValue(struct MenuEntry* DrawnMenuEntry, struct MenuEntry* ActiveMenuEntry)
{
	char Value[256];
	GetButtonsText(*(uint32_t*) DrawnMenuEntry->Target, Value);

	uint32_t TextWidth = GetRenderedWidth(Value);
	if (TextWidth <= GCW0_SCREEN_WIDTH - 2)
	{
		bool IsActive = (DrawnMenuEntry == ActiveMenuEntry);
		uint16_t TextColor = IsActive ? COLOR_ACTIVE_TEXT : COLOR_INACTIVE_TEXT;
		uint16_t OutlineColor = IsActive ? COLOR_ACTIVE_OUTLINE : COLOR_INACTIVE_OUTLINE;
		print_string_outline(Value, TextColor, OutlineColor, GCW0_SCREEN_WIDTH - TextWidth - 1, GetRenderedHeight(" ") * (DrawnMenuEntry->Position + 2) + 1);
	}
	else
		ReGBA_Trace("W: Hid value '%s' from the menu due to it being too long", Value);
}
Exemple #9
0
void init_sdlaudio()
{
	SDL_AudioSpec spec;

	spec.freq = OUTPUT_SOUND_FREQUENCY;
	spec.format = AUDIO_S16SYS;
	spec.channels = 2;
	spec.samples = AUDIO_OUTPUT_BUFFER_SIZE;
	spec.callback = feed_buffer;
	spec.userdata = NULL;

	if (SDL_OpenAudio(&spec, NULL) < 0) {
		ReGBA_Trace("E: Failed to open audio: %s", SDL_GetError());
		return;
	}

	SDL_PauseAudio(0);
}
Exemple #10
0
static enum OpenDingux_Buttons GrabButton(struct Menu* ActiveMenu, char* Lines[4])
{
	enum OpenDingux_Buttons Buttons;
	// Wait for the buttons that triggered the action to be released.
	while (GetPressedOpenDinguxButtons() != 0)
	{
		DefaultDisplayBackgroundFunction(ActiveMenu);
		SDL_Flip(OutputSurface);
		usleep(5000); // for platforms that don't sync their flips
	}
	// Wait until a button is pressed.
	while ((Buttons = GetPressedOpenDinguxButtons()) == 0)
	{
		DefaultDisplayBackgroundFunction(ActiveMenu);
		uint32_t Line;
		for (Line = 0; Line < 4; Line++)
		{
			uint32_t TextWidth = GetRenderedWidth(Lines[Line]);
			if (TextWidth <= GCW0_SCREEN_WIDTH - 2)
				print_string_outline(Lines[Line], COLOR_ACTIVE_TEXT, COLOR_ACTIVE_OUTLINE, (GCW0_SCREEN_WIDTH - TextWidth) / 2, (GCW0_SCREEN_HEIGHT - GetRenderedHeight(" ") * 4) / 2 + GetRenderedHeight(" ") * Line);
			else
				ReGBA_Trace("E: '%s' doesn't fit the screen! Fix this, Nebuleon!", Lines[Line]);
		}
		SDL_Flip(OutputSurface);
		usleep(5000); // for platforms that don't sync their flips
	}
	// Accumulate buttons until they're all released.
	enum OpenDingux_Buttons ButtonTotal = Buttons;
	while ((Buttons = GetPressedOpenDinguxButtons()) != 0)
	{
		ButtonTotal |= Buttons;
		DefaultDisplayBackgroundFunction(ActiveMenu);
		SDL_Flip(OutputSurface);
		usleep(5000); // for platforms that don't sync their flips
	}
	return ButtonTotal;
}
Exemple #11
0
void ReGBA_LoadSettings(char *cfg_name, bool PerGame)
{
	char fname[MAX_PATH + 1];
	if (strlen(main_path) + strlen(cfg_name) + 5 /* / .cfg */ > MAX_PATH)
	{
		ReGBA_Trace("E: Somehow you hit the filename size limit :o\n");
		return;
	}
	sprintf(fname, "%s/%s.cfg", main_path, cfg_name);

	FILE_TAG_TYPE fd;

	ReGBA_ProgressInitialise(PerGame ? FILE_ACTION_LOAD_GAME_SETTINGS : FILE_ACTION_LOAD_GLOBAL_SETTINGS);

	FILE_OPEN(fd, fname, READ);

	if(FILE_CHECK_VALID(fd)) {
		char line[257];

		while(fgets(line, 256, fd))
		{
			line[256] = '\0';

			char* opt = NULL;
			char* arg = NULL;

			char* cur = line;

			// Find the start of the option name.
			while (*cur == ' ' || *cur == '\t')
				cur++;
			// Now find where it ends.
			while (*cur && !(*cur == ' ' || *cur == '\t' || *cur == '='))
			{
				if (*cur == '#')
					continue;
				else if (opt == NULL)
					opt = cur;
				cur++;
			}
			if (opt == NULL)
				continue;
			bool WasEquals = *cur == '=';
			*cur++ = '\0';
			if (!WasEquals)
			{
				// Skip all whitespace before =.
				while (*cur == ' ' || *cur == '\t')
					cur++;
				if (*cur != '=')
					continue;
				cur++;
			}
			// Find the start of the option argument.
			while (*cur == ' ' || *cur == '\t')
				cur++;
			// Now find where it ends.
			while (*cur)
			{
				if (*cur == '#')
				{
					*cur = '\0';
					break;
				}
				else if (arg == NULL)
					arg = cur;
				cur++;
			}
			if (arg == NULL)
				continue;
			cur--;
			while (*cur == ' ' || *cur == '\t' || *cur == '\n' || *cur == '\r')
			{
				*cur = '\0';
				cur--;
			}

			struct MenuEntry* entry = Menu_FindByPersistentName(PerGame ? MainMenu.AlternateVersion : &MainMenu, opt);
			if (entry == NULL)
			{
				ReGBA_Trace("W: Option '%s' not found; ignored", opt);
			}
			else
			{
				MenuPersistenceFunction LoadFunction = entry->LoadFunction;
				if (LoadFunction == NULL) LoadFunction = &DefaultLoadFunction;
				(*LoadFunction)(entry, arg);
			}
		}
		ReGBA_ProgressUpdate(1, 1);
	}
	else
	{
		ReGBA_Trace("W: Couldn't open file %s for loading.\n", fname);
	}
	FixUpSettings();
	ReGBA_ProgressFinalise();
}
Exemple #12
0
signed int ReGBA_AudioUpdate()
{
	u32 i, j;
	s16* audio_buff;
	s16 *dst_ptr, *dst_ptr1;
	u32 n = ds2_checkAudiobuff();
	int ret;

	u8 WasInUnderrun = Stats.InSoundBufferUnderrun;
	Stats.InSoundBufferUnderrun = n == 0 && ReGBA_GetAudioSamplesAvailable() < AUDIO_LEN * 2;
	if (Stats.InSoundBufferUnderrun && !WasInUnderrun)
		Stats.SoundBufferUnderrunCount++;

	// On auto frameskip, sound buffers being full or empty determines
	// whether we're late.
	if (AUTO_SKIP)
	{
		if (n >= 2)
		{
			// We're in no hurry, because 2 buffers are still full.
			// Minimum skip 1
			if(SKIP_RATE > 1)
			{
#if defined TRACE || defined TRACE_FRAMESKIP
				ReGBA_Trace("I: Decreasing automatic frameskip: %u..%u", SKIP_RATE, SKIP_RATE - 1);
#endif
				SKIP_RATE--;
			}
		}
		else
		{
			// Maximum skip 9
			if(SKIP_RATE < 8)
			{
#if defined TRACE || defined TRACE_FRAMESKIP
				ReGBA_Trace("I: Increasing automatic frameskip: %u..%u", SKIP_RATE, SKIP_RATE + 1);
#endif
				SKIP_RATE++;
			}
		}
	}

	/* There must be AUDIO_LEN * 2 samples generated in order for the first
	 * AUDIO_LEN to be valid. Some sound is generated in the past from the
	 * future, and if the first AUDIO_LEN is grabbed before the core has had
	 * time to generate all of it (at AUDIO_LEN * 2), the end may still be
	 * silence, causing crackling. */
	if (ReGBA_GetAudioSamplesAvailable() < AUDIO_LEN * 2)
	{
		// Generate more sound first, please!
		return -1;
	}

	// We have enough sound. Complete this update.
	if (game_fast_forward || temporary_fast_forward)
	{
		if (n >= AUDIO_BUFFER_COUNT)
		{
			// Drain the buffer down to a manageable size, then exit.
			// This needs to be high to avoid audible crackling/bubbling,
			// but not so high as to require all of the sound to be emitted.
			// gpSP synchronises on the sound, after all. -Neb, 2013-03-23
			ReGBA_DiscardAudioSamples(ReGBA_GetAudioSamplesAvailable() - AUDIO_LEN);
			return 0;
		}
	}
	else
	{
		// Wait for at least one buffer to be free for audio.
		// Output assertion: The return value is between 0, inclusive,
		// and AUDIO_BUFFER_COUNT, inclusive, but can also be
		// 4294967295; that's (unsigned int) -1. (DSTWO SPECIFIC HACK)
		unsigned int n2;
		while ((n2 = ds2_checkAudiobuff()) >= AUDIO_BUFFER_COUNT && (int) n2 >= 0);
	}

	audio_buff = ds2_getAudiobuff();
	if (audio_buff == NULL) {
#if defined TRACE || defined TRACE_SOUND
		ReGBA_Trace("Recovered from the lack of a buffer");
#endif
		return -1;
	}

	dst_ptr = audio_buff; // left (stereo)
	dst_ptr1 = dst_ptr + (int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR); // right (stereo)

	for(i= 0; i < AUDIO_LEN; i += OUTPUT_FREQUENCY_DIVISOR)
	{
		s16 Left = 0, Right = 0, LeftPart, RightPart;
		for (j = 0; j < OUTPUT_FREQUENCY_DIVISOR; j++) {
			ReGBA_LoadNextAudioSample(&LeftPart, &RightPart);

			if      (LeftPart >  2047) LeftPart =  2047;
			else if (LeftPart < -2048) LeftPart = -2048;
			Left += LeftPart / OUTPUT_FREQUENCY_DIVISOR;

			if      (RightPart >  2047) RightPart =  2047;
			else if (RightPart < -2048) RightPart = -2048;
			Right += RightPart / OUTPUT_FREQUENCY_DIVISOR;
		}
		*dst_ptr++ = Left << 4;
		*dst_ptr1++ = Right << 4;
	}

	if (game_fast_forward || temporary_fast_forward)
	{
		// Dampen the sound with the previous samples written
		// (or unitialised data if we just started the emulator)
		StartFastForwardedSound(audio_buff,
			&audio_buff[(int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR)]);
		// Store the end for the next time
		EndFastForwardedSound(&audio_buff[(int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR) - DAMPEN_SAMPLE_COUNT],
			&audio_buff[(int) (AUDIO_LEN / OUTPUT_FREQUENCY_DIVISOR) * 2 - DAMPEN_SAMPLE_COUNT]);
	}

	Stats.InSoundBufferUnderrun = 0;
	ds2_updateAudio();
	return 0;
}