From 185a6e53829aecb05124acaf4eb78f3960892ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Thu, 6 Feb 2025 21:33:25 +0100 Subject: [PATCH] generate stringtables --- game/CMakeLists.txt | 1 + game/crc.c | 31 ------- game/dialogy.c | 9 +- game/gen_stringtable.c | 200 +++++++++++++++++++++++++++++++++++++++++ game/globals.h | 5 ++ game/realgame.c | 1 - game/skeldal.c | 36 ++++++-- 7 files changed, 239 insertions(+), 44 deletions(-) delete mode 100644 game/crc.c create mode 100644 game/gen_stringtable.c diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index ec4e460..d514e84 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -33,6 +33,7 @@ chargen.c sndandmus.c specproc.c console.c +gen_stringtable.c advconfig.c temp_storage.cpp ${CMAKE_BINARY_DIR}/default_font.cpp diff --git a/game/crc.c b/game/crc.c deleted file mode 100644 index d179a2d..0000000 --- a/game/crc.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - - -uint32_t l; - -#define ZAKLAD_CRC 0xC005 - -char data[100000]; -int32_t delka; -FILE *f; - - -main() - { - int i; - f=fopen_icase("CRC.C","rb"); - memset(data,0,sizeof(data)); - delka=fread(data,1,sizeof(data),f); - fclose(f); - memcpy(&l,data,2);i=0; - l%=ZAKLAD_CRC; - while(ivisited) z->first=1; if (z->alt==z->num || !z->visited) { - pc=((char *)ablock_copy(H_DIALOGY_DAT))+*((int *)ablock_copy(H_DIALOGY_DAT))*sizeof(T_PARAGRAPH)+8+z->position; + pc=((char *)ablock_copy(H_DIALOGY_DAT))+*((const int *)ablock(H_DIALOGY_DAT))*sizeof(T_PARAGRAPH)+8+z->position; last_pgf=prgf; z->visited=1; return; @@ -391,7 +391,8 @@ static char *Get_string() { short i; pc++; - i=*(short *)pc;pc+=2; + i = (uint8_t)pc[0] + 256*pc[1]; + pc+=2; if (i<=0) c=conv_text(texty[abs(i)]);else c=conv_text(level_texts[i]); return string_buffer; } @@ -406,14 +407,14 @@ static short Get_short() if (*pc==P_SHORT) { pc++; - p=*(short *)pc; + p = (uint8_t)pc[0] + 256*pc[1]; pc+=2; return p; } if (*pc==P_VAR) { pc++; - p=*(short *)pc; + p = (uint8_t)pc[0] + 256*pc[1]; pc+=2; return varibles[p]; } diff --git a/game/gen_stringtable.c b/game/gen_stringtable.c new file mode 100644 index 0000000..4853316 --- /dev/null +++ b/game/gen_stringtable.c @@ -0,0 +1,200 @@ +#include + +#include +#include +#include +#include +#include "globals.h" +#include + + + +static void csv_output(FILE *f, const char *txt) { + while (*txt) { + if (*txt == '"') { + fputc('"',f); + fputc('"',f); + } else { + fputc(kamenik2windows_chr(*txt),f); + } + ++txt; + } +} + +static char store_to_csv(TSTR_LIST lst, const char *target_path) { + int cnt = str_count(lst); + char to_store = 0; + for (int i = 0; i < cnt; ++i) if (lst[i]) to_store = 1; + if (!to_store) { + fprintf(stdout, "Empty string table not stored: %s\n", target_path); + return 1; + } + FILE *out = fopen_icase(target_path, "w"); + if (!out) { + fprintf(stderr, "Failed to open %s for writing\n",target_path); + return 0; + } + printf("Writing file: %s\n", target_path); + fprintf(out, "id,string\n"); + for (int i = 0; i < cnt; ++i) { + if (lst[i]) { + fprintf(out, "%d,\"",i); + csv_output(out, lst[i]); + fprintf(out, "\"\n"); + } + } + fclose(out); + return 1; +} + +static int find_mapedit(TSTR_LIST lst) { + for (int i = 0; i < str_count(lst); ++i) { + if (lst[i] && imatch(lst[i], "TOTO JE MAGIC SLOUP MAPEDIT")) return i; + } + return 0; +} + +void cti_texty(void); + +static int convert_map_strings_1(const char *source_name, LIST_FILE_TYPE type, size_t sz, void *context) { + int l = strlen(source_name); + if (stricmp(source_name+l-4,".map")) return 0; + source_name = set_file_extension(source_name, ".txt"); + const char *target_name = set_file_extension(concat2("map_", source_name),".csv"); + const char *target_path = *(const char **)context; + TSTR_LIST lst = create_list(100); + int err = load_string_list_ex(&lst, build_pathname(2, gpathtable[SR_MAP], source_name)); + if (err) { + release_list(lst); + fprintf(stderr,"Failed to read: %s, error code: %d\n",source_name, err); + return 1; + } + str_replace(&lst, 0, NULL); + int toremove = find_mapedit(lst); + if (toremove) { + str_replace(&lst, toremove, NULL); + } + err = store_to_csv(lst, build_pathname(2, target_path, target_name)); + release_list(lst); + return !err; + ; + +} + +static char convert_map_strings(const char *target_path) { + return !list_files(build_pathname(1, gpathtable[SR_MAP]), file_type_normal|file_type_just_name,convert_map_strings_1 , &target_path); +} + + +static char convert_file_to(const char *src_file, const char *target_file) { + TMPFILE_RD *rd = enc_open(src_file); + size_t sz = temp_storage_find("__enc_temp"); + char *buff = malloc(sz); + temp_storage_retrieve("__enc_temp", buff, sz); + FILE *out = fopen_icase(target_file, "w"); + if (!out) { + fprintf(stderr, "Failed to open %s for writing\n",target_file); + return 0; + } + printf("Writing %s\n", target_file); + fwrite(buff,1,sz,out); + fclose(out); + enc_close(rd); + return 1; +} + +static char convert_book(const char *target_path) { + const char *path = build_pathname(2, target_path, "book.txt"); + path = local_strdup(path); + return convert_file_to(build_pathname(2, gpathtable[SR_MAP], "kniha.txt"), path); +} + +static char convert_end_titles(const char *target_path) { + const char *path = build_pathname(2, target_path, "end_titles.txt"); + path = local_strdup(path); + return convert_file_to(build_pathname(2, gpathtable[SR_DATA], "titulky.txt"), path); +} + +static char convert_epilog(const char *target_path) { + const char *path = build_pathname(2, target_path, "epilog.txt"); + path = local_strdup(path); + return convert_file_to(build_pathname(2, gpathtable[SR_DATA], "endtext.txt"), path); +} + +char generate_items_strings(const char *path) { + load_items(); + TSTR_LIST lst = create_list(item_count); + for (int i = 0; i < item_count;++i) { + str_replace(&lst, i, concat3(glob_items[i].jmeno,"\n",glob_items[i].popis)); + } + int r = store_to_csv(lst, build_pathname(2,path,"items.csv")); + release_list(lst); + return r; +} +char generate_spell_strings(const char *path) { + TSTR_LIST lst = create_list(255); + for (int i = 0; i < 5; i++) + for (int j = 0; j < 7; j++) { + int idx = (i * 7 + j)*3; + str_replace(&lst, idx, get_rune_name(idx)); + } + + int r = store_to_csv(lst, build_pathname(2,path,"spells.csv")); + release_list(lst); + return r; +} + +char generate_dialog_append_pgf(TSTR_LIST *lst,const char *beg, const char *pc, const char *end) { + + while (pc < end) { + char type = *pc; + ++pc; + if (type == 1) { + str_replace(lst, pc - beg, pc); + pc += strlen(pc)+1; + } else { + pc+=2; + } + } + return 1; + +} + +char generate_dialog_table(const char *path) { + const int32_t *data = (const int32_t *)ablock(H_DIALOGY_DAT); + size_t total_sz = get_handle_size(H_DIALOGY_DAT); + const char *beg = (const char *)data; + + size_t count = data[0]; + TSTR_LIST lst = create_list(256); + data+=2; + for (size_t i = 0; i < count; i++) { + int pos = data[1] + 8*(count+1); + int end = i + 1 == count? total_sz : data[3] + 8*(count+1); + + generate_dialog_append_pgf(&lst, beg, beg+pos, beg+end); + + data+=2; + } + int r = store_to_csv(lst, build_pathname(2,path,"dialogs.csv")); + release_list(lst); + return r; +} + + + +char generate_string_tables(const char *path) { + create_directories(path); + cti_texty(); + if (!store_to_csv(texty, build_pathname(2, path, "ui.csv"))) return 0; + if (!convert_map_strings(path)) return 0; + if (!convert_book(path)) return 0; + if (!convert_end_titles(path)) return 0; + if (!convert_epilog(path)) return 0; + if (!generate_items_strings(path)) return 0; + if (!generate_spell_strings(path)) return 0; + if (!generate_dialog_table(path)) return 0; + return 1; +} + + diff --git a/game/globals.h b/game/globals.h index e45beeb..19fbacb 100644 --- a/game/globals.h +++ b/game/globals.h @@ -1803,6 +1803,11 @@ char *map_hash_to_string_impl(char *c, uint32_t h, int sz); const char *find_map_from_hash_impl(char *c, uint32_t h, int sz); #define find_map_from_hash(h) (find_map_from_hash_impl((char *)alloca(31), h, 30)) char can_select_player(THUMAN *p, char select_dead, char select_far); +char generate_string_tables(const char *path); + +char *change_extension_support(char *buffer, const char *filename,char *new_extension); +#define set_file_extension(filename, extension) change_extension_support((char *)alloca(strlen(filename)+strlen(extension)), (filename), (extension)) + //extras diff --git a/game/realgame.c b/game/realgame.c index bdb9e53..2c77196 100644 --- a/game/realgame.c +++ b/game/realgame.c @@ -157,7 +157,6 @@ char *change_extension_support(char *buffer, const char *filename,char *new_exte return buffer; } -#define set_file_extension(filename, extension) change_extension_support((char *)alloca(strlen(filename)+strlen(extension)), (filename), (extension)) uint32_t fnv1a_hash(const char *str) { diff --git a/game/skeldal.c b/game/skeldal.c index 4c80ff3..75bd8b0 100644 --- a/game/skeldal.c +++ b/game/skeldal.c @@ -913,6 +913,18 @@ static void patch_error(int err) showview(0,460,640,20); } +void init_DDL_manager() { + + const char *ddlfile = build_pathname(2, gpathtable[SR_DATA],"SKELDAL.DDL"); + ddlfile = local_strdup(ddlfile); + + init_manager(ddlfile, NULL); + SEND_LOG("(GAME) Memory manager initialized. Using DDL: '%s'",ddlfile); + + register_basic_data(); + +} + void init_skeldal(const INI_CONFIG *cfg) { @@ -932,20 +944,15 @@ void init_skeldal(const INI_CONFIG *cfg) general_engine_init(); atexit(done_skeldal); -/* - install_dos_error(device_error,(char *)getmem(4096)+4096);*/ - const char *ddlfile = build_pathname(2, gpathtable[SR_DATA],"SKELDAL.DDL"); - ddlfile = local_strdup(ddlfile); - init_manager(ddlfile, NULL); - SEND_LOG("(GAME) Memory manager initialized. Using DDL: '%s'",ddlfile); + init_DDL_manager(); + texty_knihy=strdup(build_pathname(2,gpathtable[SR_MAP],"kniha.txt")); install_gui(); if (patch_file!=NULL) patch_error(add_patch_file(patch_file)); - register_basic_data(); send_message(E_DONE,E_WATCH,timer); send_message(E_DONE,E_IDLE,redraw_desktop_call); @@ -1588,6 +1595,7 @@ void show_help(const char *arg0) { printf("-f path to configuration file\n" "-a path for adventure file (.adv)\n" + "-s generate string-tables (for localization)\n" "-h this help\n"); exit(0); } @@ -1600,6 +1608,8 @@ void quit_cb_exit_wait(void *_) { exit_wait = 1; } + + int main(int argc,char *argv[]) { def_mman_group_table(gpathtable); @@ -1607,11 +1617,13 @@ int main(int argc,char *argv[]) turn_speed(1); const char *config_name = CONFIG_NAME; const char *adv_config_file = NULL; - for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:")) != -1; ) { + const char *gen_stringtable_path = NULL; + for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:")) != -1; ) { switch (optchr) { case 'f': config_name = local_strdup(optarg);break; case 'a': adv_config_file = local_strdup(optarg);break; case 'h': show_help(argv[0]);break; + case 's': gen_stringtable_path = local_strdup(optarg);break; default: show_help_short(); return 1; } @@ -1637,6 +1649,14 @@ int main(int argc,char *argv[]) } + if (gen_stringtable_path) { + init_DDL_manager(); + generate_string_tables(gen_stringtable_path); + printf("Done\n"); + return 0; + } + + start_check(); purge_temps(1);