diff --git a/.gitignore b/.gitignore index 5a3af07..c878590 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,9 @@ *.filters *.sln *.user +*.tlog +.vs/ bin/ lib/ *.dir/ @@ -34,12 +36,6 @@ steamshim_parent/build/ object_script.* rpgscript.bat rpgscript - mklang.bat -oneshot_JA_2_merge.pot -oneshot_JA_2_merge-jpn.pot -oneshot_JA_2_ver4.pot -oneshot_JA_2_fixed_ver3.pot -oneshot_JA_2_ver3_checked.pot -oneshot_JA_Mariko1_WIP.pot *.pot xScripts.rxdata diff --git a/journal/w32/.gitignore b/journal/w32/.gitignore new file mode 100644 index 0000000..53e7d64 --- /dev/null +++ b/journal/w32/.gitignore @@ -0,0 +1,7 @@ +.vs +Debug +journal/Debug +!*.sln +!*.vcxproj +!*.vcxproj.filters +!*.bmp \ No newline at end of file diff --git a/journal/w32/journal.sln b/journal/w32/journal.sln new file mode 100644 index 0000000..303676e --- /dev/null +++ b/journal/w32/journal.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30309.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "journal", "journal\journal.vcxproj", "{0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Debug|x64.ActiveCfg = Debug|x64 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Debug|x64.Build.0 = Debug|x64 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Debug|x86.ActiveCfg = Debug|Win32 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Debug|x86.Build.0 = Debug|Win32 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Release|x64.ActiveCfg = Release|x64 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Release|x64.Build.0 = Release|x64 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Release|x86.ActiveCfg = Release|Win32 + {0AC54FE5-AE4B-4B4F-9B06-2A29101AE745}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FE54145F-EE02-422A-BE71-80A6862C6C91} + EndGlobalSection +EndGlobal diff --git a/journal/w32/journal/img/default.bmp b/journal/w32/journal/img/default.bmp new file mode 100644 index 0000000..e25e1ee Binary files /dev/null and b/journal/w32/journal/img/default.bmp differ diff --git a/journal/w32/journal/img/niko1.bmp b/journal/w32/journal/img/niko1.bmp new file mode 100644 index 0000000..e47ee1d Binary files /dev/null and b/journal/w32/journal/img/niko1.bmp differ diff --git a/journal/w32/journal/img/niko2.bmp b/journal/w32/journal/img/niko2.bmp new file mode 100644 index 0000000..54371c8 Binary files /dev/null and b/journal/w32/journal/img/niko2.bmp differ diff --git a/journal/w32/journal/img/niko3.bmp b/journal/w32/journal/img/niko3.bmp new file mode 100644 index 0000000..ea317b7 Binary files /dev/null and b/journal/w32/journal/img/niko3.bmp differ diff --git a/journal/w32/journal/journal.vcxproj b/journal/w32/journal/journal.vcxproj new file mode 100644 index 0000000..e8d7617 --- /dev/null +++ b/journal/w32/journal/journal.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + 16.0 + Win32Proj + {0ac54fe5-ae4b-4b4f-9b06-2a29101ae745} + journal + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/journal/w32/journal/journal.vcxproj.filters b/journal/w32/journal/journal.vcxproj.filters new file mode 100644 index 0000000..5d136f8 --- /dev/null +++ b/journal/w32/journal/journal.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/journal/w32/icon.ico b/journal/w32/journal/src/icon.ico similarity index 100% rename from journal/w32/icon.ico rename to journal/w32/journal/src/icon.ico diff --git a/journal/w32/journal.c b/journal/w32/journal/src/journal.c similarity index 70% rename from journal/w32/journal.c rename to journal/w32/journal/src/journal.c index 68b7736..45b9af6 100644 --- a/journal/w32/journal.c +++ b/journal/w32/journal/src/journal.c @@ -1,5 +1,8 @@ #define WINVER 0x0600 #define _WIN32_WINNT 0x0600 +// needed to suppress warnings about wcscpy and such +#define _CRT_SECURE_NO_WARNINGS 1 + #include #include #include @@ -8,6 +11,7 @@ #define DEFAULT_WIDTH 800 #define DEFAULT_HEIGHT 600 #define IN_BUFFER_SIZE 256 +#define IMAGE_PATH_MAX_SIZE 512 #define WINDOW_STYLE (WS_OVERLAPPEDWINDOW ^ (WS_THICKFRAME | WS_MAXIMIZEBOX)) @@ -20,25 +24,61 @@ static DWORD err = 0; static HWND window = NULL; +static char DataPath[512]; + static void loadImage(const char *name) { - char copy_space[IN_BUFFER_SIZE]; - const char* lang_ptr; + char imagePath[IMAGE_PATH_MAX_SIZE]; + if (image_handle) { DeleteObject(image_handle); } - image_handle = LoadBitmapA(GetModuleHandleW(NULL), name); - // In the event we can't find an image's translated value - // try to find a matching resource without any language code suffix - if (!image_handle) { - lang_ptr = strchr(name, '_'); - if (lang_ptr) { - memset(copy_space, 0, IN_BUFFER_SIZE); - strncpy(copy_space, name, lang_ptr - name); - //terminate the string because I guess strncpy doesn't - image_handle = LoadBitmapA(GetModuleHandleW(NULL), copy_space); - if (!image_handle) { - err = GetLastError(); - } + + // handle default as a special case, since we'll keep that image internally + if (strcmp(name, "default") == 0) { + image_handle = LoadBitmapA(GetModuleHandleW(NULL), "default"); + } + else { + // names come in the format XX_YY + // where XX is the image (ex: c1) + // and YY is the lang code (ex: ja, or pt_br) + // so let's separate this into 2 char pointers + char imageName[IN_BUFFER_SIZE]; + char* langCode = 0; + char* emptyString = "\0"; + strcpy(imageName, name); + langCode = strchr(imageName, '_'); + if (langCode > 0) { + // replace the code with 0 to null terminate the image name where this is + // then use the rest of the string as the language code + // so c1_ja becomes "c1\0ja", thus imageName is "c1" and then langCode is "ja" + (*langCode) = 0; + langCode++; + } + else { + langCode = emptyString; + } + + // build imagePath + strcpy(imagePath, DataPath); + strcat(imagePath, "Graphics\\Journal\\"); + strcat(imagePath, langCode); + strcat(imagePath, "\\"); + strcat(imagePath, imageName); + strcat(imagePath, ".bmp"); + + image_handle = LoadImageA(NULL, imagePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + // In the event we can't find an image's translated value + // try to find a matching file in the root folder + if (!image_handle) { + // build imagePath + strcpy(imagePath, DataPath); + strcat(imagePath, "Graphics\\Journal\\"); + strcat(imagePath, imageName); + strcat(imagePath, ".bmp"); + image_handle = LoadImageA(NULL, imagePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + if (!image_handle) { + err = GetLastError(); + } } } } @@ -146,11 +186,34 @@ void init_check_save(WCHAR* save_path) { } } +// images should be loaded from gamepath folder +// so we need a gamepath, which should be saved in the registry +boolean readGamePath() { + // clear data path + memset(&DataPath[0], 0, sizeof(DataPath)); + DWORD dataPathSize = sizeof(DataPath); + + HKEY key; + long keyOpenError = RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\OneShot\\"), &key); + + if (keyOpenError == ERROR_SUCCESS) { + long dirReadError = RegQueryValueEx(key, TEXT("GameDirectory"), NULL, NULL, (LPBYTE)DataPath, &dataPathSize); + + RegCloseKey(key); + + return dirReadError == ERROR_SUCCESS; + } + return FALSE; +} + int do_journal() { // Create HINSTANCE module = GetModuleHandleW(NULL); + // load data path from registry + readGamePath(); + // Default image WCHAR save_path[MAX_PATH]; PWSTR folder_path = NULL; diff --git a/journal/w32/main.c b/journal/w32/journal/src/main.c similarity index 100% rename from journal/w32/main.c rename to journal/w32/journal/src/main.c diff --git a/journal/w32/niko.c b/journal/w32/journal/src/niko.c similarity index 100% rename from journal/w32/niko.c rename to journal/w32/journal/src/niko.c diff --git a/journal/w32/journal/src/resources.rc b/journal/w32/journal/src/resources.rc new file mode 100644 index 0000000..8afb395 --- /dev/null +++ b/journal/w32/journal/src/resources.rc @@ -0,0 +1,9 @@ +#include +MAINICON ICON "icon.ico" + +NIKO1 BITMAP "img/NIKO1.bmp" +NIKO2 BITMAP "img/NIKO2.bmp" +NIKO3 BITMAP "img/NIKO3.bmp" + +default BITMAP "img/DEFAULT.bmp" + diff --git a/journal/w32/resources.rc b/journal/w32/resources.rc deleted file mode 100644 index 9c04a61..0000000 --- a/journal/w32/resources.rc +++ /dev/null @@ -1,223 +0,0 @@ -#include -MAINICON ICON "icon.ico" - -NIKO1 BITMAP "img/NIKO1.bmp" -NIKO2 BITMAP "img/NIKO2.bmp" -NIKO3 BITMAP "img/NIKO3.bmp" - -default BITMAP "img/DEFAULT.bmp" -t1 BITMAP "img/T1.bmp" -t2 BITMAP "img/T2.bmp" -t3 BITMAP "img/T3.bmp" -t4 BITMAP "img/T4.bmp" -t5 BITMAP "img/T5.bmp" -t6 BITMAP "img/T6.bmp" -t7 BITMAP "img/T7.bmp" -t8 BITMAP "img/T8.bmp" -t9 BITMAP "img/T9.bmp" -t10 BITMAP "img/T10.bmp" -t11 BITMAP "img/T11.bmp" -t12 BITMAP "img/T12.bmp" -t13 BITMAP "img/T13.bmp" -t14 BITMAP "img/T14.bmp" -t15 BITMAP "img/T15.bmp" -t16 BITMAP "img/T16.bmp" -c1 BITMAP "img/C1.bmp" -c2 BITMAP "img/C2.bmp" -c3 BITMAP "img/C3.bmp" -c4 BITMAP "img/C4.bmp" -c5 BITMAP "img/C5.bmp" -c6 BITMAP "img/C6.bmp" -c7 BITMAP "img/C7.bmp" -s1 BITMAP "img/S1.bmp" -s2 BITMAP "img/S2.bmp" -s3 BITMAP "img/S3.bmp" -s4 BITMAP "img/S4.bmp" -save BITMAP "img/SAVE.bmp" -final BITMAP "img/FINAL.bmp" - -//french -t1_FR BITMAP "img/fr/T1.bmp" -t2_FR BITMAP "img/fr/T2.bmp" -t3_FR BITMAP "img/fr/T3.bmp" -t4_FR BITMAP "img/fr/T4.bmp" -t5_FR BITMAP "img/fr/T5.bmp" -t6_FR BITMAP "img/fr/T6.bmp" -t7_FR BITMAP "img/fr/T7.bmp" -t8_FR BITMAP "img/fr/T8.bmp" -t9_FR BITMAP "img/fr/T9.bmp" -t10_FR BITMAP "img/fr/T10.bmp" -t11_FR BITMAP "img/fr/T11.bmp" -t12_FR BITMAP "img/fr/T12.bmp" -t13_FR BITMAP "img/fr/T13.bmp" -t14_FR BITMAP "img/fr/T14.bmp" -t15_FR BITMAP "img/fr/T15.bmp" -t16_FR BITMAP "img/fr/T16.bmp" -c1_FR BITMAP "img/fr/C1.bmp" -c2_FR BITMAP "img/fr/C2.bmp" -c3_FR BITMAP "img/fr/C3.bmp" -c4_FR BITMAP "img/fr/C4.bmp" -c5_FR BITMAP "img/fr/C5.bmp" -c6_FR BITMAP "img/fr/C6.bmp" -c7_FR BITMAP "img/fr/C7.bmp" -s1_FR BITMAP "img/fr/S1.bmp" -s2_FR BITMAP "img/fr/S2.bmp" -s3_FR BITMAP "img/fr/S3.bmp" -s4_FR BITMAP "img/fr/S4.bmp" -save_FR BITMAP "img/fr/SAVE.bmp" -final_FR BITMAP "img/fr/FINAL.bmp" - -//spanish -t1_ES BITMAP "img/es/T1.bmp" -t2_ES BITMAP "img/es/T2.bmp" -t3_ES BITMAP "img/es/T3.bmp" -t4_ES BITMAP "img/es/T4.bmp" -t5_ES BITMAP "img/es/T5.bmp" -t6_ES BITMAP "img/es/T6.bmp" -t7_ES BITMAP "img/es/T7.bmp" -t8_ES BITMAP "img/es/T8.bmp" -t9_ES BITMAP "img/es/T9.bmp" -t10_ES BITMAP "img/es/T10.bmp" -t11_ES BITMAP "img/es/T11.bmp" -t12_ES BITMAP "img/es/T12.bmp" -t13_ES BITMAP "img/es/T13.bmp" -t14_ES BITMAP "img/es/T14.bmp" -t15_ES BITMAP "img/es/T15.bmp" -t16_ES BITMAP "img/es/T16.bmp" -c1_ES BITMAP "img/es/C1.bmp" -c2_ES BITMAP "img/es/C2.bmp" -c3_ES BITMAP "img/es/C3.bmp" -c4_ES BITMAP "img/es/C4.bmp" -c5_ES BITMAP "img/es/C5.bmp" -c6_ES BITMAP "img/es/C6.bmp" -c7_ES BITMAP "img/es/C7.bmp" -s1_ES BITMAP "img/es/S1.bmp" -s2_ES BITMAP "img/es/S2.bmp" -s3_ES BITMAP "img/es/S3.bmp" -s4_ES BITMAP "img/es/S4.bmp" -save_ES BITMAP "img/es/SAVE.bmp" -final_ES BITMAP "img/es/FINAL.bmp" - -//japanese -t1_JA BITMAP "img/ja/T1.bmp" -t2_JA BITMAP "img/ja/T2.bmp" -t3_JA BITMAP "img/ja/T3.bmp" -t4_JA BITMAP "img/ja/T4.bmp" -t5_JA BITMAP "img/ja/T5.bmp" -t6_JA BITMAP "img/ja/T6.bmp" -t7_JA BITMAP "img/ja/T7.bmp" -t8_JA BITMAP "img/ja/T8.bmp" -t9_JA BITMAP "img/ja/T9.bmp" -t10_JA BITMAP "img/ja/T10.bmp" -t11_JA BITMAP "img/ja/T11.bmp" -t12_JA BITMAP "img/ja/T12.bmp" -t13_JA BITMAP "img/ja/T13.bmp" -t14_JA BITMAP "img/ja/T14.bmp" -t15_JA BITMAP "img/ja/T15.bmp" -t16_JA BITMAP "img/ja/T16.bmp" -c1_JA BITMAP "img/ja/C1.bmp" -c2_JA BITMAP "img/ja/C2.bmp" -c3_JA BITMAP "img/ja/C3.bmp" -c4_JA BITMAP "img/ja/C4.bmp" -c5_JA BITMAP "img/ja/C5.bmp" -c6_JA BITMAP "img/ja/C6.bmp" -c7_JA BITMAP "img/ja/C7.bmp" -s1_JA BITMAP "img/ja/S1.bmp" -s2_JA BITMAP "img/ja/S2.bmp" -s3_JA BITMAP "img/ja/S3.bmp" -s4_JA BITMAP "img/ja/S4.bmp" -save_JA BITMAP "img/ja/SAVE.bmp" -final_JA BITMAP "img/ja/FINAL.bmp" - -//korean -t1_KO BITMAP "img/ko/T1.bmp" -t2_KO BITMAP "img/ko/T2.bmp" -t3_KO BITMAP "img/ko/T3.bmp" -t4_KO BITMAP "img/ko/T4.bmp" -t5_KO BITMAP "img/ko/T5.bmp" -t6_KO BITMAP "img/ko/T6.bmp" -t7_KO BITMAP "img/ko/T7.bmp" -t8_KO BITMAP "img/ko/T8.bmp" -t9_KO BITMAP "img/ko/T9.bmp" -t10_KO BITMAP "img/ko/T10.bmp" -t11_KO BITMAP "img/ko/T11.bmp" -t12_KO BITMAP "img/ko/T12.bmp" -t13_KO BITMAP "img/ko/T13.bmp" -t14_KO BITMAP "img/ko/T14.bmp" -t15_KO BITMAP "img/ko/T15.bmp" -t16_KO BITMAP "img/ko/T16.bmp" -c1_KO BITMAP "img/ko/C1.bmp" -c2_KO BITMAP "img/ko/C2.bmp" -c3_KO BITMAP "img/ko/C3.bmp" -c4_KO BITMAP "img/ko/C4.bmp" -c5_KO BITMAP "img/ko/C5.bmp" -c6_KO BITMAP "img/ko/C6.bmp" -c7_KO BITMAP "img/ko/C7.bmp" -s1_KO BITMAP "img/ko/S1.bmp" -s2_KO BITMAP "img/ko/S2.bmp" -s3_KO BITMAP "img/ko/S3.bmp" -s4_KO BITMAP "img/ko/S4.bmp" -save_KO BITMAP "img/ko/SAVE.bmp" -final_KO BITMAP "img/ko/FINAL.bmp" - -//portuges -t1_PT_BR BITMAP "img/pt_br/T1.bmp" -t2_PT_BR BITMAP "img/pt_br/T2.bmp" -t3_PT_BR BITMAP "img/pt_br/T3.bmp" -t4_PT_BR BITMAP "img/pt_br/T4.bmp" -t5_PT_BR BITMAP "img/pt_br/T5.bmp" -t6_PT_BR BITMAP "img/pt_br/T6.bmp" -t7_PT_BR BITMAP "img/pt_br/T7.bmp" -t8_PT_BR BITMAP "img/pt_br/T8.bmp" -t9_PT_BR BITMAP "img/pt_br/T9.bmp" -t10_PT_BR BITMAP "img/pt_br/T10.bmp" -t11_PT_BR BITMAP "img/pt_br/T11.bmp" -t12_PT_BR BITMAP "img/pt_br/T12.bmp" -t13_PT_BR BITMAP "img/pt_br/T13.bmp" -t14_PT_BR BITMAP "img/pt_br/T14.bmp" -t15_PT_BR BITMAP "img/pt_br/T15.bmp" -t16_PT_BR BITMAP "img/pt_br/T16.bmp" -c1_PT_BR BITMAP "img/pt_br/C1.bmp" -c2_PT_BR BITMAP "img/pt_br/C2.bmp" -c3_PT_BR BITMAP "img/pt_br/C3.bmp" -c4_PT_BR BITMAP "img/pt_br/C4.bmp" -c5_PT_BR BITMAP "img/pt_br/C5.bmp" -c6_PT_BR BITMAP "img/pt_br/C6.bmp" -c7_PT_BR BITMAP "img/pt_br/C7.bmp" -s1_PT_BR BITMAP "img/pt_br/S1.bmp" -s2_PT_BR BITMAP "img/pt_br/S2.bmp" -s3_PT_BR BITMAP "img/pt_br/S3.bmp" -s4_PT_BR BITMAP "img/pt_br/S4.bmp" -save_PT_BR BITMAP "img/pt_br/SAVE.bmp" -final_PT_BR BITMAP "img/pt_br/FINAL.bmp" - -//chinese -t1_ZH_CN BITMAP "img/zh_cn/T1.bmp" -t2_ZH_CN BITMAP "img/zh_cn/T2.bmp" -t3_ZH_CN BITMAP "img/zh_cn/T3.bmp" -t4_ZH_CN BITMAP "img/zh_cn/T4.bmp" -t5_ZH_CN BITMAP "img/zh_cn/T5.bmp" -t6_ZH_CN BITMAP "img/zh_cn/T6.bmp" -t7_ZH_CN BITMAP "img/zh_cn/T7.bmp" -t8_ZH_CN BITMAP "img/zh_cn/T8.bmp" -t9_ZH_CN BITMAP "img/zh_cn/T9.bmp" -t10_ZH_CN BITMAP "img/zh_cn/T10.bmp" -t11_ZH_CN BITMAP "img/zh_cn/T11.bmp" -t12_ZH_CN BITMAP "img/zh_cn/T12.bmp" -t13_ZH_CN BITMAP "img/zh_cn/T13.bmp" -t14_ZH_CN BITMAP "img/zh_cn/T14.bmp" -t15_ZH_CN BITMAP "img/zh_cn/T15.bmp" -t16_ZH_CN BITMAP "img/zh_cn/T16.bmp" -c1_ZH_CN BITMAP "img/zh_cn/C1.bmp" -c2_ZH_CN BITMAP "img/zh_cn/C2.bmp" -c3_ZH_CN BITMAP "img/zh_cn/C3.bmp" -c4_ZH_CN BITMAP "img/zh_cn/C4.bmp" -c5_ZH_CN BITMAP "img/zh_cn/C5.bmp" -c6_ZH_CN BITMAP "img/zh_cn/C6.bmp" -c7_ZH_CN BITMAP "img/zh_cn/C7.bmp" -s1_ZH_CN BITMAP "img/zh_cn/S1.bmp" -s2_ZH_CN BITMAP "img/zh_cn/S2.bmp" -s3_ZH_CN BITMAP "img/zh_cn/S3.bmp" -s4_ZH_CN BITMAP "img/zh_cn/S4.bmp" -save_ZH_CN BITMAP "img/zh_cn/SAVE.bmp" -final_ZH_CN BITMAP "img/zh_cn/FINAL.bmp" diff --git a/scripts/i18n_Language.rb b/scripts/i18n_Language.rb index ced44d2..9f7ae9a 100644 --- a/scripts/i18n_Language.rb +++ b/scripts/i18n_Language.rb @@ -1,5 +1,4 @@ # Classes for translating text similar to GNU gettext - # Translator class: translate text to another language # for debug REMOVE BEFORE COMMITTING / BUILDING @@ -7,19 +6,8 @@ class Language FONT_WESTERN = 'Terminus (TTF)' - FONT_CK = 'WenQuanYi Micro Hei' FONT_J = 'HigashiOme Gothic regular' - LANG_WESTERN = [ - 'en', 'fr', 'pt_BR', 'es' - ] - LANG_J = [ - 'ja' - ] - LANG_CK = [ - 'ko', 'zh_CN' - ] - LANGUAGES = Steam.enabled? ? (LANG_WESTERN + LANG_CK + LANG_J) : ['en'] - + LANGUAGES = [] class << self def set(lc) dbg_print(lc.lang) @@ -27,27 +15,43 @@ class Language @tr = nil script = nil [lc.full.to_s, lc.lang.to_s].each do |name| - path = "Languages/#{name}.loc" + path = "Languages/#{name}.po" dbg_print(path) if FileTest.exist?(path) - File.open(path, "rb") do |file| - @data = Marshal.load(file) - if LANG_CK.include? name - Font.default_name = FONT_CK - elsif LANG_J.include? name - Font.default_name = FONT_J - else - Font.default_name = FONT_WESTERN - end - Journal.setLang(name) - dbg_print(Font.default_name) - end + load_pot(path) + loadFontMap + Font.default_name = @languageFontMap[name] + Journal.setLang(name) + dbg_print(Font.default_name) + break end end reset_fonts(@text_sprites) Oneshot.set_yes_no(tr('Yes'), tr('No')) end + def load_pot(path) + msgid = nil + msgstr = nil + @data = Hash.new + if FileTest.exist?(path) + File.readlines(path).each do |line| + if line.start_with?("msgid ") + line = line[6..-1] + #unescape the string + eval("msgid = " + line) + elsif line.start_with?("msgstr ") + line = line[7..-1] + #unescape the string + eval("msgstr = " + line) + if !(msgid.nil? || msgid.empty?) + @data[Oneshot::crc32(msgid)] = msgstr + end + end + end + end + end + # Translate some text def tr(string) #dbg_print(caller_locations(1, 1).first.tap{|loc| puts "#{loc.path}:#{loc.lineno}"}) @@ -60,6 +64,23 @@ class Language return String.new(rv) end + def loadFontMap + if !@fontMapLoaded + @languageFontMap = Hash.new + path = "Languages/language_fonts.ini" + if FileTest.exist?(path) + File.readlines(path).each do |line| + parts = line.split("=", 2) + if parts.length == 2 + LANGUAGES.push(parts[0]) + @languageFontMap[parts[0]] = parts[1].strip + end + end + end + @fontMapLoaded = true + end + end + # Turn all database items into translatable strings def initialize_database $data_actors.each do |i| @@ -95,7 +116,7 @@ class Language if sprites.kind_of?(Array) sprites.each do |spr| if spr.kind_of?(Sprite) and !spr.disposed? - spr.bitmap.font.name = Font.default_name + spr.bitmap.font.name = Font.default_name end end elsif sprites.kind_of?(Hash) diff --git a/src/i18n.cpp b/src/i18n.cpp index f882162..0b2b06d 100644 --- a/src/i18n.cpp +++ b/src/i18n.cpp @@ -7,16 +7,23 @@ #include #include -const char* LOC_HEADER = "ONELOC\x10"; - char** strdict = 0; unsigned int nStr = 0; -int family = LOCALE_FAMILY_LATIN; -size_t readSize; -int getLocaleFamily() { - return family; -} +const int MAX_LANGUAGES = 20; + +const int LANGCODE_SIZE = 16; +const int LANGFONT_SIZE = 128; + +char* currentLocale = 0; + +struct LanguageFontAndSize { + char* lang_code = 0; + int size = 0; + char* font_name = 0; +}; + +LanguageFontAndSize** languageMetadata = 0; const char* findtext(unsigned int msgid, const char* fallback) { if (msgid >= nStr) { @@ -31,57 +38,225 @@ void unloadLocale() { free(strdict[i]); } free(strdict); + free(currentLocale); strdict = 0; nStr = 0; } -void _setLocaleFamily(const char* locale) { - if (!strcmp(locale, "ja") - || !strcmp(locale, "ko") - || !strcmp(locale, "zh_CN")) { - family = LOCALE_FAMILY_ASIAN; - } else { - family = LOCALE_FAMILY_LATIN; + +void unloadLanguageMetadata() { + if (languageMetadata) { + for (int i = 0; i < MAX_LANGUAGES; ++i) { + LanguageFontAndSize* ldata = languageMetadata[i]; + if (ldata) { + if (ldata->font_name) { + free(ldata->font_name); + } + if (ldata->lang_code) { + free(ldata->lang_code); + } + free(ldata); + } + } + } + free(languageMetadata); +} + +void loadLanguageMetadata() { + if (languageMetadata) { + unloadLanguageMetadata(); + } + + char line[256]; + + languageMetadata = (LanguageFontAndSize**) calloc(MAX_LANGUAGES, sizeof(LanguageFontAndSize*)); + FILE* fontsFile = fopen("Languages/internal/language_fonts.ini", "r"); + if (fontsFile) { + + int languageMetadataIndex = 0; + + while (fgets(line, 1024, fontsFile)) { + char* indexOfEquals = strchr(line, '='); + if (indexOfEquals) { + // splitting the string in place here + indexOfEquals[0] = 0; + char* indexOfFontName = indexOfEquals + 1; + + // remove new line from end of font name + char* indexOfNewLine = strchr(indexOfFontName, '\n'); + if (indexOfNewLine) { + indexOfNewLine[0] = 0; + } + + // make new strings for code and font name + char* langCode = (char*)calloc(LANGCODE_SIZE, sizeof(char)); + char* langFont = (char*)calloc(LANGFONT_SIZE, sizeof(char)); + + strcpy(langCode, line); + strcpy(langFont, indexOfFontName); + + // allocate metadata mem + LanguageFontAndSize* metadata = (LanguageFontAndSize*) calloc(1, sizeof(LanguageFontAndSize)); + metadata->font_name = langFont; + metadata->lang_code = langCode; + + // put into metadata array and check if we're going to go over the language limit + languageMetadata[languageMetadataIndex] = metadata; + languageMetadataIndex++; + if (languageMetadataIndex >= MAX_LANGUAGES) { + break; + } + } + } + + fclose(fontsFile); + } + + + FILE* fontSizesFile = fopen("Languages/internal/language_sizes.ini", "r"); + if (fontSizesFile) { + while (fgets(line, 1024, fontSizesFile)) { + int languageMetadataIndex = 0; + char* indexOfEquals = strchr(line, '='); + if (indexOfEquals) { + // splitting the string in place here + indexOfEquals[0] = 0; + char* indexOfFontSize = indexOfEquals + 1; + + // remove new line from end of font size + char* indexOfNewLine = strchr(indexOfFontSize, '\n'); + if (indexOfNewLine) { + indexOfNewLine[0] = 0; + } + + int fontSize = atoi(indexOfFontSize); + + for (int i = 0; i < MAX_LANGUAGES; i++) { + // search for corresponding langCode in metadata array to populate font size in the appropriate metadata + LanguageFontAndSize* metadata = languageMetadata[i]; + if (metadata && strcmp(line, metadata->lang_code) == 0) { + metadata->size = fontSize; + break; + } + } + } + } + + fclose(fontSizesFile); } } -void _read(void * ptr, size_t size, size_t count, FILE * stream) { - readSize = fread(ptr, size, count, stream); - if (readSize != count) { +int getFontSize() { + for (int i = 0; i < MAX_LANGUAGES; i++) { + LanguageFontAndSize* metadata = languageMetadata[i]; + if (metadata && strcmp(currentLocale, metadata->lang_code) == 0) { + return metadata->size; + } } + + // default to 12? + return 12; +} + +char* getFontName() { + for (int i = 0; i < MAX_LANGUAGES; i++) { + LanguageFontAndSize* metadata = languageMetadata[i]; + if (metadata && strcmp(currentLocale, metadata->lang_code) == 0) { + return metadata->font_name; + } + } + + // default to terminus? + return "Terminus (TTF)"; } void loadLocale(const char* locale) { + char line[1024]; char pathbuf[100]; FILE* locfile; - char header[8]; - unsigned int i; - int strSize = 0; unloadLocale(); - _setLocaleFamily(locale); + currentLocale = (char*) calloc(128, sizeof(char)); + strncpy(currentLocale, locale, 128 - 1); - sprintf(pathbuf, "Languages/internal/%s.loc", locale); - locfile = fopen(pathbuf, "rb"); + int dictSize = 100; + // currently there are 52, but 100 should be plenty if we ever do add more + strdict = (char**)malloc(sizeof(char*) * dictSize); + + sprintf(pathbuf, "Languages/internal/%s.po", locale); + locfile = fopen(pathbuf, "r"); if (locfile) { - _read(header, 1, 8, locfile); - if (!strcmp(header, LOC_HEADER)) { - // Read number of strs in this file - _read(&nStr, 4, 1, locfile); - strdict = (char**)malloc(sizeof(char*) * nStr); - for (i = 0; i < nStr; i++) { - // Read the size of the next string - _read(&strSize, 4, 1, locfile); - strdict[i] = (char*)malloc(strSize+1); - if (strSize > 0) { - // Read the contents of the next string - _read(strdict[i], 1, strSize, locfile); - strdict[i][strSize] = 0; + while (fgets(line, 1024, locfile)) { + if (strncmp("msgstr \"", line, 8) == 0) { + char* lineWithoutMsgid = line + 8; + + char* endQuoteAddress = strrchr(lineWithoutMsgid, '"'); + + // end string at last quotation mark + if (endQuoteAddress != 0) { + endQuoteAddress[0] = 0; } - strdict[i][strSize] = 0; + + decodeEscapeChars(lineWithoutMsgid); + + int lineLen = strlen(lineWithoutMsgid); + + strdict[nStr] = (char*)malloc(lineLen + 1); + strcpy(strdict[nStr], lineWithoutMsgid); + + nStr++; } } + fclose(locfile); } } + +// replaces escape characters with their actual values in-place in a string +// can do it in-place because the replacement values are always smaller than the original value +// it only handles \\ and \", but this can be expanded to include more if needed +void decodeEscapeChars(char* s) { + char* dest = s; + char* src = s; + while (src[0] != 0) { + switch (src[0]) { + // might be an escape character? + case '\\': + switch (src[1]) { + case '\\' : + dest[0] = '\\'; + dest++; + src += 2; + break; + case '\"': + dest[0] = '\"'; + dest++; + src += 2; + break; + // end of the string? + // so only advance forward 1 character + case 0: + dest[0] = '\\'; + dest++; + src++; + break; + // not escape, handle normally + default: + dest[0] = '\\'; + dest[1] = src[1]; + dest+=2; + src+=2; + break; + } + break; + default: + dest[0] = src[0]; + dest++; + src++; + } + } + // cap the end of the string + dest[0] = 0; +} + diff --git a/src/i18n.h b/src/i18n.h index db6936d..4bada70 100644 --- a/src/i18n.h +++ b/src/i18n.h @@ -5,10 +5,11 @@ void unloadLocale(); void loadLocale(const char* locale); +void decodeEscapeChars(char* s); const char* findtext(unsigned int msgid, const char* fallback); -int getLocaleFamily(); - -#define LOCALE_FAMILY_LATIN 1 -#define LOCALE_FAMILY_ASIAN 2 +void loadLanguageMetadata(); +void unloadLanguageMetadata(); +int getFontSize(); +char* getFontName(); #endif /* end of include guard: I18N_H */ diff --git a/src/main.cpp b/src/main.cpp index f2cc8bb..fa71c1b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -192,6 +192,48 @@ static void setupWindowIcon(const Config &conf, SDL_Window *win) } } +// mainly doing this so journal app knows where to load images from +static void setGamePathInRegistry() { + +#if defined WIN32 + // this logic is currently windows specific + char* dataDir = SDL_GetBasePath(); + if (dataDir) + { + HKEY key; + long keyOpenError = RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\OneShot\\"), &key); + + if (keyOpenError != ERROR_SUCCESS) { + // try creating the key first + long keyCreateError = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Software\\OneShot\\"), 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL); + + if (keyCreateError != ERROR_SUCCESS) + { + showInitError("Unable to create key in registry."); + } + else { + keyOpenError = ERROR_SUCCESS; + } + } + + if (keyOpenError != ERROR_SUCCESS) + { + showInitError("Unable to open registry."); + } + else { + DWORD dataSize = (strlen(dataDir) + 1) * sizeof(char); + if (RegSetValueEx(key, TEXT("GameDirectory"), 0, REG_SZ, (LPBYTE)dataDir, dataSize) != ERROR_SUCCESS) + { + showInitError("Unable to set GameDirectory registry value."); + } + RegCloseKey(key); + } + SDL_free(dataDir); + } +#endif + //TODO handle this for Linux/Mac +} + int main(int argc, char *argv[]) { SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); @@ -233,9 +275,13 @@ int main(int argc, char *argv[]) } #endif + setGamePathInRegistry(); + /* Initialize physfs here so that config can call PHYSFS_getPrefDir */ PHYSFS_init(argv[0]); + loadLanguageMetadata(); + /* now we load the config */ Config conf; conf.read(argc, argv); @@ -393,6 +439,7 @@ int main(int argc, char *argv[]) Debug() << "Shutting down."; unloadLocale(); + unloadLanguageMetadata(); alcCloseDevice(alcDev); SDL_DestroyWindow(win); diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index 269897c..9afb646 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -47,12 +47,6 @@ const uint8_t cBgDark = 20; const uint8_t cLine = 0; const uint8_t cText = 255; -// const char *const fontFamilyLatin = "Terminus (TTF)"; -const char *const fontFamilyLatin = "WenQuanYi Micro Hei"; -const uint8_t fontSizeLatin = 12; -const char *const fontFamilyAsian = "WenQuanYi Micro Hei"; -const uint8_t fontSizeAsian = 16; - static bool pointInRect(const SDL_Rect &r, int x, int y) { return (x >= r.x && x <= r.x+r.w && y >= r.y && y <= r.y+r.h); @@ -530,7 +524,13 @@ struct SettingsMenuPrivate { dstRect.w = alignW; dstRect.x = drawOff.x + x; - SDL_BlitScaled(txtSurf, 0, surf, &dstRect); + + SDL_Rect srcRect; + srcRect.x = 0; + srcRect.y = 0; + srcRect.w = dstRect.w; + srcRect.h = txtSurf->h; + SDL_BlitSurface(txtSurf, &srcRect, surf, &dstRect); } } @@ -973,7 +973,7 @@ void BindingWidget::clickHandler(int x, int y, uint8_t button) if (cell == -1) return; - p->onBWidgetCellClicked(src[cell], vb.str, button); + p->onBWidgetCellClicked(src[cell], findtext(vb.trstrId, vb.str), button); } int BindingWidget::cellIndex(int x, int y) const @@ -1080,11 +1080,7 @@ SettingsMenu::SettingsMenu(RGSSThreadData &rtData) p->winSurf = SDL_GetWindowSurface(p->window); p->winID = SDL_GetWindowID(p->window); - if (getLocaleFamily() == LOCALE_FAMILY_ASIAN) { - p->font = shState->fontState().getFont(fontFamilyAsian, fontSizeAsian); - } else { - p->font = shState->fontState().getFont(fontFamilyLatin, fontSizeLatin); - } + p->font = shState->fontState().getFont(getFontName(), getFontSize()); p->rgb = p->winSurf->format;