Add proto data opcodes

This commit is contained in:
Alexander Batalov 2023-04-19 09:21:38 +03:00
parent 9b02f600de
commit ef34fdb519
3 changed files with 62 additions and 4 deletions

View File

@ -249,6 +249,12 @@ int _proto_list_str(int pid, char* proto_path)
return 0;
}
// 0x49E984
size_t proto_size(int type)
{
return type >= 0 && type < OBJ_TYPE_COUNT ? _proto_sizes[type] : 0;
}
// 0x49E99C
bool _proto_action_can_use(int pid)
{
@ -1704,12 +1710,10 @@ static int _proto_load_pid(int pid, Proto** protoPtr)
return 0;
}
// allocate memory for proto of given type and adds it to proto cache
// 0x4A1D98
static int _proto_find_free_subnode(int type, Proto** protoPtr)
{
size_t size = (type >= 0 && type < 11) ? _proto_sizes[type] : 0;
Proto* proto = (Proto*)internal_malloc(size);
Proto* proto = (Proto*)internal_malloc(proto_size(type));
*protoPtr = proto;
if (proto == NULL) {
return -1;

View File

@ -104,6 +104,7 @@ extern char* _proto_none_str;
void _proto_make_path(char* path, int pid);
int _proto_list_str(int pid, char* proto_path);
size_t proto_size(int type);
bool _proto_action_can_use(int pid);
bool _proto_action_can_use_on(int pid);
bool _proto_action_can_talk_to(int pid);

View File

@ -10,6 +10,7 @@
#include "message.h"
#include "mouse.h"
#include "object.h"
#include "proto.h"
#include "sfall_global_vars.h"
#include "sfall_lists.h"
#include "stat.h"
@ -143,6 +144,56 @@ static void op_set_car_current_town(Program* program)
wmCarSetCurrentArea(area);
}
// get_proto_data
static void op_get_proto_data(Program* program)
{
size_t offset = static_cast<size_t>(programStackPopInteger(program));
int pid = programStackPopInteger(program);
Proto* proto;
if (protoGetProto(pid, &proto) != 0) {
debugPrint("op_get_proto_data: bad proto %d", pid);
programStackPushInteger(program, -1);
return;
}
// CE: Make sure the requested offset is within memory bounds and is
// properly aligned.
if (offset + sizeof(int) > proto_size(PID_TYPE(pid)) || offset % sizeof(int) != 0) {
debugPrint("op_get_proto_data: bad offset %d", offset);
programStackPushInteger(program, -1);
return;
}
int value = *reinterpret_cast<int*>(reinterpret_cast<unsigned char*>(proto) + offset);
programStackPushInteger(program, value);
}
// set_proto_data
static void op_set_proto_data(Program* program)
{
int value = programStackPopInteger(program);
size_t offset = static_cast<size_t>(programStackPopInteger(program));
int pid = programStackPopInteger(program);
Proto* proto;
if (protoGetProto(pid, &proto) != 0) {
debugPrint("op_set_proto_data: bad proto %d", pid);
programStackPushInteger(program, -1);
return;
}
// CE: Make sure the requested offset is within memory bounds and is
// properly aligned.
if (offset + sizeof(int) > proto_size(PID_TYPE(pid)) || offset % sizeof(int) != 0) {
debugPrint("op_set_proto_data: bad offset %d", offset);
programStackPushInteger(program, -1);
return;
}
*reinterpret_cast<int*>(reinterpret_cast<unsigned char*>(proto) + offset) = value;
}
// list_begin
static void opListBegin(Program* program)
{
@ -362,6 +413,8 @@ void sfallOpcodesInit()
interpreterRegisterOpcode(0x819E, opGetGlobalInt);
interpreterRegisterOpcode(0x81AF, opGetGameMode);
interpreterRegisterOpcode(0x81B6, op_set_car_current_town);
interpreterRegisterOpcode(0x8204, op_get_proto_data);
interpreterRegisterOpcode(0x8205, op_set_proto_data);
interpreterRegisterOpcode(0x820D, opListBegin);
interpreterRegisterOpcode(0x820E, opListNext);
interpreterRegisterOpcode(0x820F, opListEnd);