aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CATSFC/system/Pictochat-16.odfbin104380 -> 104365 bytes
-rw-r--r--CATSFC/system/language.msg18
-rw-r--r--README.md24
-rw-r--r--source/font/Pictochat-16.bdf36
-rw-r--r--source/images/hotkeys-preview.psdbin0 -> 43042 bytes
-rw-r--r--source/nds/draw.c26
-rw-r--r--source/nds/entry.cpp26
-rw-r--r--source/nds/gui.c172
-rw-r--r--source/soundux.cpp17
9 files changed, 271 insertions, 48 deletions
diff --git a/CATSFC/system/Pictochat-16.odf b/CATSFC/system/Pictochat-16.odf
index 84edb64..a52b219 100644
--- a/CATSFC/system/Pictochat-16.odf
+++ b/CATSFC/system/Pictochat-16.odf
Binary files differ
diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg
index b8b8199..126c8c2 100644
--- a/CATSFC/system/language.msg
+++ b/CATSFC/system/language.msg
@@ -78,8 +78,7 @@ Temporary fast-forward
#MSG_HOTKEY_SOUND_TOGGLE
Toggle sound
#MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS
-Press the buttons you wish to use to perform\n
-this action.
+Press the buttons you wish to use to perform this action.
#MSG_HOTKEY_DELETE_WITH_A
[A] Clear
#MSG_HOTKEY_CANCEL_WITH_B
@@ -141,8 +140,7 @@ No game is currently loaded
#MSG_CHEAT_ELEMENT_NOT_LOADED
<None loaded here>
#MSG_SAVESTATE_FULL
-The current slot holds a state.\n
-Do you wish to overwrite it?
+The current slot holds a state. Do you wish to overwrite it?
#MSG_PROGRESS_SAVED_STATE_CREATING
Saving state...
#MSG_PROGRESS_SAVED_STATE_CREATION_FAILED
@@ -274,8 +272,7 @@ Temporary fast-forward
#MSG_HOTKEY_SOUND_TOGGLE
Toggle sound
#MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS
-Press the buttons you wish to use to perform\n
-this action.
+Press the buttons you wish to use to perform this action.
#MSG_HOTKEY_DELETE_WITH_A
[A] Clear
#MSG_HOTKEY_CANCEL_WITH_B
@@ -337,8 +334,7 @@ this action.
#MSG_CHEAT_ELEMENT_NOT_LOADED
<没有加载>
#MSG_SAVESTATE_FULL
-当前存档槽已有存档文件,\n
-覆盖已有存档吗?
+当前存档槽已有存档文件,覆盖已有存档吗?
#MSG_PROGRESS_SAVED_STATE_CREATING
正在写入...
#MSG_PROGRESS_SAVED_STATE_CREATION_FAILED
@@ -470,8 +466,7 @@ Avance rapide temporaire
#MSG_HOTKEY_SOUND_TOGGLE
(Dés)activer le son
#MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS
-Appuyez sur les boutons que vous voulez utiliser\n
-pour effectuer cette action.
+Appuyez sur les boutons que vous voulez utiliser pour effectuer cette action.
#MSG_HOTKEY_DELETE_WITH_A
[A] Effacer
#MSG_HOTKEY_CANCEL_WITH_B
@@ -533,8 +528,7 @@ Aucun jeu n'est actuellement chargé
#MSG_CHEAT_ELEMENT_NOT_LOADED
<Aucun chargé ici>
#MSG_SAVESTATE_FULL
-Il y a une sauvegarde dans cet emplacement.\n
-Voulez-vous l'écraser?
+Il y a une sauvegarde dans cet emplacement. Voulez-vous l'écraser?
#MSG_PROGRESS_SAVED_STATE_CREATING
Sauvegarde en cours...
#MSG_PROGRESS_SAVED_STATE_CREATION_FAILED
diff --git a/README.md b/README.md
index ec54da2..b55f80d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-CATSFC version 1.22, 2013-01-20
+CATSFC version 1.23, 2013-01-22
A Super Nintendo emulator for the Supercard DSTWO.
@@ -86,6 +86,28 @@ It is recommended to start with frame skipping 4 (Show 1 frame every 5) and
go to 3 or 2 if the game doesn't run with major slowdowns with them. If you
don't like the slowdowns, return to frame skipping 4 or -.
+# Hotkeys
+
+You can set buttons to press to perform certain actions. For each action,
+there is a *global hotkey* and a *game-specific override hotkey*. You might,
+for example, want to have the R button bound to Temporary fast-forward, but
+a specific game uses R for something important. In that case, you can set the
+global hotkey to R and make an override with X for that game.
+
+Hotkeys are sent to the current game as well as to their corresponding action.
+The criterion for a hotkey is met when **at least** all of its buttons are
+held. Additional keys are sent to the game and can trigger another hotkey.
+For example, setting a hotkey to L and another to R+X, then pressing L+R+X+Y
+will trigger both and send L+R+X+Y to the game.
+
+Available actions are:
+* Go to main menu. In addition to tapping the Touch Screen to return to
+ the main menu, you can set a hotkey to do the same.
+* Temporary fast-forward. While this hotkey is held, the fast-forward option
+ will be forced on.
+* Toggle sound. Each time this hotkey is held, the sound will be disabled if
+ it's currently enabled, and vice-versa.
+
# The font
The font used by CATSFC is now similar to the Pictochat font. To modify it,
diff --git a/source/font/Pictochat-16.bdf b/source/font/Pictochat-16.bdf
index 4a07e0b..a512814 100644
--- a/source/font/Pictochat-16.bdf
+++ b/source/font/Pictochat-16.bdf
@@ -1,7 +1,7 @@
STARTFONT 2.1
FONT -FontForge-Pictochat-Book-R-Normal--16-150-75-75-P-53-ISO10646-1
SIZE 15 75 75
-FONTBOUNDINGBOX 23 13 0 -1
+FONTBOUNDINGBOX 12 13 0 -1
COMMENT "Generated by fontforge, http://fontforge.sourceforge.net"
STARTPROPERTIES 37
FAMILY_NAME "Pictochat"
@@ -2657,27 +2657,27 @@ FF80
ENDCHAR
STARTCHAR uni05CE
ENCODING 1486
-SWIDTH 1250 0
-DWIDTH 20 0
-BBX 19 5 0 2
+SWIDTH 625 0
+DWIDTH 10 0
+BBX 7 5 1 2
BITMAP
-6E4CE0
-84AA40
-44EC40
-24AA40
-C4AA40
+6E
+84
+44
+24
+C4
ENDCHAR
STARTCHAR uni05CF
ENCODING 1487
-SWIDTH 1500 0
-DWIDTH 24 0
-BBX 23 5 0 2
-BITMAP
-6E8E6E
-888884
-4C8E84
-288884
-CEEE64
+SWIDTH 875 0
+DWIDTH 14 0
+BBX 11 5 1 2
+BITMAP
+6E80
+8880
+4C80
+2880
+CEE0
ENDCHAR
STARTCHAR quotedblleft
ENCODING 8220
diff --git a/source/images/hotkeys-preview.psd b/source/images/hotkeys-preview.psd
new file mode 100644
index 0000000..2307b0d
--- /dev/null
+++ b/source/images/hotkeys-preview.psd
Binary files differ
diff --git a/source/nds/draw.c b/source/nds/draw.c
index f373aa3..3eab510 100644
--- a/source/nds/draw.c
+++ b/source/nds/draw.c
@@ -883,24 +883,42 @@ u32 draw_hotkey_dialog(enum SCREEN_ID screen, u32 sy, char *clear, char *cancel)
ds2_flipScreen(screen, 2);
- // While there are no keys pressed, wait for keys.
+ // This function has been started by a key press. Wait for it to end.
struct key_buf inputdata;
do {
mdelay(1);
ds2_getrawInput(&inputdata);
+ } while (inputdata.key != 0);
+
+ // While there are no keys pressed, wait for keys.
+ do {
+ mdelay(1);
+ ds2_getrawInput(&inputdata);
} while (inputdata.key == 0);
// Now, while there are keys pressed, keep a tally of keys that have
// been pressed. (IGNORE TOUCH AND LID! Otherwise, closing the lid or
// touching to get to the menu will do stuff the user doesn't expect.
// Also ignore the direction pad because every game uses it.)
- u32 TotalKeys = inputdata.key;
+ u32 TotalKeys = 0;
do {
+ TotalKeys |= inputdata.key & ~(KEY_TOUCH | KEY_LID | KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT);
+ // If there's a touch on either button, turn it into a
+ // clear (A) or cancel (B) request.
+ if (inputdata.key & KEY_TOUCH)
+ {
+ if (inputdata.y >= 128 && inputdata.y < 128 + ICON_BUTTON.y)
+ {
+ if (inputdata.x >= 49 && inputdata.x < 49 + ICON_BUTTON.x)
+ return KEY_A;
+ else if (inputdata.x >= 136 && inputdata.x < 136 + ICON_BUTTON.x)
+ return KEY_B;
+ }
+ }
mdelay(1);
ds2_getrawInput(&inputdata);
- TotalKeys |= inputdata.key & ~(KEY_TOUCH | KEY_LID | KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT);
- } while (inputdata.key != 0);
+ } while (inputdata.key != 0 || TotalKeys == 0);
return TotalKeys;
}
diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp
index 792608a..702442e 100644
--- a/source/nds/entry.cpp
+++ b/source/nds/entry.cpp
@@ -1064,6 +1064,8 @@ const unsigned int keymap[12] = {
};
*/
+static bool8 SoundToggleWasHeld = FALSE;
+
unsigned int S9xReadJoypad (int which1)
{
struct key_buf inputdata;
@@ -1082,9 +1084,31 @@ unsigned int S9xReadJoypad (int which1)
set_cpu_clock(clock_speed_number);
}
- if(inputdata.key & KEY_TOUCH) //Active menu
+ u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu;
+ u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward;
+ u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound;
+
+ if(inputdata.key & KEY_TOUCH ||
+ (HotkeyReturnToMenu && ((inputdata.key & HotkeyReturnToMenu) == HotkeyReturnToMenu))
+ ) //Active menu
Settings.Paused = 1;
+ temporary_fast_forward =
+ (HotkeyTemporaryFastForward && ((inputdata.key & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward))
+ ;
+
+ bool8 SoundToggleIsHeld =
+ (HotkeyToggleSound && ((inputdata.key & HotkeyToggleSound) == HotkeyToggleSound))
+ ;
+
+ if (SoundToggleIsHeld && !SoundToggleWasHeld)
+ {
+ game_enable_audio = !game_enable_audio;
+ game_disableAudio();
+ }
+
+ SoundToggleWasHeld = SoundToggleIsHeld;
+
if(which1 < 1)
{
unsigned int key;
diff --git a/source/nds/gui.c b/source/nds/gui.c
index 293361f..09e01ac 100644
--- a/source/nds/gui.c
+++ b/source/nds/gui.c
@@ -61,7 +61,7 @@ char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lan
******************************************************************************/
#define SUBMENU_ROW_NUM 6
-#define NDSSFC_VERSION "1.22"
+#define NDSSFC_VERSION "1.23"
#define SAVE_STATE_SLOT_NUM 16
@@ -1710,6 +1710,19 @@ u32 menu(u16 *screen)
auto void time_period_passive();
auto void time_period_action();
auto void tools_menu_init();
+ auto void obtain_hotkey (u32 *HotkeyBitfield);
+ auto void set_global_hotkey_return_to_menu();
+ auto void set_global_hotkey_temporary_fast_forward();
+ auto void set_global_hotkey_toggle_sound();
+ auto void set_game_specific_hotkey_return_to_menu();
+ auto void set_game_specific_hotkey_temporary_fast_forward();
+ auto void set_game_specific_hotkey_toggle_sound();
+ auto void global_hotkey_return_to_menu_passive();
+ auto void global_hotkey_temporary_fast_forward_passive();
+ auto void global_hotkey_toggle_sound_passive();
+ auto void game_specific_hotkey_return_to_menu_passive();
+ auto void game_specific_hotkey_temporary_fast_forward_passive();
+ auto void game_specific_hotkey_toggle_sound_passive();
auto void load_default_setting();
auto void check_gbaemu_version();
auto void load_lastest_played();
@@ -2468,9 +2481,9 @@ u32 menu(u16 *screen)
{
}
-#define CHEAT_NUMBER_X 26
-#define CHEAT_DESC_X 52
-#define CHEAT_DESC_SX 163
+#define CHEAT_NUMBER_X 23
+#define CHEAT_DESC_X 49
+#define CHEAT_DESC_SX 166
#define CHEAT_ACTIVE_X 225
void cheat_option_passive()
@@ -2891,6 +2904,39 @@ u32 menu(u16 *screen)
};
MAKE_MENU(tools_screensnap, NULL, NULL, NULL, NULL, 0, 0);
+
+ /*--------------------------------------------------------
+ Tools - Global hotkeys
+ --------------------------------------------------------*/
+ MENU_OPTION_TYPE tools_global_hotkeys_options[] =
+ {
+ /* 00 */ SUBMENU_OPTION(&tools_menu, &msg[MSG_TOOLS_GLOBAL_HOTKEY_GENERAL], NULL, 0),
+
+ /* 01 */ ACTION_OPTION(set_global_hotkey_return_to_menu, global_hotkey_return_to_menu_passive, &msg[MSG_HOTKEY_MAIN_MENU], NULL, 1),
+
+ /* 02 */ ACTION_OPTION(set_global_hotkey_temporary_fast_forward, global_hotkey_temporary_fast_forward_passive, &msg[MSG_HOTKEY_TEMPORARY_FAST_FORWARD], NULL, 2),
+
+ /* 03 */ ACTION_OPTION(set_global_hotkey_toggle_sound, global_hotkey_toggle_sound_passive, &msg[MSG_HOTKEY_SOUND_TOGGLE], NULL, 3)
+ };
+
+ MAKE_MENU(tools_global_hotkeys, NULL, NULL, NULL, NULL, 0, 0);
+
+ /*--------------------------------------------------------
+ Tools - Game-specific hotkey overrides
+ --------------------------------------------------------*/
+ MENU_OPTION_TYPE tools_game_specific_hotkeys_options[] =
+ {
+ /* 00 */ SUBMENU_OPTION(&tools_menu, &msg[MSG_TOOLS_GAME_HOTKEY_GENERAL], NULL, 0),
+
+ /* 01 */ ACTION_OPTION(set_game_specific_hotkey_return_to_menu, game_specific_hotkey_return_to_menu_passive, &msg[MSG_HOTKEY_MAIN_MENU], NULL, 1),
+
+ /* 02 */ ACTION_OPTION(set_game_specific_hotkey_temporary_fast_forward, game_specific_hotkey_temporary_fast_forward_passive, &msg[MSG_HOTKEY_TEMPORARY_FAST_FORWARD], NULL, 2),
+
+ /* 03 */ ACTION_OPTION(set_game_specific_hotkey_toggle_sound, game_specific_hotkey_toggle_sound_passive, &msg[MSG_HOTKEY_SOUND_TOGGLE], NULL, 3)
+ };
+
+ MAKE_MENU(tools_game_specific_hotkeys, NULL, NULL, NULL, NULL, 0, 0);
+
/*--------------------------------------------------------
Tools
--------------------------------------------------------*/
@@ -2900,6 +2946,10 @@ u32 menu(u16 *screen)
/* 01 */ SUBMENU_OPTION(&tools_screensnap_menu, &msg[MSG_TOOLS_SCREENSHOT_GENERAL], NULL, 1),
+ /* 02 */ SUBMENU_OPTION(&tools_global_hotkeys_menu, &msg[MSG_TOOLS_GLOBAL_HOTKEY_GENERAL], NULL, 2),
+
+ /* 03 */ SUBMENU_OPTION(&tools_game_specific_hotkeys_menu, &msg[MSG_TOOLS_GAME_HOTKEY_GENERAL], NULL, 3)
+
// /* 02 */ SUBMENU_OPTION(&tools_keyremap_menu, &msg[MSG_SUB_MENU_31], NULL, 2),
// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options,
@@ -3145,6 +3195,114 @@ u32 menu(u16 *screen)
else
tools_options[4].option_type |= HIDEN_TYPE; */
// OUT OF BOUNDS MEMORY ACCESS, REENABLE IF NEEDED [NEB]
+ if (first_load)
+ tools_options[3] /* game hotkeys */.option_type |= HIDEN_TYPE;
+ else
+ tools_options[3] /* game hotkeys */.option_type &= ~HIDEN_TYPE;
+ }
+
+ void obtain_hotkey (u32 *HotkeyBitfield)
+ {
+ draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
+ draw_string_vcenter(down_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS]);
+
+ u32 Keys = draw_hotkey_dialog(DOWN_SCREEN, 115, msg[MSG_HOTKEY_DELETE_WITH_A], msg[MSG_HOTKEY_CANCEL_WITH_B]);
+ if (Keys == KEY_B)
+ ; // unmodified
+ else if (Keys == KEY_A)
+ *HotkeyBitfield = 0; // clear
+ else
+ *HotkeyBitfield = Keys; // set
+ }
+
+ void set_global_hotkey_return_to_menu()
+ {
+ obtain_hotkey(&emu_config.HotkeyReturnToMenu);
+ }
+
+ void set_global_hotkey_temporary_fast_forward()
+ {
+ obtain_hotkey(&emu_config.HotkeyTemporaryFastForward);
+ }
+
+ void set_global_hotkey_toggle_sound()
+ {
+ obtain_hotkey(&emu_config.HotkeyToggleSound);
+ }
+
+ void set_game_specific_hotkey_return_to_menu()
+ {
+ obtain_hotkey(&game_config.HotkeyReturnToMenu);
+ }
+
+ void set_game_specific_hotkey_temporary_fast_forward()
+ {
+ obtain_hotkey(&game_config.HotkeyTemporaryFastForward);
+ }
+
+ void set_game_specific_hotkey_toggle_sound()
+ {
+ obtain_hotkey(&game_config.HotkeyToggleSound);
+ }
+
+#define HOTKEY_CONTENT_X 156
+ void hotkey_option_passive_common(u32 HotkeyBitfield)
+ {
+ unsigned short color;
+ char tmp_buf[512];
+ unsigned int len;
+
+ if(display_option == current_option)
+ color= COLOR_ACTIVE_ITEM;
+ else
+ color= COLOR_INACTIVE_ITEM;
+
+ strcpy(tmp_buf, *(display_option->display_string));
+ PRINT_STRING_BG(down_screen_addr, tmp_buf, color, COLOR_TRANS, 23, 40 + display_option-> line_number*27);
+
+ // Construct a UTF-8 string showing the buttons in the
+ // bitfield.
+ tmp_buf[0] = '\0';
+ if (HotkeyBitfield & KEY_L) strcpy(tmp_buf, HOTKEY_L_DISPLAY);
+ if (HotkeyBitfield & KEY_R) strcat(tmp_buf, HOTKEY_R_DISPLAY);
+ if (HotkeyBitfield & KEY_A) strcat(tmp_buf, HOTKEY_A_DISPLAY);
+ if (HotkeyBitfield & KEY_B) strcat(tmp_buf, HOTKEY_B_DISPLAY);
+ if (HotkeyBitfield & KEY_Y) strcat(tmp_buf, HOTKEY_Y_DISPLAY);
+ if (HotkeyBitfield & KEY_X) strcat(tmp_buf, HOTKEY_X_DISPLAY);
+ if (HotkeyBitfield & KEY_START) strcat(tmp_buf, HOTKEY_START_DISPLAY);
+ if (HotkeyBitfield & KEY_SELECT) strcat(tmp_buf, HOTKEY_SELECT_DISPLAY);
+
+ PRINT_STRING_BG(down_screen_addr, tmp_buf, color, COLOR_TRANS, HOTKEY_CONTENT_X, 40 + display_option-> line_number*27);
+ }
+
+ void global_hotkey_return_to_menu_passive()
+ {
+ hotkey_option_passive_common(emu_config.HotkeyReturnToMenu);
+ }
+
+ void global_hotkey_temporary_fast_forward_passive()
+ {
+ hotkey_option_passive_common(emu_config.HotkeyTemporaryFastForward);
+ }
+
+ void global_hotkey_toggle_sound_passive()
+ {
+ hotkey_option_passive_common(emu_config.HotkeyToggleSound);
+ }
+
+ void game_specific_hotkey_return_to_menu_passive()
+ {
+ hotkey_option_passive_common(game_config.HotkeyReturnToMenu);
+ }
+
+ void game_specific_hotkey_temporary_fast_forward_passive()
+ {
+ hotkey_option_passive_common(game_config.HotkeyTemporaryFastForward);
+ }
+
+ void game_specific_hotkey_toggle_sound_passive()
+ {
+ hotkey_option_passive_common(game_config.HotkeyToggleSound);
}
int lastest_game_menu_scroll_value;
@@ -3615,6 +3773,8 @@ u32 menu(u16 *screen)
}
else if(current_option->option_type & ACTION_TYPE)
current_option->action_function();
+ else if(current_option->option_type & SUBMENU_TYPE)
+ choose_menu(current_option->sub_menu);
}
/* Save states */
else if(current_menu == (main_menu.options + 1)->sub_menu)
@@ -3894,6 +4054,10 @@ u32 menu(u16 *screen)
ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
} // end while
+
+ if (current_menu && current_menu->end_function)
+ current_menu->end_function();
+
destroy_dynamic_cheats();
if(bg_screenp != NULL) free((void*)bg_screenp);
diff --git a/source/soundux.cpp b/source/soundux.cpp
index a3103e7..fda2e25 100644
--- a/source/soundux.cpp
+++ b/source/soundux.cpp
@@ -429,24 +429,25 @@ void S9xSetFilterCoefficient (int tap, int value)
void S9xSetSoundADSR (int channel, int attack_rate, int decay_rate,
int sustain_rate, int sustain_level, int release_rate)
{
- SoundData.channels[channel].attack_rate = attack_rate;
- SoundData.channels[channel].decay_rate = decay_rate;
- SoundData.channels[channel].sustain_rate = sustain_rate;
- SoundData.channels[channel].release_rate = release_rate;
- SoundData.channels[channel].sustain_level = sustain_level + 1;
+ Channel *ch = &SoundData.channels[channel];
+ ch->attack_rate = attack_rate;
+ ch->decay_rate = decay_rate;
+ ch->sustain_rate = sustain_rate;
+ ch->release_rate = release_rate;
+ ch->sustain_level = sustain_level + 1;
switch (SoundData.channels[channel].state)
{
case SOUND_ATTACK:
- S9xSetEnvelopeRate (channel, attack_rate, 1, 127);
+ S9xSetEnvRate (ch, attack_rate, 1, 127);
break;
case SOUND_DECAY:
- S9xSetEnvelopeRate (channel, decay_rate, -1,
+ S9xSetEnvRate (ch, decay_rate, -1,
(MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3);
break;
case SOUND_SUSTAIN:
- S9xSetEnvelopeRate (channel, sustain_rate, -1, 0);
+ S9xSetEnvRate (ch, sustain_rate, -1, 0);
break;
}
}