From dfad543f6ef7f156c578b3a6adee4b63c0a269cf Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 07:53:12 +0900 Subject: [PATCH 01/10] Implement vmDalkGaiden HLL --- CMakeLists.txt | 1 + src/ffi.c | 2 + src/hll/vmDalkGaiden.c | 109 +++++++++++++++++++++++++++++++++++++++++ src/meson.build | 1 + 4 files changed, 113 insertions(+) create mode 100644 src/hll/vmDalkGaiden.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 65d0cfd..a2f2e1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,6 +182,7 @@ target_sources(xsystem4 PRIVATE src/hll/vmCG.c src/hll/vmChrLoader.c src/hll/vmCursor.c + src/hll/vmDalkGaiden.c src/hll/vmData.c src/hll/vmDialog.c src/hll/vmDrawGauge.c diff --git a/src/ffi.c b/src/ffi.c index fedc90c..5fc695b 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -378,6 +378,7 @@ extern struct static_library lib_vmArray; extern struct static_library lib_vmCG; extern struct static_library lib_vmChrLoader; extern struct static_library lib_vmCursor; +extern struct static_library lib_vmDalkGaiden; extern struct static_library lib_vmData; extern struct static_library lib_vmDialog; extern struct static_library lib_vmDrawGauge; @@ -477,6 +478,7 @@ static struct static_library *static_libraries[] = { &lib_vmCG, &lib_vmChrLoader, &lib_vmCursor, + &lib_vmDalkGaiden, &lib_vmData, &lib_vmDialog, &lib_vmDrawGauge, diff --git a/src/hll/vmDalkGaiden.c b/src/hll/vmDalkGaiden.c new file mode 100644 index 0000000..7863292 --- /dev/null +++ b/src/hll/vmDalkGaiden.c @@ -0,0 +1,109 @@ +/* Copyright (C) 2024 kichikuou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "system4/cg.h" + +#include "asset_manager.h" +#include "hll.h" +#include "vm/heap.h" +#include "vm/page.h" +#include "vmSurface.h" + +HLL_QUIET_UNIMPLEMENTED(, void, vmDalkGaiden, Init, void); + +#define STRUCT_BANK_POS_SLOT 1 +#define MAP_WIDTH 45 +#define MAP_HEIGHT 45 +#define MAP_BACKGROUND_CG 1057 +#define MAP_SPRITE_CG 1058 + +static int vmDalkGaiden_GrepEnemyIndex(int pos, struct page *bank, int *id_out) +{ + if (pos < 0 || !bank || bank->type != ARRAY_PAGE || bank->a_type != AIN_ARRAY_STRUCT) + return 0; + + for (int i = 0; i < bank->nr_vars; i++) { + struct page *elem = heap_get_page(bank->values[i].i); + if (elem->values[STRUCT_BANK_POS_SLOT].i == pos) { + *id_out = i; + return 1; + } + } + return 0; +} + +static void vmDalkGaiden_PutFullMap(int surface, struct page *map_w1, struct page *map_w2, struct page *map_w3, struct page *mask) +{ + struct vm_surface *sf = vm_surface_get(surface); + if (!sf) + return; + + struct cg *cg = asset_cg_load(MAP_BACKGROUND_CG); + if (!cg) + return; + Texture tex; + gfx_init_texture_with_cg(&tex, cg); + cg_free(cg); + gfx_blend_amap(&sf->texture, 0, 0, &tex, 0, 0, tex.w, tex.h); + gfx_delete_texture(&tex); + + cg = asset_cg_load(MAP_SPRITE_CG); + if (!cg) + return; + gfx_init_texture_with_cg(&tex, cg); + cg_free(cg); + + for (int y = 0; y < MAP_HEIGHT; y++) { + for (int x = 0; x < MAP_WIDTH; x++) { + if (y == MAP_HEIGHT - 1 && x % 2 == 1) + continue; + int dx = 15 + 10 * x; + int dy = 15 + 10 * y + x % 2 * 5; + if (mask->values[y * MAP_WIDTH + x].i) { + gfx_blend_amap(&sf->texture, dx, dy, &tex, 0, 0, 12, 9); + continue; + } + + int w1 = map_w1->values[y * MAP_WIDTH + x].i; + int w2 = map_w2->values[y * MAP_WIDTH + x].i; + int w3 = map_w3->values[y * MAP_WIDTH + x].i; + gfx_blend_amap(&sf->texture, dx, dy, &tex, w1 < 0 ? 12 : 24, 0, 12, 9); + + int sprite = -1; + if (w3 >= 0) { + sprite = (w3 < 8) ? 4 + : (w3 < 16) ? 3 + : (w3 >= 32) ? 6 + : (w3 - 16) / 2 + 8; + } else if (w2 >= 0) { + sprite = 5; + } + if (sprite >= 0) { + int sx = sprite % 8 * 12; + int sy = sprite / 8 * 9; + gfx_blend_amap(&sf->texture, dx, dy, &tex, sx, sy, 12, 9); + } + } + } + + gfx_delete_texture(&tex); +} + +HLL_LIBRARY(vmDalkGaiden, + HLL_EXPORT(Init, vmDalkGaiden_Init), + HLL_EXPORT(GrepEnemyIndex, vmDalkGaiden_GrepEnemyIndex), + HLL_EXPORT(PutFullMap, vmDalkGaiden_PutFullMap) + ); diff --git a/src/meson.build b/src/meson.build index 019fd93..4246fb8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -136,6 +136,7 @@ xsystem4 = [version_h, 'hll/vmCG.c', 'hll/vmChrLoader.c', 'hll/vmCursor.c', + 'hll/vmDalkGaiden.c', 'hll/vmData.c', 'hll/vmDialog.c', 'hll/vmDrawGauge.c', From 4e4f0b868342d3c6f0a11dc20ba282de2da97b91 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 07:58:59 +0900 Subject: [PATCH 02/10] vmDrawMsg: Implement tags used in DALK Gaiden --- src/hll/vmDrawMsg.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hll/vmDrawMsg.c b/src/hll/vmDrawMsg.c index cebf738..5cbacc4 100644 --- a/src/hll/vmDrawMsg.c +++ b/src/hll/vmDrawMsg.c @@ -146,7 +146,7 @@ static int vmDrawMsg_Draw(int handle) char *s = dm->text->text; const int line_space = 2; while (*s) { - int skiplen = 0, a1, a2, a3; + int skiplen = 0, a1, a2, a3, a4, a5, a6; if (*s != '<') { char *lb = strchr(s, '<'); if (lb) { @@ -174,6 +174,11 @@ static int vmDrawMsg_Draw(int handle) dm->pos.x += gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &dm->style.ts, false); if (lb) *lb = '<'; + } else if (sscanf(s, "<@C%d,%d,%d,%d,%d,%d>%n", &a1, &a2, &a3, &a4, &a5, &a6, &skiplen) == 6) { + // FIXME: This tag specifies a vertical gradient from (a1, a2, a3) + // to (a4, a5, a6), but we just use the average color. + dm->initial_style.ts.color = dm->style.ts.color = + COLOR((a1 + a4) / 2, (a2 + a5) / 2, (a3 + a6) / 2, 255); } else if (sscanf(s, "%n", &a1, &a2, &a3, &skiplen) == 3) { dm->style.ts.color = COLOR(a1, a2, a3, 255); } else if (sscanf(s, "<@C%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) { @@ -181,6 +186,11 @@ static int vmDrawMsg_Draw(int handle) } else if (!strncmp(s, "", 4)) { skiplen = 4; dm->style.ts.color = dm->initial_style.ts.color; + } else if (sscanf(s, "%n", &a1, &skiplen) == 1) { + dm->style.ts.weight = a1 ? FW_HEAVY : FW_BOLD; + } else if (sscanf(s, "%n", &a1, &skiplen) == 1) { + dm->style.ts.font_size = NULL; + dm->style.ts.face = a1 ? FONT_MINCHO : FONT_GOTHIC; } else if (sscanf(s, "%n", &a1, &skiplen) == 1) { dm->style.bold = a1; } else if (sscanf(s, "<@E%d>%n", &a1, &skiplen) == 1) { From d3bd28a0c1ce3763b4a3f1753246e48de9d6dced Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 08:52:20 +0900 Subject: [PATCH 03/10] Implement vmFile functions for DALK Gaiden --- src/hll/vmFile.c | 174 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 128 insertions(+), 46 deletions(-) diff --git a/src/hll/vmFile.c b/src/hll/vmFile.c index 33dd2da..65711d6 100644 --- a/src/hll/vmFile.c +++ b/src/hll/vmFile.c @@ -31,7 +31,8 @@ enum vm_file_mode { VM_FILE_READ = 1, - VM_FILE_WRITE = 2 + VM_FILE_WRITE = 2, + VM_FILE_READWRITE = 3 }; struct vm_file { @@ -155,7 +156,8 @@ static int vmFile_Open(struct string *string, int type) char *path = savedir_path(string->text); vf->path = path; - if (type == VM_FILE_READ) { + if (type == VM_FILE_READ || + type == VM_FILE_READWRITE /* Used in DALK Gaiden, but only for reading */) { size_t len; uint8_t *data = file_read(path, &len); if (!data) { @@ -266,37 +268,52 @@ static int vmFile_Decode(int handle, int seed) return 1; } -//int vmFile_ReadArrayChar(int handle, struct page **pIVMArray); -//int vmFile_ReadArrayShort(int handle, struct page **pIVMArray); -//int vmFile_ReadArrayInt(int handle, struct page **pIVMArray); -//int vmFile_ReadArrayFloat(int handle, struct page **pIVMArray); -//int vmFile_ReadArrayString(int handle, struct page **pIVMArray); -//int vmFile_ReadArrayStruct(int handle, struct page **pIVMArray); - -static int vmFile_ReadStruct(int handle, struct page **_page) +static int vmFile_ReadArrayChar(int handle, struct page **_array) { struct vm_file *vf = id_pool_get(&pool, handle); if (!vf) return 0; - struct page *page = *_page; - if (page->type != STRUCT_PAGE) { - VM_ERROR("vmFile.ReadStruct of non-struct"); + struct page *array = *_array; + if (array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1) + VM_ERROR("Type error"); + for (int i = 0; i < array->nr_vars; i++) { + array->values[i].i = (int8_t)buffer_read_u8(&vf->buf); } + return 1; +} - read_page(vf, page); +//int vmFile_ReadArrayShort(int handle, struct page **pIVMArray); + +static int vmFile_ReadPage(int handle, struct page **page) +{ + struct vm_file *vf = id_pool_get(&pool, handle); + if (!vf) + return 0; + + read_page(vf, *page); return 1; } //int vmFile_ReadGlobal(int handle, IMainSystem pIMainSystem); -//int vmFile_WriteArrayChar(int handle, struct page *pIVMArray); -//int vmFile_WriteArrayShort(int handle, struct page *pIVMArray); -//int vmFile_WriteArrayInt(int handle, struct page *pIVMArray); -//int vmFile_WriteArrayFloat(int handle, struct page *pIVMArray); -//int vmFile_WriteArrayString(int handle, struct page *pIVMArray); -//int vmFile_WriteArrayStruct(int handle, struct page *pIVMArray); -static int vmFile_WriteStruct(int handle, struct page *page) +static int vmFile_WriteArrayChar(int handle, struct page *array) +{ + struct vm_file *vf = id_pool_get(&pool, handle); + if (!vf) + return 0; + if (array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1) + VM_ERROR("Type error"); + + for (int i = 0; i < array->nr_vars; i++) { + buffer_write_int8(&vf->buf, array->values[i].i); + } + return 1; +} + +//int vmFile_WriteArrayShort(int handle, struct page *pIVMArray); + +static int vmFile_WritePage(int handle, struct page *page) { struct vm_file *vf = id_pool_get(&pool, handle); if (!vf) @@ -306,11 +323,35 @@ static int vmFile_WriteStruct(int handle, struct page *page) } //int vmFile_WriteGlobal(int handle, IMainSystem pIMainSystem); -//int vmFile_SeekChar(int handle, int nPos, int nAbsolute); -//int vmFile_SeekShort(int handle, int nPos, int nAbsolute); -//int vmFile_SeekInt(int handle, int nPos, int nAbsolute); -//int vmFile_SeekFloat(int handle, int nPos, int nAbsolute); -//int vmFile_SeekString(int handle, int nPos, int nAbsolute); + +static int vmFile_SeekChar(int handle, int pos, int absolute) +{ + struct vm_file *vf = id_pool_get(&pool, handle); + if (!vf) + return 0; + if (absolute) + buffer_seek(&vf->buf, pos); + else + buffer_skip(&vf->buf, pos); + return 1; +} + +static int vmFile_SeekShort(int handle, int pos, int absolute) +{ + return vmFile_SeekChar(handle, pos * 2, absolute); +} + +static int vmFile_SeekInt(int handle, int pos, int absolute) +{ + return vmFile_SeekChar(handle, pos * 4, absolute); +} + +static int vmFile_SeekFloat(int handle, int pos, int absolute) +{ + return vmFile_SeekChar(handle, pos * 4, absolute); +} + +//int vmFile_SeekString(int handle, int pos, int absolute); //int vmFile_SizeChar(int handle); //int vmFile_SizeShort(int handle); //int vmFile_SizeInt(int handle); @@ -327,8 +368,49 @@ static int vmFile_Delete(struct string *string) } //int vmFile_GetTime(struct string *pIString, struct page **pIVMStruct); -//int vmFile_Find(struct string *pIWildString, struct string **pIString, int *pnCount); -//int vmFile_MakeDirectory(struct string *pIString); + +// XXX: Supports patterns with only a single '*' +static bool wildcard_match(const char *pat, const char *s) +{ + const char *star = strchr(pat, '*'); + if (!star) + return !strcmp(pat, s); + return !strncmp(pat, s, star - pat) && !strcmp(star + 1, s + strlen(s) - strlen(star + 1)); +} + +static int vmFile_Find(struct string *wild_string, struct string **fname_out, int *count) +{ + int found = 0; + char *wild_path = savedir_path(wild_string->text); + UDIR *dir = opendir_utf8(path_dirname(wild_path)); + if (dir) { + char *d_name; + const char *pattern = path_basename(wild_path); + for (int i = 0; !found && (d_name = readdir_utf8(dir)) != NULL; i++) { + if (i >= *count) { + *count = i; + if (wildcard_match(pattern, d_name)) { + if (*fname_out) + free_string(*fname_out); + *fname_out = cstr_to_string(d_name); + found = 1; + } + } + free(d_name); + } + closedir_utf8(dir); + } + free(wild_path); + return found; +} + +static int vmFile_MakeDirectory(struct string *string) +{ + char *path = savedir_path(string->text); + int r = mkdir_p(path); + free(path); + return r == 0; +} HLL_LIBRARY(vmFile, HLL_EXPORT(_ModuleInit, vmFile_ModuleInit), @@ -338,26 +420,26 @@ HLL_LIBRARY(vmFile, HLL_EXPORT(Close, vmFile_Close), HLL_EXPORT(Encode, vmFile_Encode), HLL_EXPORT(Decode, vmFile_Decode), - HLL_TODO_EXPORT(ReadArrayChar, vmFile_ReadArrayChar), + HLL_EXPORT(ReadArrayChar, vmFile_ReadArrayChar), HLL_TODO_EXPORT(ReadArrayShort, vmFile_ReadArrayShort), - HLL_TODO_EXPORT(ReadArrayInt, vmFile_ReadArrayInt), - HLL_TODO_EXPORT(ReadArrayFloat, vmFile_ReadArrayFloat), - HLL_TODO_EXPORT(ReadArrayString, vmFile_ReadArrayString), - HLL_TODO_EXPORT(ReadArrayStruct, vmFile_ReadArrayStruct), - HLL_EXPORT(ReadStruct, vmFile_ReadStruct), + HLL_EXPORT(ReadArrayInt, vmFile_ReadPage), + HLL_EXPORT(ReadArrayFloat, vmFile_ReadPage), + HLL_EXPORT(ReadArrayString, vmFile_ReadPage), + HLL_EXPORT(ReadArrayStruct, vmFile_ReadPage), + HLL_EXPORT(ReadStruct, vmFile_ReadPage), HLL_TODO_EXPORT(ReadGlobal, vmFile_ReadGlobal), - HLL_TODO_EXPORT(WriteArrayChar, vmFile_WriteArrayChar), + HLL_EXPORT(WriteArrayChar, vmFile_WriteArrayChar), HLL_TODO_EXPORT(WriteArrayShort, vmFile_WriteArrayShort), - HLL_TODO_EXPORT(WriteArrayInt, vmFile_WriteArrayInt), - HLL_TODO_EXPORT(WriteArrayFloat, vmFile_WriteArrayFloat), - HLL_TODO_EXPORT(WriteArrayString, vmFile_WriteArrayString), - HLL_TODO_EXPORT(WriteArrayStruct, vmFile_WriteArrayStruct), - HLL_EXPORT(WriteStruct, vmFile_WriteStruct), + HLL_EXPORT(WriteArrayInt, vmFile_WritePage), + HLL_EXPORT(WriteArrayFloat, vmFile_WritePage), + HLL_EXPORT(WriteArrayString, vmFile_WritePage), + HLL_EXPORT(WriteArrayStruct, vmFile_WritePage), + HLL_EXPORT(WriteStruct, vmFile_WritePage), HLL_TODO_EXPORT(WriteGlobal, vmFile_WriteGlobal), - HLL_TODO_EXPORT(SeekChar, vmFile_SeekChar), - HLL_TODO_EXPORT(SeekShort, vmFile_SeekShort), - HLL_TODO_EXPORT(SeekInt, vmFile_SeekInt), - HLL_TODO_EXPORT(SeekFloat, vmFile_SeekFloat), + HLL_EXPORT(SeekChar, vmFile_SeekChar), + HLL_EXPORT(SeekShort, vmFile_SeekShort), + HLL_EXPORT(SeekInt, vmFile_SeekInt), + HLL_EXPORT(SeekFloat, vmFile_SeekFloat), HLL_TODO_EXPORT(SeekString, vmFile_SeekString), HLL_TODO_EXPORT(SizeChar, vmFile_SizeChar), HLL_TODO_EXPORT(SizeShort, vmFile_SizeShort), @@ -367,6 +449,6 @@ HLL_LIBRARY(vmFile, HLL_TODO_EXPORT(Copy, vmFile_Copy), HLL_EXPORT(Delete, vmFile_Delete), HLL_TODO_EXPORT(GetTime, vmFile_GetTime), - HLL_TODO_EXPORT(Find, vmFile_Find), - HLL_TODO_EXPORT(MakeDirectory, vmFile_MakeDirectory) + HLL_EXPORT(Find, vmFile_Find), + HLL_EXPORT(MakeDirectory, vmFile_MakeDirectory) ); From 877ca1f74eccf881dada7962c5f93ed4f5c0972e Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 27 Jul 2024 10:50:23 +0900 Subject: [PATCH 04/10] Implement vmSystem functions for DALK Gaiden --- include/vm.h | 1 + src/hll/vmSystem.c | 15 +++++++++++---- src/vm.c | 4 +--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/vm.h b/include/vm.h index 2cfe68f..20355a0 100644 --- a/include/vm.h +++ b/include/vm.h @@ -128,6 +128,7 @@ struct string *string_format(struct string *fmt, union vm_value arg, enum string void vm_stack_trace(void); _Noreturn void _vm_error(const char *fmt, ...); _Noreturn void vm_exit(int code); +_Noreturn void vm_reset(void); #ifdef __ANDROID__ // Report the error with a message box and exit. diff --git a/src/hll/vmSystem.c b/src/hll/vmSystem.c index d05a440..a7df8e0 100644 --- a/src/hll/vmSystem.c +++ b/src/hll/vmSystem.c @@ -49,8 +49,15 @@ void vmSystem_CurrentTime(struct page **page) date[6].i = tm->tm_wday; } -//void vmSystem_Reset(void); -//void vmSystem_Shutdown(void); +static void vmSystem_Reset(void) +{ + vm_reset(); +} + +static void vmSystem_Shutdown(void) +{ + vm_exit(0); +} static int vmSystem_OpenWeb(struct string *url) { @@ -62,8 +69,8 @@ HLL_WARN_UNIMPLEMENTED(0, int, vmSystem, AddURLMenu, struct string *title, struc HLL_LIBRARY(vmSystem, HLL_EXPORT(Init, vmSystem_Init), HLL_EXPORT(CurrentTime, vmSystem_CurrentTime), - HLL_TODO_EXPORT(Reset, vmSystem_Reset), - HLL_TODO_EXPORT(Shutdown, vmSystem_Shutdown), + HLL_EXPORT(Reset, vmSystem_Reset), + HLL_EXPORT(Shutdown, vmSystem_Shutdown), HLL_EXPORT(OpenWeb, vmSystem_OpenWeb), HLL_EXPORT(AddURLMenu, vmSystem_AddURLMenu) ); diff --git a/src/vm.c b/src/vm.c index 5546c5e..01b9cc5 100644 --- a/src/vm.c +++ b/src/vm.c @@ -458,8 +458,6 @@ static const SDL_MessageBoxButtonData buttons[] = { { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "Cancel" }, }; -static _Noreturn void vm_reset(void); - static struct string *get_func_stack_name(int index) { int i = call_stack_ptr - (1 + index); @@ -2337,7 +2335,7 @@ static void vm_free(void) static jmp_buf reset_buf; -static _Noreturn void vm_reset(void) +_Noreturn void vm_reset(void) { vm_free(); longjmp(reset_buf, 1); From cb4a04ce14368bb49c42d02053fbf0d54273cb4f Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 27 Jul 2024 09:55:11 +0900 Subject: [PATCH 05/10] Implement vmString functions for DALK Gaiden --- src/hll/vmString.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/hll/vmString.c b/src/hll/vmString.c index b8f3287..43078c8 100644 --- a/src/hll/vmString.c +++ b/src/hll/vmString.c @@ -15,6 +15,7 @@ */ #include +#include #include #include "system4/string.h" @@ -59,11 +60,20 @@ static struct string *vmString_IntToStringExA(int num, int figure, int zero) return format_int(num, figure, zero, false); } -//int vmString_StringToInt(struct string *pIString); +static int vmString_StringToInt(struct string *string) +{ + return atoi(string->text); +} + //struct string *vmString_FloatToString(float fNum); //struct string *vmString_FloatToStringA(float fNum); //float vmString_StringToFloat(struct string *pIString); -//struct string *vmString_GetString(struct string *pIString, int nIndex, int nLength); + +static struct string *vmString_GetString(struct string *string, int index, int length) +{ + return string_copy(string, index, length); +} + //struct string *vmString_CutTag(struct string *pIString); //void vmString_TransLower(struct string **pIString); //void vmString_TransUpper(struct string **pIString); @@ -76,11 +86,11 @@ HLL_LIBRARY(vmString, HLL_EXPORT(IntToStringA, vmString_IntToStringA), HLL_EXPORT(IntToStringEx, vmString_IntToStringEx), HLL_EXPORT(IntToStringExA, vmString_IntToStringExA), - HLL_TODO_EXPORT(StringToInt, vmString_StringToInt), + HLL_EXPORT(StringToInt, vmString_StringToInt), HLL_TODO_EXPORT(FloatToString, vmString_FloatToString), HLL_TODO_EXPORT(FloatToStringA, vmString_FloatToStringA), HLL_TODO_EXPORT(StringToFloat, vmString_StringToFloat), - HLL_TODO_EXPORT(GetString, vmString_GetString), + HLL_EXPORT(GetString, vmString_GetString), HLL_TODO_EXPORT(CutTag, vmString_CutTag), HLL_TODO_EXPORT(TransLower, vmString_TransLower), HLL_TODO_EXPORT(TransUpper, vmString_TransUpper), From c3c241adf58b2d7650f5ac669e1e16acb35078fc Mon Sep 17 00:00:00 2001 From: kichikuou Date: Wed, 24 Jul 2024 10:56:30 +0900 Subject: [PATCH 06/10] vmDrawNumber: Respect `space` parameter --- src/hll/vmDrawNumber.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hll/vmDrawNumber.c b/src/hll/vmDrawNumber.c index 32be191..786cddd 100644 --- a/src/hll/vmDrawNumber.c +++ b/src/hll/vmDrawNumber.c @@ -61,7 +61,7 @@ static int vmDrawNumber_Open(int cg_no, int kind, int figure, int space) if (!cg) return 0; - int width = cg->metrics.w / 10 * figure; + int width = (cg->metrics.w / 10 + space) * figure; int height = cg->metrics.h; int handle = id_pool_get_unused(&pool); @@ -126,7 +126,7 @@ static void vmDrawNumber_Draw(int handle, int num) } int dw = dn->digits.w / 10; - int w = dw * strlen(buf); + int w = (dw + dn->space) * strlen(buf); int h = dn->digits.h; int left; @@ -151,10 +151,10 @@ static void vmDrawNumber_Draw(int handle, int num) for (int i = 0; buf[i]; i++) { switch (buf[i]) { case '-': - gfx_copy_with_alpha_map(&sf->texture, left + i * dw, 0, &dn->sign, 0, 0, dw, h); + gfx_copy_with_alpha_map(&sf->texture, left + i * (dw + dn->space), 0, &dn->sign, 0, 0, dw, h); break; default: - gfx_copy_with_alpha_map(&sf->texture, left + i * dw, 0, &dn->digits, (buf[i] - '0') * dw, 0, dw, h); + gfx_copy_with_alpha_map(&sf->texture, left + i * (dw + dn->space), 0, &dn->digits, (buf[i] - '0') * dw, 0, dw, h); break; } } From bcf81af71d73a207151138ae4f89c67f32b303fb Mon Sep 17 00:00:00 2001 From: kichikuou Date: Wed, 24 Jul 2024 10:30:46 +0900 Subject: [PATCH 07/10] Fix vmMsgSkip.Query It should return true only if message skip is turned on. --- src/hll/MsgSkip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hll/MsgSkip.c b/src/hll/MsgSkip.c index 37bf752..7eb1e2d 100644 --- a/src/hll/MsgSkip.c +++ b/src/hll/MsgSkip.c @@ -169,7 +169,7 @@ static int vmMsgSkip_Query(possibly_unused int handle, int msgnum) int r = MsgSkip_GetFlag(msgnum); // vmMsgSkip does not have an explicit set function. MsgSkip_SetFlag(msgnum); - return r; + return state && r; } HLL_LIBRARY(vmMsgSkip, From dd77de027b596c57c98fb445171ab0a217f906f9 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 09:09:21 +0900 Subject: [PATCH 08/10] Implement vmSound functions for DALK Gaiden --- src/hll/vmSound.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/hll/vmSound.c b/src/hll/vmSound.c index 2d3e8f4..ad93815 100644 --- a/src/hll/vmSound.c +++ b/src/hll/vmSound.c @@ -26,7 +26,8 @@ static void vmSound_Init(possibly_unused void *imainsystem) } //void vmSound_Enable(int nEnable); -//void vmSound_SetType(int nType); + +HLL_QUIET_UNIMPLEMENTED(, void, vmSound, SetType, int type); static int vmSound_Load(int channel, int num) { @@ -41,9 +42,10 @@ static int vmSound_LoadMemory(int channel, int memory) return wav_prepare_from_archive_data(channel, dfile); } -static void vmSound_Unload(int channel, possibly_unused int length) +static void vmSound_Unload(int channel, int length) { - wav_unprepare(channel); + for (int i = 0; i < length; i++) + wav_unprepare(channel + i); } static int vmSound_Play(int channel, possibly_unused int length) @@ -60,7 +62,16 @@ static int vmSound_RingPlay(int channel, int ring) } //int vmSound_Stop(int channel, int nLength); -//int vmSound_IsPlay(int channel, int nLength); + +static int vmSound_IsPlay(int channel, int length) +{ + for (int i = 0; i < length; i++) { + if (wav_is_playing(channel + i)) + return 1; + } + return 0; +} + //void vmSound_Wait(int channel, int nLength); //int vmSound_Fade(int channel, int nLength, int nTime, int nVolume, int nStopFlag); //int vmSound_StopFade(int channel, int nLength); @@ -70,14 +81,14 @@ static int vmSound_RingPlay(int channel, int ring) HLL_LIBRARY(vmSound, HLL_EXPORT(Init, vmSound_Init), HLL_TODO_EXPORT(Enable, vmSound_Enable), - HLL_TODO_EXPORT(SetType, vmSound_SetType), + HLL_EXPORT(SetType, vmSound_SetType), HLL_EXPORT(Load, vmSound_Load), HLL_EXPORT(LoadMemory, vmSound_LoadMemory), HLL_EXPORT(Unload, vmSound_Unload), HLL_EXPORT(Play, vmSound_Play), HLL_EXPORT(RingPlay, vmSound_RingPlay), HLL_TODO_EXPORT(Stop, vmSound_Stop), - HLL_TODO_EXPORT(IsPlay, vmSound_IsPlay), + HLL_EXPORT(IsPlay, vmSound_IsPlay), HLL_TODO_EXPORT(Wait, vmSound_Wait), HLL_TODO_EXPORT(Fade, vmSound_Fade), HLL_TODO_EXPORT(StopFade, vmSound_StopFade), From a2c225bf64b83c330b920b5844b5102b03207ef5 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 09:24:07 +0900 Subject: [PATCH 09/10] vmSprite changes for DALK Gaiden * SetFind(2) lets the sprite to participate in hit testing even if it is not visible. * SetAnime() respects frame_s and frame_e parameters. Sprites animate only when `current` is within the range of [frame_s, frame_e]. * SetCurrent() resets animation state. --- src/hll/vmSprite.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/hll/vmSprite.c b/src/hll/vmSprite.c index cda19a0..9e3d803 100644 --- a/src/hll/vmSprite.c +++ b/src/hll/vmSprite.c @@ -35,12 +35,21 @@ struct child_surface { }; struct animation { + int frame_s; + int frame_e; int nr_frames; int current_frame; + uint64_t time_origin; int total_frame_time; int frame_times[]; }; +enum findability { + NOT_FINDABLE = 0, + FINDABLE_WHEN_VISIBLE = 1, + ALWAYS_FINDABLE = 2 +}; + struct vm_sprite { struct sprite sp; int surface; @@ -48,7 +57,7 @@ struct vm_sprite { Rectangle rect; int current; int id; - bool findable; + enum findability findability; struct animation *anime; struct id_pool children; }; @@ -77,7 +86,11 @@ static void update_animation(void) struct vm_sprite *sp = id_pool_get(&pool, id); if (!sp || !sp->anime) continue; - int t = now % sp->anime->total_frame_time; + if (sp->current < sp->anime->frame_s || sp->current > sp->anime->frame_e) { + sp->anime->current_frame = 0; + continue; + } + int t = (now - sp->anime->time_origin) % sp->anime->total_frame_time; int frame; for (frame = 0; t >= sp->anime->frame_times[frame]; frame++) t -= sp->anime->frame_times[frame]; @@ -158,6 +171,7 @@ static cJSON *vm_sprite_to_json(struct sprite *_sp, bool verbose) cJSON_AddNumberToObject(sprite, "type", sp->type); cJSON_AddItemToObjectCS(sprite, "rect", rectangle_to_json(&sp->rect, verbose)); cJSON_AddNumberToObject(sprite, "current", sp->current); + cJSON_AddNumberToObject(sprite, "findability", sp->findability); cJSON_AddItemToObjectCS(sprite, "children", children = cJSON_CreateArray()); for (int id = id_pool_get_first(&sp->children); id >= 0; id = id_pool_get_next(&sp->children, id)) { @@ -278,6 +292,9 @@ static int vmSprite_SetCurrent(int sprite, int current) return 0; if (sp->current != current) { sp->current = current; + if (sp->anime) { + sp->anime->time_origin = SDL_GetTicks64(); + } vm_sprite_dirty(sp); } return 1; @@ -357,7 +374,7 @@ static void vmSprite_SetFind(int sprite, int find) { struct vm_sprite *sp = id_pool_get(&pool, sprite); if (sp) - sp->findable = !!find; + sp->findability = find; } static void vmSprite_SetID(int sprite, int id) @@ -377,8 +394,11 @@ static int vmSprite_SetAnime(int sprite, int frame_s, int frame_e, struct page * free(sp->anime); int nr_frames = array->nr_vars; struct animation *a = xmalloc(sizeof(struct animation) + nr_frames * sizeof(int)); + a->frame_s = frame_s; + a->frame_e = frame_e; a->nr_frames = nr_frames; a->current_frame = 0; + a->time_origin = SDL_GetTicks64(); a->total_frame_time = 0; for (int i = 0; i < a->nr_frames; i++) { a->total_frame_time += a->frame_times[i] = array->values[i].i; @@ -502,7 +522,9 @@ static int vmSprite_FindPos(int x, int y) Point p = { .x = x, .y = y }; for (int id = id_pool_get_first(&pool); id >= 0; id = id_pool_get_next(&pool, id)) { struct vm_sprite *sp = id_pool_get(&pool, id); - if (!sp || !sp->findable) + if (!sp || sp->findability == NOT_FINDABLE) + continue; + if (sp->findability == FINDABLE_WHEN_VISIBLE && sp->sp.hidden) continue; if (!SDL_PointInRect(&p, &sp->rect)) continue; @@ -575,7 +597,7 @@ static int vmSprite_GetShow(int sprite) static int vmSprite_GetFind(int sprite) { struct vm_sprite *sp = id_pool_get(&pool, sprite); - return sp ? sp->findable : 0; + return sp ? sp->findability : 0; } static int vmSprite_GetID(int sprite) From 8f7d9886c26288bb1f6a895086ff7b901af90d63 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 28 Jul 2024 09:48:02 +0900 Subject: [PATCH 10/10] Update game compatibility table DALK Gaiden is now supported. --- game_compatibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game_compatibility.md b/game_compatibility.md index 3359708..eb6a0c2 100644 --- a/game_compatibility.md +++ b/game_compatibility.md @@ -14,7 +14,7 @@ issues, please let me know or open a pull request to update this table. | Game | Status | Notes | | ------------------------------------------------------- | ----------- | ----- | -| DALK外伝 | Unsupported | | +| DALK外伝 | Supported | | | ままにょにょ | Supported | | | 大番長 -Big Bang Age- | Supported | | | Daibanchou -Big Bang Age- (EN) | Supported | |