Added support for switching the keyboard layout

(from Crafty, closes #590)

Minor edits to some documents and LoadOrder.cpp.
This commit is contained in:
NovaRain
2025-09-17 20:47:04 +08:00
parent a0967aa12a
commit 90dfe16b22
5 changed files with 110 additions and 13 deletions
+9
View File
@@ -1,4 +1,13 @@
[sfall] [sfall]
;Table for overriding ASCII codes for keyboard character input when entering the player's name and saved game descriptions
;Only character codes in the ASCII range 33-126 can be overridden
;Character codes that do not need to be overridden can be omitted by using commas as delimiters
;You must also set a key for switching layouts using the XltKey option in ddraw.ini
;Default character code table for the English layout (letter codes only)
;XltTable=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,,,,,,,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,,,,
;##############################################################################
SaveInCombat=Cannot save at this time. SaveInCombat=Cannot save at this time.
KarmaGain=You gained %d karma. KarmaGain=You gained %d karma.
KarmaLoss=You lost %d karma. KarmaLoss=You lost %d karma.
+5 -2
View File
@@ -1,9 +1,12 @@
sfall's main configuration options appear in ddraw.ini, but there are several other configuration files that it can read in for modding purposes. sfall's main configuration options appear in ddraw.ini, but there are several other configuration files that it can read in for modding purposes.
Books.ini: Lets you override/add books to the game (associated object PIDs, skills and text messages) Books.ini: Lets you override/add books to the game (associated object PIDs, skills, and text messages)
Drugs.ini: Lets you override/add drugs to the game (associated object PIDs, addiction duration, and text messages)
Perks.ini: Lets you override the name/description/frm image/other stats of perks and traits Perks.ini: Lets you override the name/description/frm image/other stats of perks and traits
Elevators.ini: Lets you override which elevators lead where Elevators.ini: Lets you override which elevators lead to where
CriticalOverrides.ini: Lets you make modifications to the critical hit tables CriticalOverrides.ini: Lets you make modifications to the critical hit tables
Translations.ini: Contains some text strings which sfall displays, to allow their translation Translations.ini: Contains some text strings which sfall displays, to allow their translation
Skills.ini: Lets you change the formula used for calculating skills Skills.ini: Lets you change the formula used for calculating skills
Stats.ini: Lets you change the formula used to calculate the derived stats Stats.ini: Lets you change the formula used to calculate the derived stats
Tweaks.ini: Lets you override a few object PIDs used in the engine
Unarmed.ini: Lets you configure the requirements and effects of unarmed attacks
+5 -1
View File
@@ -228,7 +228,7 @@ SpeedKey9=0x00
;A key to hold down to move the window around when using DX9 graphics mode 5 ;A key to hold down to move the window around when using DX9 graphics mode 5
;Set to 0 if you don't want to use a modifier key, or a DX scancode otherwise ;Set to 0 if you don't want to use a modifier key, or a DX scancode otherwise
;Set to -1 for either ctrl key, -2 for either alt key or -3 for either shift key ;Set to -1 for either Ctrl key, -2 for either Alt key, or -3 for either Shift key
WindowScrollKey=0 WindowScrollKey=0
;A key to press to reload your currently equipped weapon or use the active item ;A key to press to reload your currently equipped weapon or use the active item
@@ -254,6 +254,10 @@ ItemMoveSkipDragKey=29
;Requires sfall debugging mode and FalloutDebug.exe from the modders pack ;Requires sfall debugging mode and FalloutDebug.exe from the modders pack
DebugEditorKey=0 DebugEditorKey=0
;A key to press to switch the keyboard layout (uses character codes from the XltTable option in Translations.ini)
;Set to 1 for Num Lock, 2 for Caps Lock, 3 for Scroll Lock, or 0 to disable
XltKey=0
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Misc] [Misc]
;Changes some of Fallout 2 engine functions to Fallout 1 behavior: ;Changes some of Fallout 2 engine functions to Fallout 1 behavior:
+86 -4
View File
@@ -16,10 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//#include "..\InputFuncs.h" #include "..\main.h"
#include "..\Logging.h" #include "..\FalloutEngine\Fallout2.h"
#include "..\SafeWrite.h" #include "..\InputFuncs.h"
//#include "LoadGameHook.h" #include "..\Translate.h"
#include "ScriptExtender.h" #include "ScriptExtender.h"
#include "Input.h" #include "Input.h"
@@ -27,12 +27,94 @@
namespace sfall namespace sfall
{ {
#define TABLE_SIZE (94) // for ASCII code 33-126
static BYTE xltTable[TABLE_SIZE];
static signed char xltKey; // 4 = Scroll Lock, 2 = Caps Lock, 1 = Num Lock
static DWORD getInputStrRet;
static void __declspec(naked) get_input_str_hack() {
__asm { // al - key ASCII code, in range 32-126
pop getInputStrRet;
push ecx;
mov cl, xltKey;
test ds:[FO_VAR_kb_lock_flags], cl;
jz end;
and eax, 0xFF;
cmp eax, 32; // skip the space char
je end;
mov al, [xltTable + eax - 33];
end:
mov [esp + esi + 4], al;
jmp getInputStrRet;
}
}
static void __declspec(naked) get_input_str2_hack() {
__asm { // al - key ASCII code, in range 32-126
pop getInputStrRet;
push edx;
mov dl, xltKey;
test byte ptr ds:[FO_VAR_kb_lock_flags], dl;
jz end;
and eax, 0xFF;
cmp eax, 32; // skip the space char
je end;
mov al, [xltTable + eax - 33];
end:
mov [esp + edi + 4], al;
jmp getInputStrRet;
}
}
static void __declspec(naked) kb_next_ascii_English_US_hack() {
__asm {
mov dh, [eax];
cmp dh, DIK_LBRACKET;
je end;
cmp dh, DIK_RBRACKET;
je end;
cmp dh, DIK_SEMICOLON;
je end;
cmp dh, DIK_APOSTROPHE;
je end;
cmp dh, DIK_COMMA;
je end;
cmp dh, DIK_PERIOD;
je end;
cmp dh, DIK_B;
end:
retn;
}
}
void Input::init() { void Input::init() {
//if (IniReader::GetConfigInt("Input", "Enable", 0)) { //if (IniReader::GetConfigInt("Input", "Enable", 0)) {
dlogr("Applying input patch.", DL_INIT); dlogr("Applying input patch.", DL_INIT);
SafeWrite32(0x4DE902, 0x50FB50); // "DDRAW.DLL" SafeWrite32(0x4DE902, 0x50FB50); // "DDRAW.DLL"
::sfall::availableGlobalScriptTypes |= 1; ::sfall::availableGlobalScriptTypes |= 1;
//} //}
xltKey = IniReader::GetConfigInt("Input", "XltKey", 0);
if (xltKey > 0) {
auto codeList = Translate::GetList("sfall", "XltTable", "", ',');
size_t numCodes = codeList.size();
if (numCodes > 0) {
dlogr("Applying alternate keyboard character codes patch.", DL_INIT);
for (size_t i = 0; i < TABLE_SIZE; i++) {
int code = (i < numCodes) ? atoi(codeList[i].c_str()) : 0;
xltTable[i] = (code > 32 && code < 256)
? static_cast<BYTE>(code)
: static_cast<BYTE>(i + 33); // invalid char code, use default
}
if (xltKey > 2) xltKey = 4;
MakeCall(0x433F3E, get_input_str_hack);
MakeCall(0x47F364, get_input_str2_hack);
MakeCall(0x4CC358, kb_next_ascii_English_US_hack);
SafeWriteBatch<BYTE>(0x7E, {0x433ED6, 0x47F2F7}); // max ASCII code value allowed to input (was 122)
}
}
} }
} }
+5 -6
View File
@@ -614,11 +614,11 @@ noFile:
static DWORD hrpLoadRIX_func; static DWORD hrpLoadRIX_func;
static DWORD hrpLoadBMP_func; static DWORD hrpLoadBMP_func;
static DWORD hrpSplashScrnRet;
static __declspec(naked) void game_splash_screen_hook_rix_HRP() { static __declspec(naked) void game_splash_screen_hook_rix_HRP() {
static DWORD retAddr;
__asm { __asm {
pop retAddr; pop hrpSplashScrnRet;
call hrpLoadRIX_func; call hrpLoadRIX_func;
test al, al test al, al
jnz end; jnz end;
@@ -635,15 +635,14 @@ static __declspec(naked) void game_splash_screen_hook_rix_HRP() {
push esi; // IMAGE8 data push esi; // IMAGE8 data
call hrpLoadRIX_func; call hrpLoadRIX_func;
end: end:
jmp retAddr; jmp hrpSplashScrnRet;
} }
} }
static __declspec(naked) void game_splash_screen_hook_bmp_HRP() { static __declspec(naked) void game_splash_screen_hook_bmp_HRP() {
static const char* splashFmt = "%ssplash%d.bmp"; static const char* splashFmt = "%ssplash%d.bmp";
static DWORD retAddr;
__asm { __asm {
pop retAddr; pop hrpSplashScrnRet;
call hrpLoadBMP_func; call hrpLoadBMP_func;
test al, al test al, al
jnz end; jnz end;
@@ -660,7 +659,7 @@ static __declspec(naked) void game_splash_screen_hook_bmp_HRP() {
push esi; // IMAGE8 data push esi; // IMAGE8 data
call hrpLoadBMP_func; call hrpLoadBMP_func;
end: end:
jmp retAddr; jmp hrpSplashScrnRet;
} }
} }