diff --git a/include/parts.h b/include/parts.h index 2ceef31..42b2650 100644 --- a/include/parts.h +++ b/include/parts.h @@ -176,6 +176,19 @@ void PE_EndInput(void); int PE_GetClickPartsNumber(void); bool PE_IsCursorIn(int parts_no, int mouse_x, int mouse_y, int state); +// message.c +void PE_ReleaseMessage(void); +void PE_PopMessage(void); +int PE_GetMessageType(void); +int PE_GetMessagePartsNumber(void); +int PE_GetMessageDelegateIndex(void); +int PE_GetMessageVariableCount(void); +int PE_GetMessageVariableType(int index); +int PE_GetMessageVariableInt(int index); +float PE_GetMessageVariableFloat(int index); +bool PE_GetMessageVariableBool(int index); +void PE_GetMessageVariableString(int index, struct string **out); + // motion.c void PE_AddMotionPos(int parts_no, int begin_x, int begin_y, int end_x, int end_y, int begin_t, int end_t); void PE_AddMotionPos_curve(int parts_no, int begin_x, int begin_y, int end_x, int end_y, diff --git a/src/hll/PartsEngine.c b/src/hll/PartsEngine.c index 31de638..cc8f70b 100644 --- a/src/hll/PartsEngine.c +++ b/src/hll/PartsEngine.c @@ -143,8 +143,6 @@ static int PartsEngine_PartsFunc(int func_id, struct page **array_int, } HLL_WARN_UNIMPLEMENTED(, void, PartsEngine, StopSoundWithoutSystemSound); -HLL_WARN_UNIMPLEMENTED(, void, PartsEngine, ReleaseMessage, void); -HLL_WARN_UNIMPLEMENTED(0, int, PartsEngine, GetMessageType, void); HLL_WARN_UNIMPLEMENTED(, void, PartsEngine, Parts_SetPassCursor, int Number, bool Pass); static void PartsEngine_PreLink(void); @@ -332,18 +330,18 @@ HLL_LIBRARY(PartsEngine, HLL_TODO_EXPORT(ReleaseActivity, PartsEngine_ReleaseActivity), HLL_TODO_EXPORT(CrateActivityBinary, PartsEngine_CrateActivityBinary), HLL_TODO_EXPORT(ReadActivityBinary, PartsEngine_ReadActivityBinary), - HLL_EXPORT(ReleaseMessage, PartsEngine_ReleaseMessage), - HLL_TODO_EXPORT(PopMessage, PartsEngine_PopMessage), - HLL_TODO_EXPORT(GetMessagePartsNumber, PartsEngine_GetMessagePartsNumber), - HLL_TODO_EXPORT(GetMessageDelegateIndex, PartsEngine_GetMessageDelegateIndex), + HLL_EXPORT(ReleaseMessage, PE_ReleaseMessage), + HLL_EXPORT(PopMessage, PE_PopMessage), + HLL_EXPORT(GetMessagePartsNumber, PE_GetMessagePartsNumber), + HLL_EXPORT(GetMessageDelegateIndex, PE_GetMessageDelegateIndex), HLL_EXPORT(GetDelegateIndex, PE_GetDelegateIndex), - HLL_EXPORT(GetMessageType, PartsEngine_GetMessageType), - HLL_TODO_EXPORT(GetMessageVariableCount, PartsEngine_GetMessageVariableCount), - HLL_TODO_EXPORT(GetMessageVariableType, PartsEngine_GetMessageVariableType), - HLL_TODO_EXPORT(GetMessageVariableInt, PartsEngine_GetMessageVariableInt), - HLL_TODO_EXPORT(GetMessageVariableFloat, PartsEngine_GetMessageVariableFloat), - HLL_TODO_EXPORT(GetMessageVariableBool, PartsEngine_GetMessageVariableBool), - HLL_TODO_EXPORT(GetMessageVariableString, PartsEngine_GetMessageVariableString), + HLL_EXPORT(GetMessageType, PE_GetMessageType), + HLL_EXPORT(GetMessageVariableCount, PE_GetMessageVariableCount), + HLL_EXPORT(GetMessageVariableType, PE_GetMessageVariableType), + HLL_EXPORT(GetMessageVariableInt, PE_GetMessageVariableInt), + HLL_EXPORT(GetMessageVariableFloat, PE_GetMessageVariableFloat), + HLL_EXPORT(GetMessageVariableBool, PE_GetMessageVariableBool), + HLL_EXPORT(GetMessageVariableString, PE_GetMessageVariableString), HLL_EXPORT(SetDelegateIndex, PE_SetDelegateIndex), HLL_TODO_EXPORT(SetFocus, PartsEngine_SetFocus), HLL_TODO_EXPORT(IsFocus, PartsEngine_IsFocus), diff --git a/src/meson.build b/src/meson.build index 67bde35..26c1861 100644 --- a/src/meson.build +++ b/src/meson.build @@ -61,6 +61,7 @@ xsystem4 = [version_h, 'parts/flash.c', 'parts/flat.c', 'parts/input.c', + 'parts/message.c', 'parts/motion.c', 'parts/parts.c', 'parts/render.c', diff --git a/src/parts/message.c b/src/parts/message.c new file mode 100644 index 0000000..2bc22bd --- /dev/null +++ b/src/parts/message.c @@ -0,0 +1,146 @@ +/* Copyright (C) 2026 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 +#include +#include + +#include "system4.h" +#include "system4/string.h" + +#include "vm.h" +#include "parts.h" +#include "parts_internal.h" + +#define PARTS_MSG_MAX_VARS 4 + +struct parts_message { + STAILQ_ENTRY(parts_message) entry; + int parts_no; + int delegate_index; + int type; + int variables[PARTS_MSG_MAX_VARS]; + int nr_variables; +}; + +static STAILQ_HEAD(, parts_message) msg_queue = + STAILQ_HEAD_INITIALIZER(msg_queue); + +void parts_msg_push(int parts_no, int delegate_index, int type, const char *fmt, ...) +{ + // Message system is introduced in Rance 9 + if (!parts_multi_controller) + return; + + struct parts_message *msg = xmalloc(sizeof(*msg)); + msg->parts_no = parts_no; + msg->delegate_index = delegate_index; + msg->type = type; + msg->nr_variables = 0; + + va_list ap; + va_start(ap, fmt); + for (const char *p = fmt; *p; p++) { + if (msg->nr_variables >= PARTS_MSG_MAX_VARS) { + VM_ERROR("parts_msg_push: too many variables"); + } + switch (*p) { + case 'i': + msg->variables[msg->nr_variables++] = va_arg(ap, int); + break; + default: + VM_ERROR("parts_msg_push: unsupported format '%c'", *p); + } + } + va_end(ap); + + STAILQ_INSERT_TAIL(&msg_queue, msg, entry); +} + +void PE_ReleaseMessage(void) +{ + while (!STAILQ_EMPTY(&msg_queue)) { + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + STAILQ_REMOVE_HEAD(&msg_queue, entry); + free(msg); + } +} + +void PE_PopMessage(void) +{ + if (STAILQ_EMPTY(&msg_queue)) + return; + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + STAILQ_REMOVE_HEAD(&msg_queue, entry); + free(msg); +} + +int PE_GetMessageType(void) +{ + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + return msg ? msg->type : 0; +} + +int PE_GetMessagePartsNumber(void) +{ + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + return msg ? msg->parts_no : 0; +} + +int PE_GetMessageDelegateIndex(void) +{ + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + return msg ? msg->delegate_index : -1; +} + +int PE_GetMessageVariableCount(void) +{ + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + return msg ? msg->nr_variables : 0; +} + +int PE_GetMessageVariableType(possibly_unused int index) +{ + // In the current implementation, all variables are integers. + return 1; +} + +int PE_GetMessageVariableInt(int index) +{ + struct parts_message *msg = STAILQ_FIRST(&msg_queue); + if (!msg) + return 0; + if (index < 0 || index >= msg->nr_variables) + return 0; + return msg->variables[index]; +} + +float PE_GetMessageVariableFloat(possibly_unused int index) +{ + return 0.0f; +} + +bool PE_GetMessageVariableBool(possibly_unused int index) +{ + return false; +} + +void PE_GetMessageVariableString(possibly_unused int index, struct string **out) +{ + if (*out) + free_string(*out); + *out = string_ref(&EMPTY_STRING); +} diff --git a/src/parts/parts.c b/src/parts/parts.c index bce023a..4dc70f4 100644 --- a/src/parts/parts.c +++ b/src/parts/parts.c @@ -1020,6 +1020,7 @@ bool PE_Init(void) void PE_Reset(void) { PE_ReleaseAllParts(); + PE_ReleaseMessage(); ctrl_stack_fini(); sact_ModuleFini(); } diff --git a/src/parts/parts_internal.h b/src/parts/parts_internal.h index c94b488..1e74a34 100644 --- a/src/parts/parts_internal.h +++ b/src/parts/parts_internal.h @@ -465,6 +465,24 @@ void parts_add_motion(struct parts *parts, struct parts_motion *motion); extern Point parts_prev_pos; extern bool parts_began_click; +// message.c +enum parts_message_type { + PARTS_MSG_MOUSE_ENTER = 1, + PARTS_MSG_MOUSE_MOVE = 2, + PARTS_MSG_MOUSE_LEAVE = 3, + PARTS_MSG_MOUSE_WHEEL = 4, + PARTS_MSG_MOUSE_CLICK = 5, + PARTS_MSG_MOUSE_ON = 6, + PARTS_MSG_DRAG_BEGIN = 7, + PARTS_MSG_DRAGGING = 8, + PARTS_MSG_DRAG_END = 9, + PARTS_MSG_KEY_TRIGGER = 14, + PARTS_MSG_KEY_DOWN = 15, + PARTS_MSG_KEY_UP = 17, +}; + +void parts_msg_push(int parts_no, int delegate_index, int type, const char *fmt, ...); + // construction.c void parts_cp_op_free(struct parts_cp_op *op); void parts_add_cp_op(struct parts_construction_process *cproc, struct parts_cp_op *op);