Add support for group save format v7

V5 is used until Daiteikoku, and v7 since Rance Quest. Since both are
Ain v6, the save version is determined by the presence of the "MainVM"
field in AliceStart.ini.
This commit is contained in:
kichikuou
2024-09-16 09:01:49 +09:00
parent 489cfe5a96
commit 9e2f03d8be
4 changed files with 31 additions and 9 deletions
+1
View File
@@ -23,6 +23,7 @@
struct config {
char *game_name;
char *ain_filename;
char *vm_name;
char *game_dir;
char *save_dir;
char *home_dir;
+26 -8
View File
@@ -88,10 +88,11 @@ static struct gsave_flat_array *collect_flat_arrays(struct page *page, struct gs
fa = collect_flat_arrays(heap_get_page(page->values[i].i), fa, save);
return fa;
}
enum ain_data_type type = variable_type(page, 0, NULL, NULL);
fa->nr_values = page->nr_vars;
fa->type = type;
fa->values = xcalloc(fa->nr_values, sizeof(struct gsave_array_value));
for (int i = 0; i < page->nr_vars; i++) {
enum ain_data_type type = variable_type(page, i, NULL, NULL);
fa->values[i].type = type;
fa->values[i].value = add_value_to_gsave(type, page->values[i], save);
}
@@ -123,6 +124,11 @@ static int32_t add_value_to_gsave(enum ain_data_type type, union vm_value val, s
.nr_indices = st->nr_members,
.indices = xcalloc(st->nr_members, sizeof(int32_t)),
};
if (save->version >= 7) {
rec.struct_index = gsave_get_struct_def(save, st->name);
if (rec.struct_index < 0)
rec.struct_index = gsave_add_struct_def(save, st);
}
for (int i = 0; i < page->nr_vars; i++) {
enum ain_data_type type = st->members[i].type.data;
int32_t value = add_value_to_gsave(type, page->values[i], save);
@@ -166,6 +172,14 @@ static int32_t add_value_to_gsave(enum ain_data_type type, union vm_value val, s
}
}
static int get_gsave_version(void)
{
if (AIN_VERSION_GTE(ain, 6, 0)) {
return config.vm_name ? 5 : 7;
}
return AIN_VERSION_GTE(ain, 5, 0) ? 5 : 4;
}
int save_globals(const char *keyname, const char *filename, const char *group_name, int *n_out)
{
int group = -1;
@@ -184,8 +198,7 @@ int save_globals(const char *keyname, const char *filename, const char *group_na
nr_vars = ain->nr_globals;
}
int gsave_version = AIN_VERSION_GTE(ain, 5, 0) ? 5 : 4;
struct gsave *save = gsave_create(gsave_version, keyname, ain->nr_globals, group_name);
struct gsave *save = gsave_create(get_gsave_version(), keyname, ain->nr_globals, group_name);
gsave_add_globals_record(save, nr_vars);
struct gsave_global *global = save->globals;
@@ -450,27 +463,32 @@ static union vm_value gsave_to_vm_value(struct gsave *save, enum ain_data_type t
case AIN_STRING:
{
int slot = heap_alloc_slot(VM_STRING);
heap[slot].s = string_ref(save->strings[value]);
heap[slot].s = string_ref(value == GSAVE7_EMPTY_STRING ? &EMPTY_STRING : save->strings[value]);
return vm_int(slot);
}
case AIN_STRUCT:
{
struct gsave_record *rec = &save->records[value];
struct ain_struct *st = &ain->structures[struct_type];
if (strcmp(rec->struct_name, st->name))
struct gsave_struct_def *sd =
save->version >= 7 ? &save->struct_defs[rec->struct_index] : NULL;
const char *struct_name = sd ? sd->name : rec->struct_name;
if (strcmp(struct_name, st->name))
VM_ERROR("Bad save file: structure name mismatch");
int slot = alloc_struct(struct_type);
struct page *page = heap[slot].page;
for (int i = 0; i < rec->nr_indices; i++) {
struct gsave_keyval *kv = &save->keyvals[rec->indices[i]];
int index = struct_member_index(st, kv->name);
const char *field_name = sd ? sd->fields[i].name : kv->name;
enum ain_data_type field_type = sd ? sd->fields[i].type : kv->type;
int index = struct_member_index(st, field_name);
if (index < 0) {
WARNING("structure %s has no member named %s", display_sjis0(rec->struct_name), display_sjis1(kv->name));
WARNING("structure %s has no member named %s", display_sjis0(struct_name), display_sjis1(field_name));
continue;
}
int struct_type, array_rank;
enum ain_data_type data_type = variable_type(page, index, &struct_type, &array_rank);
if (data_type != kv->type)
if (data_type != field_type)
VM_ERROR("Bad save file: structure member type mismatch");
union vm_value val = gsave_to_vm_value(save, data_type, struct_type, array_rank, kv->value);
page->values[index] = val;
+3
View File
@@ -49,6 +49,7 @@ void apply_game_specific_hacks(struct ain *ain);
struct config config = {
.game_name = NULL,
.ain_filename = NULL,
.vm_name = NULL,
.game_dir = NULL,
.save_dir = NULL,
.home_dir = NULL,
@@ -133,6 +134,8 @@ static bool read_config(const char *path)
config.game_name = strdup(ini_string(&ini[i])->text);
} else if (!strcmp(ini[i].name->text, "CodeName")) {
config.ain_filename = strdup(ini_string(&ini[i])->text);
} else if (!strcmp(ini[i].name->text, "MainVM")) {
config.vm_name = strdup(ini_string(&ini[i])->text);
} else if (!strcmp(ini[i].name->text, "SaveFolder")) {
config.save_dir = strdup(ini_string(&ini[i])->text);
} else if (!strcmp(ini[i].name->text, "ViewWidth")) {