30 static char **_langpack_offs; |
30 static char **_langpack_offs; |
31 static LanguagePack *_langpack; |
31 static LanguagePack *_langpack; |
32 static uint _langtab_num[32]; // Offset into langpack offs |
32 static uint _langtab_num[32]; // Offset into langpack offs |
33 static uint _langtab_start[32]; // Offset into langpack offs |
33 static uint _langtab_start[32]; // Offset into langpack offs |
34 |
34 |
35 const uint16 _currency_string_list[] = { |
35 const StringID _currency_string_list[] = { |
36 STR_CURR_GBP, |
36 STR_CURR_GBP, |
37 STR_CURR_USD, |
37 STR_CURR_USD, |
38 STR_CURR_EUR, |
38 STR_CURR_EUR, |
39 STR_CURR_YEN, |
39 STR_CURR_YEN, |
40 STR_CURR_ATS, |
40 STR_CURR_ATS, |
126 { |
126 { |
127 while ((*dst++ = *src++) != '\0') {} |
127 while ((*dst++ = *src++) != '\0') {} |
128 return dst - 1; |
128 return dst - 1; |
129 } |
129 } |
130 |
130 |
131 static const char *GetStringPtr(uint16 string) |
131 static const char *GetStringPtr(StringID string) |
132 { |
132 { |
133 return _langpack_offs[_langtab_start[string >> 11] + (string & 0x7FF)]; |
133 return _langpack_offs[_langtab_start[string >> 11] + (string & 0x7FF)]; |
134 } |
134 } |
135 |
135 |
136 char *GetString(char *buffr, uint16 string) |
136 char *GetString(char *buffr, StringID string) |
137 { |
137 { |
138 uint index = string & 0x7FF; |
138 uint index = string & 0x7FF; |
139 uint tab = string >> 11; |
139 uint tab = string >> 11; |
140 |
140 |
141 if (string == 0) error("!invalid string id 0 in GetString"); |
141 switch (string) { |
142 |
142 case 0: |
143 if (tab == 4 && index >= 0xC0) |
143 error("!invalid string id 0 in GetString"); |
144 return GetSpecialTownNameString(buffr, index - 0xC0); |
144 break; |
145 |
145 |
146 if (tab == 6 && index == 0xD1) |
146 case 0x30D1: |
147 return StationGetSpecialString(buffr); |
147 return StationGetSpecialString(buffr); |
148 |
148 |
149 if (tab == 14 && index >= 0xE4) |
149 case STR_SPEC_SCREENSHOT_NAME: |
150 return GetSpecialPlayerNameString(buffr, index - 0xE4); |
150 return DecodeString(buffr, _screenshot_name); |
151 |
151 } |
152 if (tab == 15) |
152 |
153 return GetName(index, buffr); |
153 switch (tab) { |
154 |
154 case 4: |
155 // tab 31 is used for special or dynamic strings |
155 if (index >= 0xC0) return GetSpecialTownNameString(buffr, index - 0xC0); |
156 if (tab == 31) { |
156 break; |
157 return DecodeString(buffr, index == (STR_SPEC_SCREENSHOT_NAME & 0x7FF) ? _screenshot_name : _userstring); |
157 |
|
158 case 14: |
|
159 if (index >= 0xE4) return GetSpecialPlayerNameString(buffr, index - 0xE4); |
|
160 break; |
|
161 |
|
162 case 15: |
|
163 return GetName(index, buffr); |
|
164 |
|
165 case 31: // special or dynamic strings |
|
166 return DecodeString(buffr, _userstring); |
|
167 |
|
168 default: |
|
169 break; |
158 } |
170 } |
159 |
171 |
160 if (index >= _langtab_num[tab]) |
172 if (index >= _langtab_num[tab]) |
161 error("!String 0x%X is invalid. Probably because an old version of the .lng file.\n", string); |
173 error( |
|
174 "!String 0x%X is invalid. " |
|
175 "Probably because an old version of the .lng file.\n", string |
|
176 ); |
162 |
177 |
163 return DecodeString(buffr, GetStringPtr(string)); |
178 return DecodeString(buffr, GetStringPtr(string)); |
164 } |
179 } |
165 |
180 |
166 void InjectDParam(int amount) |
181 void InjectDParam(int amount) |
452 case 3: { /* {SHORTCARGO} */ |
467 case 3: { /* {SHORTCARGO} */ |
453 // Short description of cargotypes. Layout: |
468 // Short description of cargotypes. Layout: |
454 // 8-bit = cargo type |
469 // 8-bit = cargo type |
455 // 16-bit = cargo count |
470 // 16-bit = cargo count |
456 const char *s; |
471 const char *s; |
457 uint16 cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()]; |
472 StringID cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()]; |
458 uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1; |
473 uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1; |
459 // liquid type of cargo is multiplied by 100 to get correct amount |
474 // liquid type of cargo is multiplied by 100 to get correct amount |
460 buff = FormatCommaNumber(buff, GetParamInt16() * multiplier); |
475 buff = FormatCommaNumber(buff, GetParamInt16() * multiplier); |
461 s = GetStringPtr(cargo_str); |
476 s = GetStringPtr(cargo_str); |
462 |
477 |
649 "Sneaky", |
664 "Sneaky", |
650 "Nutkins", |
665 "Nutkins", |
651 }; |
666 }; |
652 |
667 |
653 static const char _initial_name_letters[] = { |
668 static const char _initial_name_letters[] = { |
654 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', |
669 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', |
|
670 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', |
655 }; |
671 }; |
656 |
672 |
657 static char *GenAndCoName(char *buff) |
673 static char *GenAndCoName(char *buff) |
658 { |
674 { |
659 uint32 x = GetParamInt32(); |
675 uint32 x = GetParamInt32(); |
728 }; |
744 }; |
729 |
745 |
730 static char *GetSpecialPlayerNameString(char *buff, int ind) |
746 static char *GetSpecialPlayerNameString(char *buff, int ind) |
731 { |
747 { |
732 switch (ind) { |
748 switch (ind) { |
733 // not used |
749 case 1: // not used |
734 case 1: { |
750 return str_cat(buff, _silly_company_names[GetParamInt32() & 0xFFFF]); |
735 int i = GetParamInt32() & 0xFFFF; |
751 |
736 return str_cat(buff, _silly_company_names[i]); |
752 case 2: // used for Foobar & Co company names |
737 } |
753 return GenAndCoName(buff); |
738 |
754 |
739 case 2: // used for Foobar & Co company names |
755 case 3: // President name |
740 return GenAndCoName(buff); |
756 return GenPlayerName_4(buff); |
741 |
757 |
742 case 3: // President name |
758 case 4: // song names |
743 return GenPlayerName_4(buff); |
759 return str_cat(buff, _song_names[GetParamUint16() - 1]); |
744 |
|
745 // song names |
|
746 case 4: { |
|
747 const char *song = _song_names[GetParamUint16() - 1]; |
|
748 return str_cat(buff, song); |
|
749 } |
|
750 } |
760 } |
751 |
761 |
752 // town name? |
762 // town name? |
753 if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) { |
763 if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) { |
754 buff = GetSpecialTownNameString(buff, ind - 6); |
764 buff = GetSpecialTownNameString(buff, ind - 6); |
778 } |
788 } |
779 |
789 |
780 // remap a string ID from the old format to the new format |
790 // remap a string ID from the old format to the new format |
781 StringID RemapOldStringID(StringID s) |
791 StringID RemapOldStringID(StringID s) |
782 { |
792 { |
783 if (s == 0x7000) s = STR_SV_UNNAMED; |
793 switch (s) { |
784 else if (s == 0x0006) s = STR_SV_EMPTY; |
794 case 0x0006: return STR_SV_EMPTY; |
785 else if (s == 0x8864) s = STR_SV_TRAIN_NAME; |
795 case 0x7000: return STR_SV_UNNAMED; |
786 else if (s == 0x902B) s = STR_SV_ROADVEH_NAME; |
796 case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH; |
787 else if (s == 0x9830) s = STR_SV_SHIP_NAME; |
797 case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH; |
788 else if (s == 0xA02F) s = STR_SV_AIRCRAFT_NAME; |
798 case 0x8864: return STR_SV_TRAIN_NAME; |
789 else if (IS_INT_INSIDE(s, 0x300F, 0x3030)) s = s - 0x300F + STR_SV_STNAME; |
799 case 0x902B: return STR_SV_ROADVEH_NAME; |
790 else if (s == 0x70E4 || s == 0x70E9) s = SPECSTR_PLAYERNAME_ENGLISH; |
800 case 0x9830: return STR_SV_SHIP_NAME; |
791 return s; |
801 case 0xA02F: return STR_SV_AIRCRAFT_NAME; |
|
802 |
|
803 default: |
|
804 if (IS_INT_INSIDE(s, 0x300F, 0x3030)) |
|
805 return s - 0x300F + STR_SV_STNAME; |
|
806 else |
|
807 return s; |
|
808 } |
792 } |
809 } |
793 |
810 |
794 bool ReadLanguagePack(int lang_index) |
811 bool ReadLanguagePack(int lang_index) |
795 { |
812 { |
796 int tot_count, i; |
813 int tot_count, i; |
837 if (len >= 0xC0) len = ((len & 0x3F) << 8) + (byte)*s++; |
854 if (len >= 0xC0) len = ((len & 0x3F) << 8) + (byte)*s++; |
838 langpack_offs[i] = s; |
855 langpack_offs[i] = s; |
839 s += len; |
856 s += len; |
840 } |
857 } |
841 |
858 |
842 if (_langpack) free(_langpack); |
859 free(_langpack); |
843 _langpack = lang_pack; |
860 _langpack = lang_pack; |
844 |
861 |
845 if (_langpack_offs) free(_langpack_offs); |
862 free(_langpack_offs); |
846 _langpack_offs = langpack_offs; |
863 _langpack_offs = langpack_offs; |
847 |
864 |
848 ttd_strlcpy(_dynlang.curr_file, _dynlang.ent[lang_index].file, sizeof(_dynlang.curr_file)); |
865 ttd_strlcpy(_dynlang.curr_file, _dynlang.ent[lang_index].file, sizeof(_dynlang.curr_file)); |
849 |
866 |
850 |
867 |
854 |
871 |
855 // make a list of the available language packs. put the data in _dynlang struct. |
872 // make a list of the available language packs. put the data in _dynlang struct. |
856 void InitializeLanguagePacks(void) |
873 void InitializeLanguagePacks(void) |
857 { |
874 { |
858 DynamicLanguages *dl = &_dynlang; |
875 DynamicLanguages *dl = &_dynlang; |
859 int i, j, n, m,def; |
876 int i; |
|
877 int n; |
|
878 int m; |
|
879 int def; |
860 LanguagePack hdr; |
880 LanguagePack hdr; |
861 FILE *in; |
881 FILE *in; |
862 char *files[32]; |
882 char *files[32]; |
863 |
883 |
864 n = GetLanguageList(files, lengthof(files)); |
884 n = GetLanguageList(files, lengthof(files)); |
865 |
885 |
866 def = 0; // default language file |
886 def = 0; // default language file |
867 |
887 |
868 // go through the language files and make sure that they are valid. |
888 // go through the language files and make sure that they are valid. |
869 for (i = m = 0; i != n; i++) { |
889 for (i = m = 0; i != n; i++) { |
|
890 int j; |
|
891 |
870 char *s = str_fmt("%s%s", _path.lang_dir, files[i]); |
892 char *s = str_fmt("%s%s", _path.lang_dir, files[i]); |
871 in = fopen(s, "rb"); |
893 in = fopen(s, "rb"); |
872 free(s); |
894 free(s); |
873 if (in == NULL || |
895 if (in == NULL || |
874 (j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 || |
896 (j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 || |