Reconcile with reference edition (#100)

This commit is contained in:
Alexander Batalov 2022-07-29 16:04:05 +03:00 committed by GitHub
parent 39057fd1fb
commit e41a4b8e16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
98 changed files with 9028 additions and 2808 deletions

View File

@ -170,6 +170,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/palette.h"
"src/party_member.cc"
"src/party_member.h"
"src/pcx.cc"
"src/pcx.h"
"src/perk_defs.h"
"src/perk.cc"
"src/perk.h"

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ bool _can_see(Object* a1, Object* a2);
bool _action_explode_running();
int actionExplode(int tile, int elevation, int minDamage, int maxDamage, Object* a5, bool a6);
int actionTalk(Object* a1, Object* a2);
void _action_dmg(int tile, int elevation, int minDamage, int maxDamage, int damageType, bool animated, bool bypassArmor);
void actionDamage(int tile, int elevation, int minDamage, int maxDamage, int damageType, bool animated, bool bypassArmor);
bool actionCheckPush(Object* a1, Object* a2);
int actionPush(Object* a1, Object* a2);
int _action_can_talk_to(Object* a1, Object* a2);

File diff suppressed because it is too large Load Diff

View File

@ -3,36 +3,14 @@
#include "combat_defs.h"
#include "obj_types.h"
#include "sound.h"
typedef enum AnimKind {
ANIM_KIND_OBJ_MOVE_TO_OBJ = 0,
ANIM_KIND_OBJ_MOVE_TO_TILE = 1,
ANIM_KIND_2 = 2,
ANIM_KIND_KNOCKDOWN = 3,
ANIM_KIND_ANIMATE = 4,
ANIM_KIND_ANIMATE_REVERSE = 5,
ANIM_KIND_6 = 6,
ANIM_KIND_SET_ROTATION_TO_TILE = 7,
ANIM_KIND_ROTATE_CLOCKWISE = 8,
ANIM_KIND_ROTATE_COUNTER_CLOCKWISE = 9,
ANIM_KIND_HIDE = 10,
ANIM_KIND_EXEC = 11,
ANIM_KIND_EXEC_2 = 12,
ANIM_KIND_14 = 14,
ANIM_KIND_15 = 15,
ANIM_KIND_16 = 16,
ANIM_KIND_17 = 17,
ANIM_KIND_18 = 18,
ANIM_KIND_19 = 19,
ANIM_KIND_20 = 20,
ANIM_KIND_23 = 23,
ANIM_KIND_24 = 24,
ANIM_KIND_ANIMATE_FOREVER = 25,
ANIM_KIND_26 = 26,
ANIM_KIND_27 = 27,
ANIM_KIND_28 = 28,
} AnimKind;
typedef enum AnimationRequestOptions {
ANIMATION_REQUEST_UNRESERVED = 0x01,
ANIMATION_REQUEST_RESERVED = 0x02,
ANIMATION_REQUEST_NO_STAND = 0x04,
ANIMATION_REQUEST_0x100 = 0x100,
ANIMATION_REQUEST_INSIGNIFICANT = 0x200,
} AnimationRequestOptions;
// Basic animations: 0-19
// Knockdown and death: 20-35
@ -112,9 +90,13 @@ typedef enum AnimationType {
LAST_SF_DEATH_ANIM = ANIM_FALL_FRONT_BLOOD_SF,
} AnimationType;
typedef int AnimationProc(Object*, Object*);
typedef int AnimationSoundProc(Sound*);
typedef int AnimationProc2(Object*, Object*, void*);
#define FID_ANIM_TYPE(value) ((value) & 0xFF0000) >> 16
// Signature of animation callback accepting 2 parameters.
typedef int(AnimationCallback)(void* a1, void* a2);
// Signature of animation callback accepting 3 parameters.
typedef int(AnimationCallback3)(void* a1, void* a2, void* a3);
typedef struct STRUCT_530014_28 {
int tile;
@ -133,28 +115,31 @@ int _register_priority(int a1);
int reg_anim_clear(Object* a1);
int reg_anim_end();
int animationIsBusy(Object* a1);
int reg_anim_obj_move_to_obj(Object* a1, Object* a2, int actionPoints, int delay);
int reg_anim_obj_run_to_obj(Object* owner, Object* destination, int actionPoints, int delay);
int reg_anim_obj_move_to_tile(Object* obj, int tile_num, int elev, int actionPoints, int delay);
int reg_anim_obj_run_to_tile(Object* obj, int tile_num, int elev, int actionPoints, int delay);
int reg_anim_2(Object* obj, int tile_num, int elev, int a4, int a5);
int reg_anim_knockdown(Object* obj, int tile, int elev, int anim, int delay);
int reg_anim_animate(Object* obj, int anim, int delay);
int reg_anim_animate_reverse(Object* obj, int anim, int delay);
int reg_anim_6(Object* obj, int anim, int delay);
int reg_anim_set_rotation_to_tile(Object* owner, int tile);
int reg_anim_rotate_clockwise(Object* obj);
int reg_anim_rotate_counter_clockwise(Object* obj);
int reg_anim_hide(Object* obj);
int reg_anim_11_0(Object* a1, Object* a2, AnimationProc* proc, int delay);
int reg_anim_12(Object* a1, Object* a2, void* a3, AnimationProc2* proc, int delay);
int reg_anim_11_1(Object* a1, Object* a2, AnimationProc* proc, int delay);
int reg_anim_15(Object* obj, int a2, int a3);
int reg_anim_17(Object* obj, int fid, int a3);
int reg_anim_18(Object* obj, int a2, int a3);
int reg_anim_update_light(Object* obj, int fid, int a3);
int reg_anim_play_sfx(Object* obj, const char* a2, int a3);
int reg_anim_animate_forever(Object* obj, int a2, int a3);
int animationRegisterMoveToObject(Object* owner, Object* destination, int actionPoints, int delay);
int animationRegisterRunToObject(Object* owner, Object* destination, int actionPoints, int delay);
int animationRegisterMoveToTile(Object* owner, int tile, int elevation, int actionPoints, int delay);
int animationRegisterRunToTile(Object* owner, int tile, int elevation, int actionPoints, int delay);
int animationRegisterMoveToTileStraight(Object* object, int tile, int elevation, int anim, int delay);
int animationRegisterMoveToTileStraightAndWaitForComplete(Object* owner, int tile, int elev, int anim, int delay);
int animationRegisterAnimate(Object* owner, int anim, int delay);
int animationRegisterAnimateReversed(Object* owner, int anim, int delay);
int animationRegisterAnimateAndHide(Object* owner, int anim, int delay);
int animationRegisterRotateToTile(Object* owner, int tile);
int animationRegisterRotateClockwise(Object* owner);
int animationRegisterRotateCounterClockwise(Object* owner);
int animationRegisterHideObject(Object* object);
int animationRegisterHideObjectForced(Object* object);
int animationRegisterCallback(void* a1, void* a2, AnimationCallback* proc, int delay);
int animationRegisterCallback3(void* a1, void* a2, void* a3, AnimationCallback3* proc, int delay);
int animationRegisterCallbackForced(void* a1, void* a2, AnimationCallback* proc, int delay);
int animationRegisterSetFlag(Object* object, int flag, int delay);
int animationRegisterUnsetFlag(Object* object, int flag, int delay);
int animationRegisterSetFid(Object* owner, int fid, int delay);
int animationRegisterTakeOutWeapon(Object* owner, int weaponAnimationCode, int delay);
int animationRegisterSetLightDistance(Object* owner, int lightDistance, int delay);
int animationRegisterToggleOutline(Object* object, bool outline, int delay);
int animationRegisterPlaySoundEffect(Object* owner, const char* soundEffectName, int delay);
int animationRegisterAnimateForever(Object* owner, int anim, int delay);
int reg_anim_26(int a1, int a2);
int _make_path(Object* object, int from, int to, unsigned char* a4, int a5);
int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback);

View File

@ -3,6 +3,7 @@
#include "animation.h"
#include "debug.h"
#include "draw.h"
#include "game.h"
#include "game_config.h"
#include "memory.h"
#include "object.h"
@ -126,10 +127,8 @@ static int* gArtCritterFidShoudRunData;
int artInit()
{
char path[COMPAT_MAX_PATH];
int i;
File* stream;
char str[200];
char *ptr, *curr;
char string[200];
int cacheSize;
if (!configGetInt(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_ART_CACHE_SIZE_KEY, &cacheSize)) {
@ -147,20 +146,20 @@ int artInit()
gArtLanguageInitialized = true;
}
for (i = 0; i < 11; i++) {
gArtListDescriptions[i].flags = 0;
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[i].name, gArtListDescriptions[i].name);
for (int objectType = 0; objectType < OBJ_TYPE_COUNT; objectType++) {
gArtListDescriptions[objectType].flags = 0;
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[objectType].name, gArtListDescriptions[objectType].name);
if (artReadList(path, &(gArtListDescriptions[i].fileNames), &(gArtListDescriptions[i].fileNamesLength)) != 0) {
if (artReadList(path, &(gArtListDescriptions[objectType].fileNames), &(gArtListDescriptions[objectType].fileNamesLength)) != 0) {
debugPrint("art_read_lst failed in art_init\n");
cacheFree(&gArtCache);
return -1;
}
}
_anon_alias = (int*)internal_malloc(sizeof(*_anon_alias) * gArtListDescriptions[1].fileNamesLength);
_anon_alias = (int*)internal_malloc(sizeof(*_anon_alias) * gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength);
if (_anon_alias == NULL) {
gArtListDescriptions[1].fileNamesLength = 0;
gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength = 0;
debugPrint("Out of memory for anon_alias in art_init\n");
cacheFree(&gArtCache);
return -1;
@ -168,17 +167,17 @@ int artInit()
gArtCritterFidShoudRunData = (int*)internal_malloc(sizeof(*gArtCritterFidShoudRunData) * gArtListDescriptions[1].fileNamesLength);
if (gArtCritterFidShoudRunData == NULL) {
gArtListDescriptions[1].fileNamesLength = 0;
gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength = 0;
debugPrint("Out of memory for artCritterFidShouldRunData in art_init\n");
cacheFree(&gArtCache);
return -1;
}
for (i = 0; i < gArtListDescriptions[1].fileNamesLength; i++) {
gArtCritterFidShoudRunData[i] = 0;
for (int critterIndex = 0; critterIndex < gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength; critterIndex++) {
gArtCritterFidShoudRunData[critterIndex] = 0;
}
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[1].name, gArtListDescriptions[1].name);
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[OBJ_TYPE_CRITTER].name, gArtListDescriptions[OBJ_TYPE_CRITTER].name);
stream = fileOpen(path, "rt");
if (stream == NULL) {
@ -206,75 +205,70 @@ int artInit()
tribalMaleFileName = gDefaultTribalMaleFileName;
}
char *tribalFemaleFileName = NULL;
char* tribalFemaleFileName = NULL;
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_FEMALE_KEY, &tribalFemaleFileName);
if (tribalFemaleFileName == NULL || tribalFemaleFileName[0] == '\0') {
tribalFemaleFileName = gDefaultTribalFemaleFileName;
}
ptr = gArtListDescriptions[1].fileNames;
for (i = 0; i < gArtListDescriptions[1].fileNamesLength; i++) {
if (compat_stricmp(ptr, jumpsuitMaleFileName) == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_MALE] = i;
} else if (compat_stricmp(ptr, jumpsuitFemaleFileName) == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_FEMALE] = i;
char* critterFileNames = gArtListDescriptions[OBJ_TYPE_CRITTER].fileNames;
for (int critterIndex = 0; critterIndex < gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength; critterIndex++) {
if (compat_stricmp(critterFileNames, "hmjmps") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_MALE] = critterIndex;
} else if (compat_stricmp(critterFileNames, "hfjmps") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_FEMALE] = critterIndex;
}
if (compat_stricmp(ptr, tribalMaleFileName) == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_MALE] = i;
_art_vault_guy_num = i;
} else if (compat_stricmp(ptr, tribalFemaleFileName) == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_FEMALE] = i;
if (compat_stricmp(critterFileNames, "hmwarr") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_MALE] = critterIndex;
_art_vault_guy_num = critterIndex;
} else if (compat_stricmp(critterFileNames, "hfprim") == 0) {
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_FEMALE] = critterIndex;
}
ptr += 13;
critterFileNames += 13;
}
for (i = 0; i < gArtListDescriptions[1].fileNamesLength; i++) {
if (!fileReadString(str, sizeof(str), stream)) {
for (int critterIndex = 0; critterIndex < gArtListDescriptions[OBJ_TYPE_CRITTER].fileNamesLength; critterIndex++) {
if (!fileReadString(string, sizeof(string), stream)) {
break;
}
ptr = str;
curr = ptr;
while (*curr != '\0' && *curr != ',') {
curr++;
}
char* sep1 = strchr(string, ',');
if (sep1 != NULL) {
_anon_alias[critterIndex] = atoi(sep1 + 1);
if (*curr != '\0') {
_anon_alias[i] = atoi(curr + 1);
ptr = curr + 1;
curr = ptr;
while (*curr != '\0' && *curr != ',') {
curr++;
char* sep2 = strchr(sep1 + 1, ',');
if (sep2 != NULL) {
gArtCritterFidShoudRunData[critterIndex] = atoi(sep2 + 1);
} else {
gArtCritterFidShoudRunData[critterIndex] = 0;
}
gArtCritterFidShoudRunData[i] = *curr != '\0' ? atoi(ptr) : 0;
} else {
_anon_alias[i] = _art_vault_guy_num;
gArtCritterFidShoudRunData[i] = 1;
_anon_alias[critterIndex] = _art_vault_guy_num;
gArtCritterFidShoudRunData[critterIndex] = 1;
}
}
fileClose(stream);
ptr = gArtListDescriptions[4].fileNames;
for (i = 0; i < gArtListDescriptions[4].fileNamesLength; i++) {
if (compat_stricmp(ptr, "grid001.frm") == 0) {
_art_mapper_blank_tile = i;
char* tileFileNames = gArtListDescriptions[OBJ_TYPE_TILE].fileNames;
for (int tileIndex = 0; tileIndex < gArtListDescriptions[OBJ_TYPE_TILE].fileNamesLength; tileIndex++) {
if (compat_stricmp(tileFileNames, "grid001.frm") == 0) {
_art_mapper_blank_tile = tileIndex;
}
tileFileNames += 13;
}
gHeadDescriptions = (HeadDescription*)internal_malloc(sizeof(HeadDescription) * gArtListDescriptions[8].fileNamesLength);
gHeadDescriptions = (HeadDescription*)internal_malloc(sizeof(*gHeadDescriptions) * gArtListDescriptions[OBJ_TYPE_HEAD].fileNamesLength);
if (gHeadDescriptions == NULL) {
gArtListDescriptions[8].fileNamesLength = 0;
gArtListDescriptions[OBJ_TYPE_HEAD].fileNamesLength = 0;
debugPrint("Out of memory for head_info in art_init\n");
cacheFree(&gArtCache);
return -1;
}
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[8].name, gArtListDescriptions[8].name);
sprintf(path, "%s%s%s\\%s.lst", _cd_path_base, "art\\", gArtListDescriptions[OBJ_TYPE_HEAD].name, gArtListDescriptions[OBJ_TYPE_HEAD].name);
stream = fileOpen(path, "rt");
if (stream == NULL) {
@ -283,46 +277,42 @@ int artInit()
return -1;
}
for (i = 0; i < gArtListDescriptions[8].fileNamesLength; i++) {
if (!fileReadString(str, sizeof(str), stream)) {
for (int headIndex = 0; headIndex < gArtListDescriptions[OBJ_TYPE_HEAD].fileNamesLength; headIndex++) {
if (!fileReadString(string, sizeof(string), stream)) {
break;
}
ptr = str;
curr = ptr;
while (*curr != '\0' && *curr != ',') {
curr++;
char* sep1 = strchr(string, ',');
if (sep1 != NULL) {
*sep1 = '\0';
} else {
sep1 = string;
}
if (*curr != '\0') {
ptr = curr + 1;
curr = ptr;
while (*curr != '\0' && *curr != ',') {
curr++;
}
if (*curr != '\0') {
gHeadDescriptions[i].goodFidgetCount = atoi(ptr);
ptr = curr + 1;
curr = ptr;
while (*curr != '\0' && *curr != ',') {
curr++;
}
if (*curr != '\0') {
gHeadDescriptions[i].neutralFidgetCount = atoi(ptr);
ptr = curr + 1;
curr = strpbrk(ptr, " ,;\t\n");
if (curr != NULL) {
*curr = '\0';
}
gHeadDescriptions[i].badFidgetCount = atoi(ptr);
}
}
char* sep2 = strchr(sep1, ',');
if (sep2 != NULL) {
*sep2 = '\0';
} else {
sep2 = sep1;
}
gHeadDescriptions[headIndex].goodFidgetCount = atoi(sep1 + 1);
char* sep3 = strchr(sep2, ',');
if (sep3 != NULL) {
*sep3 = '\0';
} else {
sep3 = sep2;
}
gHeadDescriptions[headIndex].neutralFidgetCount = atoi(sep2 + 1);
char* sep4 = strpbrk(sep3 + 1, " ,;\t\n");
if (sep4 != NULL) {
*sep4 = '\0';
}
gHeadDescriptions[headIndex].badFidgetCount = atoi(sep3 + 1);
}
fileClose(stream);
@ -357,19 +347,19 @@ void artExit()
// 0x418F1C
char* artGetObjectTypeName(int objectType)
{
return objectType >= 0 && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].name : NULL;
return objectType >= OBJ_TYPE_ITEM && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].name : NULL;
}
// 0x418F34
int artIsObjectTypeHidden(int objectType)
{
return objectType >= 0 && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].flags & 1 : 0;
return objectType >= OBJ_TYPE_ITEM && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].flags & 1 : 0;
}
// 0x418F7C
int artGetFidgetCount(int headFid)
{
if ((headFid & 0xF000000) >> 24 != OBJ_TYPE_HEAD) {
if (FID_TYPE(headFid) != OBJ_TYPE_HEAD) {
return 0;
}
@ -522,15 +512,15 @@ int artCacheFlush()
}
// 0x4192B0
int artCopyFileName(int type, int id, char* dest)
int artCopyFileName(int objectType, int id, char* dest)
{
ArtListDescription* ptr;
if (type < 0 && type >= 11) {
if (objectType < OBJ_TYPE_ITEM && objectType >= OBJ_TYPE_COUNT) {
return -1;
}
ptr = &(gArtListDescriptions[type]);
ptr = &(gArtListDescriptions[objectType]);
if (id >= ptr->fileNamesLength) {
return -1;
@ -622,7 +612,7 @@ char* artBuildFilePath(int fid)
v10 = (fid & 0x70000000) >> 28;
v1 = _art_alias_fid(fid);
v1 = artAliasFid(fid);
if (v1 != -1) {
v2 = v1;
}
@ -630,15 +620,15 @@ char* artBuildFilePath(int fid)
*_art_name = '\0';
v3 = v2 & 0xFFF;
v4 = (v2 & 0xFF0000) >> 16;
v4 = FID_ANIM_TYPE(v2);
v5 = (v2 & 0xF000) >> 12;
type = (v2 & 0xF000000) >> 24;
type = FID_TYPE(v2);
if (v3 >= gArtListDescriptions[type].fileNamesLength) {
return NULL;
}
if (type < 0 || type >= 11) {
if (type < OBJ_TYPE_ITEM || type >= OBJ_TYPE_COUNT) {
return NULL;
}
@ -669,44 +659,40 @@ char* artBuildFilePath(int fid)
// art_read_lst
// 0x419664
static int artReadList(const char* path, char** out_arr, int* out_count)
static int artReadList(const char* path, char** artListPtr, int* artListSizePtr)
{
File* stream;
char str[200];
char* arr;
int count;
char* brk;
stream = fileOpen(path, "rt");
File* stream = fileOpen(path, "rt");
if (stream == NULL) {
return -1;
}
count = 0;
while (fileReadString(str, sizeof(str), stream)) {
int count = 0;
char string[200];
while (fileReadString(string, sizeof(string), stream)) {
count++;
}
fileSeek(stream, 0, SEEK_SET);
*out_count = count;
*artListSizePtr = count;
arr = (char*)internal_malloc(13 * count);
*out_arr = arr;
if (arr == NULL) {
goto err;
char* artList = (char*)internal_malloc(13 * count);
*artListPtr = artList;
if (artList == NULL) {
fileClose(stream);
return -1;
}
while (fileReadString(str, sizeof(str), stream)) {
brk = strpbrk(str, " ,;\r\t\n");
while (fileReadString(string, sizeof(string), stream)) {
char* brk = strpbrk(string, " ,;\r\t\n");
if (brk != NULL) {
*brk = '\0';
}
strncpy(arr, str, 12);
arr[12] = '\0';
strncpy(artList, string, 12);
artList[12] = '\0';
arr += 13;
artList += 13;
}
fileClose(stream);
@ -864,34 +850,24 @@ ArtFrame* artGetFrame(Art* art, int frame, int rotation)
// 0x4198C8
bool artExists(int fid)
{
int v3;
bool result;
bool result = false;
int oldDb = -1;
v3 = -1;
result = false;
if ((fid & 0xF000000) >> 24 == 1) {
v3 = _db_current(1);
// _db_current(_critter_db_handle);
_db_current(0);
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current(1);
_db_current(_critter_db_handle);
}
char* filePath = artBuildFilePath(fid);
if (filePath == NULL) {
goto out;
if (filePath != NULL) {
int fileSize;
if (dbGetFileSize(filePath, &fileSize) != -1) {
result = true;
}
}
int fileSize;
if (dbGetFileSize(filePath, &fileSize) == -1) {
goto out;
}
result = true;
out:
if (v3 != -1) {
_db_current(v3);
if (oldDb != -1) {
_db_current(oldDb);
}
return result;
@ -923,7 +899,7 @@ int _art_alias_num(int index)
// 0x4199AC
int artCritterFidShouldRun(int fid)
{
if ((fid & 0xF000000) >> 24 == 1) {
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
return gArtCritterFidShoudRunData[fid & 0xFFF];
}
@ -931,64 +907,61 @@ int artCritterFidShouldRun(int fid)
}
// 0x4199D4
int _art_alias_fid(int fid)
int artAliasFid(int fid)
{
int v2;
int v3;
int result;
int type = FID_TYPE(fid);
int anim = FID_ANIM_TYPE(fid);
if (type == OBJ_TYPE_CRITTER) {
if (anim == ANIM_ELECTRIFY
|| anim == ANIM_BURNED_TO_NOTHING
|| anim == ANIM_ELECTRIFIED_TO_NOTHING
|| anim == ANIM_ELECTRIFY_SF
|| anim == ANIM_BURNED_TO_NOTHING_SF
|| anim == ANIM_ELECTRIFIED_TO_NOTHING_SF
|| anim == ANIM_FIRE_DANCE
|| anim == ANIM_CALLED_SHOT_PIC) {
// NOTE: Original code is slightly different. It uses many mutually
// mirrored bitwise operators. Probably result of some macros for
// getting/setting individual bits on fid.
return (fid & 0x70000000) | ((anim << 16) & 0xFF0000) | 0x1000000 | (fid & 0xF000) | (_anon_alias[fid & 0xFFF] & 0xFFF);
}
}
v2 = (fid & 0xF000000) >> 24;
v3 = (fid & 0xFF0000) >> 16;
if (v2 != 1 || v3 != 27 && v3 != 29 && v3 != 30 && v3 != 55 && v3 != 57 && v3 != 58 && v3 != 33 && v3 != 64)
result = -1;
else
result = ((fid & 0x70000000) >> 28 << 28) & 0x70000000 | (v3 << 16) & 0xFF0000 | 0x1000000 | (((fid & 0xF000) >> 12) << 12) & 0xF000 | _anon_alias[fid & 0xFFF] & 0xFFF;
return result;
return -1;
}
// 0x419A78
static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
{
int v4;
char* str;
char* ptr;
int result;
char path[COMPAT_MAX_PATH];
bool loaded;
int fileSize;
int oldDb = -1;
int result = -1;
v4 = -1;
result = -1;
if ((fid & 0xF000000) >> 24 == 1) {
v4 = _db_current(1);
// _db_current(_critter_db_handle);
_db_current(0);
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current(1);
_db_current(_critter_db_handle);
}
str = artBuildFilePath(fid);
if (str != NULL) {
loaded = false;
char* artFilePath = artBuildFilePath(fid);
if (artFilePath != NULL) {
int fileSize;
bool loaded = false;
if (gArtLanguageInitialized) {
ptr = str;
while (*ptr != '\0' && *ptr != '\\') {
ptr++;
char* pch = strchr(artFilePath, '\\');
if (pch == NULL) {
pch = artFilePath;
}
if (*ptr == '\0') {
ptr = str;
}
char localizedPath[COMPAT_MAX_PATH];
sprintf(localizedPath, "art\\%s\\%s", gArtLanguage, pch);
sprintf(path, "art\\%s\\%s", gArtLanguage, ptr);
if (dbGetFileSize(path, &fileSize) == 0) {
if (dbGetFileSize(localizedPath, &fileSize) == 0) {
loaded = true;
}
}
if (!loaded) {
if (dbGetFileSize(str, &fileSize) == 0) {
if (dbGetFileSize(artFilePath, &fileSize) == 0) {
loaded = true;
}
}
@ -999,8 +972,8 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
}
}
if (v4 != -1) {
_db_current(v4);
if (oldDb != -1) {
_db_current(oldDb);
}
return result;
@ -1009,43 +982,33 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
// 0x419B78
static int artCacheReadDataImpl(int fid, int* sizePtr, unsigned char* data)
{
int v4;
char* str;
char* ptr;
int result;
char path[COMPAT_MAX_PATH];
bool loaded;
int oldDb = -1;
int result = -1;
v4 = -1;
result = -1;
if ((fid & 0xF000000) >> 24 == 1) {
v4 = _db_current(1);
// _db_current(_critter_db_handle);
_db_current(0);
if (FID_TYPE(fid) == OBJ_TYPE_CRITTER) {
oldDb = _db_current(1);
_db_current(_critter_db_handle);
}
str = artBuildFilePath(fid);
if (str != NULL) {
loaded = false;
char* artFileName = artBuildFilePath(fid);
if (artFileName != NULL) {
bool loaded = false;
if (gArtLanguageInitialized) {
ptr = str;
while (*ptr != '\0' && *ptr != '\\') {
ptr++;
char* pch = strchr(artFileName, '\\');
if (pch == NULL) {
pch = artFileName;
}
if (*ptr == '\0') {
ptr = str;
}
char localizedPath[COMPAT_MAX_PATH];
sprintf(localizedPath, "art\\%s\\%s", gArtLanguage, pch);
sprintf(path, "art\\%s\\%s", gArtLanguage, ptr);
if (artRead(str, data) == 0) {
if (artRead(localizedPath, data) == 0) {
loaded = true;
}
}
if (!loaded) {
if (artRead(str, data) == 0) {
if (artRead(artFileName, data) == 0) {
loaded = true;
}
}
@ -1057,8 +1020,8 @@ static int artCacheReadDataImpl(int fid, int* sizePtr, unsigned char* data)
}
}
if (v4 != -1) {
_db_current(v4);
if (oldDb != -1) {
_db_current(oldDb);
}
return result;
@ -1071,7 +1034,7 @@ static void artCacheFreeImpl(void* ptr)
}
// 0x419C88
int buildFid(int objectType, int a2, int anim, int a3, int rotation)
int buildFid(int objectType, int frmId, int animType, int a3, int rotation)
{
int v7, v8, v9, v10;
@ -1081,13 +1044,13 @@ int buildFid(int objectType, int a2, int anim, int a3, int rotation)
goto zero;
}
if (anim == 33 || anim < 20 || anim > 35) {
if (animType == ANIM_FIRE_DANCE || animType < ANIM_FALL_BACK || animType > ANIM_FALL_FRONT_BLOOD) {
goto zero;
}
v7 = ((a3 << 12) & 0xF000) | (anim << 16) & 0xFF0000 | 0x1000000;
v7 = ((a3 << 12) & 0xF000) | (animType << 16) & 0xFF0000 | 0x1000000;
v8 = (rotation << 28) & 0x70000000 | v7;
v9 = a2 & 0xFFF;
v9 = frmId & 0xFFF;
if (artExists(v9 | v8) != 0) {
goto out;
@ -1108,7 +1071,7 @@ zero:
out:
return (v10 << 28) & 0x70000000 | (objectType << 24) | (anim << 16) & 0xFF0000 | (a3 << 12) & 0xF000 | a2 & 0xFFF;
return (v10 << 28) & 0x70000000 | (objectType << 24) | (animType << 16) & 0xFF0000 | (a3 << 12) & 0xF000 | frmId & 0xFFF;
}
// 0x419D60
@ -1172,3 +1135,75 @@ int artRead(const char* path, unsigned char* data)
fileClose(stream);
return 0;
}
// NOTE: Unused.
//
// 0x41A070
int artWriteFrameData(unsigned char* data, File* stream, int count)
{
unsigned char* ptr = data;
for (int index = 0; index < count; index++) {
ArtFrame* frame = (ArtFrame*)ptr;
if (fileWriteInt16(stream, frame->width) == -1) return -1;
if (fileWriteInt16(stream, frame->height) == -1) return -1;
if (fileWriteInt32(stream, frame->size) == -1) return -1;
if (fileWriteInt16(stream, frame->x) == -1) return -1;
if (fileWriteInt16(stream, frame->y) == -1) return -1;
if (fileWrite(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1;
ptr += sizeof(ArtFrame) + frame->size;
}
return 0;
}
// NOTE: Unused.
//
// 0x41A138
int artWriteHeader(Art* art, File* stream)
{
if (fileWriteInt32(stream, art->field_0) == -1) return -1;
if (fileWriteInt16(stream, art->framesPerSecond) == -1) return -1;
if (fileWriteInt16(stream, art->actionFrame) == -1) return -1;
if (fileWriteInt16(stream, art->frameCount) == -1) return -1;
if (fileWriteInt16List(stream, art->xOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt16List(stream, art->yOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt32List(stream, art->dataOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt32(stream, art->field_3A) == -1) return -1;
return 0;
}
// NOTE: Unused.
//
// 0x41A1E8
int artWrite(const char* path, unsigned char* data)
{
if (data == NULL) {
return -1;
}
File* stream = fileOpen(path, "wb");
if (stream == NULL) {
return -1;
}
Art* art = (Art*)data;
if (artWriteHeader(art, stream) == -1) {
fileClose(stream);
return -1;
}
for (int index = 0; index < ROTATION_COUNT; index++) {
if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) {
if (artWriteFrameData(data + sizeof(Art) + art->dataOffsets[index], stream, art->frameCount) != 0) {
fileClose(stream);
return -1;
}
}
}
fileClose(stream);
return 0;
}

View File

@ -127,7 +127,7 @@ unsigned char* artLockFrameData(int fid, int frame, int direction, CacheEntry**
unsigned char* artLockFrameDataReturningSize(int fid, CacheEntry** out_cache_entry, int* widthPtr, int* heightPtr);
int artUnlock(CacheEntry* cache_entry);
int artCacheFlush();
int artCopyFileName(int a1, int a2, char* a3);
int artCopyFileName(int objectType, int a2, char* a3);
int _art_get_code(int a1, int a2, char* a3, char* a4);
char* artBuildFilePath(int a1);
int artGetFramesPerSecond(Art* art);
@ -144,8 +144,9 @@ bool artExists(int fid);
bool _art_fid_valid(int fid);
int _art_alias_num(int a1);
int artCritterFidShouldRun(int a1);
int _art_alias_fid(int a1);
int buildFid(int a1, int a2, int a3, int a4, int a5);
int artAliasFid(int fid);
int buildFid(int objectType, int frmId, int animType, int a4, int rotation);
int artRead(const char* path, unsigned char* data);
int artWrite(const char* path, unsigned char* data);
#endif

View File

@ -302,7 +302,7 @@ void automapShow(bool isInGame, bool isUsingScanner)
unsigned char* frmData[AUTOMAP_FRM_COUNT];
CacheEntry* frmHandle[AUTOMAP_FRM_COUNT];
for (int index = 0; index < AUTOMAP_FRM_COUNT; index++) {
int fid = buildFid(6, frmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, frmIds[index], 0, 0, 0);
frmData[index] = artLockFrameData(fid, 0, 0, &(frmHandle[index]));
if (frmData[index] == NULL) {
while (--index >= 0) {
@ -482,7 +482,7 @@ static void automapRenderInMapWindow(int window, int elevation, unsigned char* b
continue;
}
int objectType = (object->fid & 0xF000000) >> 24;
int objectType = FID_TYPE(object->fid);
unsigned char objectColor;
if ((flags & AUTOMAP_IN_GAME) != 0) {
@ -1048,7 +1048,7 @@ static void _decode_map_data(int elevation)
if (object->tile != -1 && (object->flags & OBJECT_SEEN) != 0) {
int contentType;
int objectType = (object->fid & 0xF000000) >> 24;
int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_SCENERY && object->pid != PROTO_ID_0x2000158) {
contentType = 2;
} else if (objectType == OBJ_TYPE_WALL) {

View File

@ -5,8 +5,8 @@
#include "sound.h"
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// The initial number of cache entries in new cache.

View File

@ -1275,7 +1275,7 @@ static int characterEditorWindowInit()
return -1;
}
fid = buildFid(6, (gCharacterEditorIsCreationMode ? 169 : 177), 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, (gCharacterEditorIsCreationMode ? 169 : 177), 0, 0, 0);
gCharacterEditorWindowBackgroundBuffer = artLockFrameDataReturningSize(fid, &gCharacterEditorWindowBackgroundHandle, &(gCharacterEditorFrmSize[0].width), &(gCharacterEditorFrmSize[0].height));
if (gCharacterEditorWindowBackgroundBuffer == NULL) {
messageListFree(&gCharacterEditorMessageList);
@ -1296,7 +1296,7 @@ static int characterEditorWindowInit()
soundContinueAll();
for (i = 0; i < EDITOR_GRAPHIC_COUNT; i++) {
fid = buildFid(6, gCharacterEditorFrmIds[i], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, gCharacterEditorFrmIds[i], 0, 0, 0);
gCharacterEditorFrmData[i] = artLockFrameDataReturningSize(fid, &(gCharacterEditorFrmHandle[i]), &(gCharacterEditorFrmSize[i].width), &(gCharacterEditorFrmSize[i].height));
if (gCharacterEditorFrmData[i] == NULL) {
break;
@ -4892,7 +4892,7 @@ static int characterEditorDrawCardWithOptions(int graphicId, const char* name, c
short beginnings[WORD_WRAP_MAX_COUNT];
short beginningsCount;
fid = buildFid(10, graphicId, 0, 0, 0);
fid = buildFid(OBJ_TYPE_SKILLDEX, graphicId, 0, 0, 0);
buf = artLockFrameDataReturningSize(fid, &graphicHandle, &(size.width), &(size.height));
if (buf == NULL) {
return -1;
@ -5744,7 +5744,7 @@ static int perkDialogShow()
CacheEntry* backgroundFrmHandle;
int backgroundWidth;
int backgroundHeight;
int fid = buildFid(6, 86, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 86, 0, 0, 0);
gPerkDialogBackgroundBuffer = artLockFrameDataReturningSize(fid, &backgroundFrmHandle, &backgroundWidth, &backgroundHeight);
if (gPerkDialogBackgroundBuffer == NULL) {
debugPrint("\n *** Error running perks dialog window ***\n");
@ -5956,7 +5956,7 @@ static int perkDialogHandleInput(int count, void (*refreshProc)())
soundPlayFile("ib1p1xx1");
rc = 1;
} else if (keyCode == 501) {
mouseGetPositionInWindow(gPerkDialogWindow , &gCharacterEditorMouseX, &gCharacterEditorMouseY);
mouseGetPositionInWindow(gPerkDialogWindow, &gCharacterEditorMouseX, &gCharacterEditorMouseY);
gPerkDialogCurrentLine = (gCharacterEditorMouseY - PERK_WINDOW_LIST_Y) / v16;
if (gPerkDialogCurrentLine >= 0) {
if (count - 1 < gPerkDialogCurrentLine)
@ -6526,7 +6526,7 @@ static int perkDialogOptionCompare(const void* a1, const void* a2)
// 0x43DB54
static int perkDialogDrawCard(int frmId, const char* name, const char* rank, char* description)
{
int fid = buildFid(10, frmId, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_SKILLDEX, frmId, 0, 0, 0);
CacheEntry* handle;
int width;
@ -6611,7 +6611,7 @@ static int perkDialogDrawCard(int frmId, const char* name, const char* rank, cha
strcpy(gPerkDialogCardTitle, name);
gPerkDialogCardFrmId = frmId;
gPerkDialogCardDrawn = true;
artUnlock(handle);
return 0;

View File

@ -299,7 +299,7 @@ static bool characterSelectorWindowInit()
}
CacheEntry* backgroundFrmHandle;
backgroundFid = buildFid(6, 174, 0, 0, 0);
backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 174, 0, 0, 0);
backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData == NULL) {
goto err;
@ -328,13 +328,13 @@ static bool characterSelectorWindowInit()
int fid;
// Setup "Previous" button.
fid = buildFid(6, 122, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 122, 0, 0, 0);
gCharacterSelectorWindowPreviousButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowPreviousButtonUpFrmHandle);
if (gCharacterSelectorWindowPreviousButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 123, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 123, 0, 0, 0);
gCharacterSelectorWindowPreviousButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowPreviousButtonDownFrmHandle);
if (gCharacterSelectorWindowPreviousButtonDownFrmData == NULL) {
goto err;
@ -360,13 +360,13 @@ static bool characterSelectorWindowInit()
buttonSetCallbacks(gCharacterSelectorWindowPreviousButton, _gsound_med_butt_press, _gsound_med_butt_release);
// Setup "Next" button.
fid = buildFid(6, 124, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 124, 0, 0, 0);
gCharacterSelectorWindowNextButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowNextButtonUpFrmHandle);
if (gCharacterSelectorWindowNextButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 125, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 125, 0, 0, 0);
gCharacterSelectorWindowNextButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowNextButtonDownFrmHandle);
if (gCharacterSelectorWindowNextButtonDownFrmData == NULL) {
goto err;
@ -392,13 +392,13 @@ static bool characterSelectorWindowInit()
buttonSetCallbacks(gCharacterSelectorWindowNextButton, _gsound_med_butt_press, _gsound_med_butt_release);
// Setup "Take" button.
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
gCharacterSelectorWindowTakeButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowTakeButtonUpFrmHandle);
if (gCharacterSelectorWindowTakeButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
gCharacterSelectorWindowTakeButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowTakeButtonDownFrmHandle);
if (gCharacterSelectorWindowTakeButtonDownFrmData == NULL) {
goto err;
@ -424,12 +424,12 @@ static bool characterSelectorWindowInit()
buttonSetCallbacks(gCharacterSelectorWindowTakeButton, _gsound_red_butt_press, _gsound_red_butt_release);
// Setup "Modify" button.
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
gCharacterSelectorWindowModifyButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowModifyButtonUpFrmHandle);
if (gCharacterSelectorWindowModifyButtonUpFrmData == NULL)
goto err;
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
gCharacterSelectorWindowModifyButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowModifyButtonDownFrmHandle);
if (gCharacterSelectorWindowModifyButtonDownFrmData == NULL) {
goto err;
@ -455,13 +455,13 @@ static bool characterSelectorWindowInit()
buttonSetCallbacks(gCharacterSelectorWindowModifyButton, _gsound_red_butt_press, _gsound_red_butt_release);
// Setup "Create" button.
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
gCharacterSelectorWindowCreateButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowCreateButtonUpFrmHandle);
if (gCharacterSelectorWindowCreateButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
gCharacterSelectorWindowCreateButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowCreateButtonDownFrmHandle);
if (gCharacterSelectorWindowCreateButtonDownFrmData == NULL) {
goto err;
@ -487,13 +487,13 @@ static bool characterSelectorWindowInit()
buttonSetCallbacks(gCharacterSelectorWindowCreateButton, _gsound_red_butt_press, _gsound_red_butt_release);
// Setup "Back" button.
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
gCharacterSelectorWindowBackButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowBackButtonUpFrmHandle);
if (gCharacterSelectorWindowBackButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
gCharacterSelectorWindowBackButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterSelectorWindowBackButtonDownFrmHandle);
if (gCharacterSelectorWindowBackButtonDownFrmData == NULL) {
goto err;
@ -688,7 +688,7 @@ static bool characterSelectorWindowRenderFace()
bool success = false;
CacheEntry* faceFrmHandle;
int faceFid = buildFid(6, gPremadeCharacterDescriptions[gCurrentPremadeCharacter].face, 0, 0, 0);
int faceFid = buildFid(OBJ_TYPE_INTERFACE, gPremadeCharacterDescriptions[gCurrentPremadeCharacter].face, 0, 0, 0);
Art* frm = artLock(faceFid, &faceFrmHandle);
if (frm != NULL) {
unsigned char* data = artGetFrameData(frm, 0, 0);

View File

@ -2,11 +2,19 @@
#include "core.h"
#include <string.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#define COLOR_PALETTE_STACK_CAPACITY 16
typedef struct ColorPaletteStackEntry {
unsigned char mappedColors[256];
unsigned char cmap[768];
unsigned char colorTable[32768];
} ColorPaletteStackEntry;
static int colorPaletteFileOpen(const char* filePath, int flags);
static int colorPaletteFileRead(int fd, void* buffer, size_t size);
static int colorPaletteFileClose(int fd);
@ -25,6 +33,12 @@ static char _aColor_cNoError[] = "color.c: No errors\n";
// 0x50F95C
static char _aColor_cColorTa[] = "color.c: color table not found\n";
// 0x50F984
static char _aColor_cColorpa[] = "color.c: colorpalettestack overflow";
// 0x50F9AC
static char aColor_cColor_0[] = "color.c: colorpalettestack underflow";
// 0x51DF10
static char* _errorStr = _aColor_cNoError;
@ -54,6 +68,9 @@ unsigned char _cmap[768] = {
0x3F, 0x3F, 0x3F
};
// 0x673050
static ColorPaletteStackEntry* gColorPaletteStack[COLOR_PALETTE_STACK_CAPACITY];
// 0x673090
unsigned char _systemCmap[256 * 3];
@ -78,6 +95,9 @@ unsigned char _colorMixMulTable[65536];
// 0x6A38D0
unsigned char _colorTable[32768];
// 0x6AB8D0
static int gColorPaletteStackSize;
// 0x6AB928
static ColorPaletteFileReadProc* gColorPaletteFileReadProc;
@ -572,6 +592,60 @@ void colorSetBrightness(double value)
_setSystemPalette(_systemCmap);
}
// NOTE: Unused.
//
// 0x4C8828
bool colorPushColorPalette()
{
if (gColorPaletteStackSize >= COLOR_PALETTE_STACK_CAPACITY) {
_errorStr = _aColor_cColorpa;
return false;
}
ColorPaletteStackEntry* entry = (ColorPaletteStackEntry*)malloc(sizeof(*entry));
gColorPaletteStack[gColorPaletteStackSize] = entry;
memcpy(entry->mappedColors, _mappedColor, sizeof(_mappedColor));
memcpy(entry->cmap, _cmap, sizeof(_cmap));
memcpy(entry->colorTable, _colorTable, sizeof(_colorTable));
gColorPaletteStackSize++;
return true;
}
// NOTE: Unused.
//
// 0x4C88E0
bool colorPopColorPalette()
{
if (gColorPaletteStackSize == 0) {
_errorStr = aColor_cColor_0;
return false;
}
gColorPaletteStackSize--;
ColorPaletteStackEntry* entry = gColorPaletteStack[gColorPaletteStackSize];
memcpy(_mappedColor, entry->mappedColors, sizeof(_mappedColor));
memcpy(_cmap, entry->cmap, sizeof(_cmap));
memcpy(_colorTable, entry->colorTable, sizeof(_colorTable));
free(entry);
gColorPaletteStack[gColorPaletteStackSize] = NULL;
_setIntensityTables();
for (int index = 0; index < 256; index++) {
_setMixTableColor(index);
}
_rebuildColorBlendTables();
return true;
}
// 0x4C89CC
bool _initColors()
{
@ -599,5 +673,9 @@ void _colorsClose()
_freeColorBlendTable(index);
}
// TODO: Incomplete.
for (int index = 0; index < gColorPaletteStackSize; index++) {
free(gColorPaletteStack[index]);
}
gColorPaletteStackSize = 0;
}

View File

@ -35,6 +35,8 @@ unsigned char* _getColorBlendTable(int ch);
void _freeColorBlendTable(int a1);
void colorPaletteSetMemoryProcs(MallocProc* mallocProc, ReallocProc* reallocProc, FreeProc* freeProc);
void colorSetBrightness(double value);
bool colorPushColorPalette();
bool colorPopColorPalette();
bool _initColors();
void _colorsClose();

View File

@ -96,7 +96,7 @@ int _combatNumTurns = 0;
unsigned int gCombatState = COMBAT_STATE_0x02;
// 0x510948
static STRUCT_510948* _aiInfoList = NULL;
static CombatAIInfo* _aiInfoList = NULL;
// 0x51094C
static STRUCT_664980* _gcsd = NULL;
@ -1989,7 +1989,7 @@ int _find_cid(int a1, int cid, Object** critterList, int critterListLength)
int combatLoad(File* stream)
{
int v14;
STRUCT_510948* ptr;
CombatAIInfo* ptr;
int a2;
Object* obj;
int v24;
@ -2001,7 +2001,7 @@ int combatLoad(File* stream)
if (!isInCombat()) {
obj = objectFindFirst();
while (obj != NULL) {
if (obj->pid >> 24 == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
if (obj->data.critter.combat.whoHitMeCid == -1) {
obj->data.critter.combat.whoHitMe = NULL;
}
@ -2071,7 +2071,7 @@ int combatLoad(File* stream)
internal_free(_aiInfoList);
}
_aiInfoList = (STRUCT_510948*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
_aiInfoList = (CombatAIInfo*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
if (_aiInfoList == NULL) {
return -1;
}
@ -2082,31 +2082,31 @@ int combatLoad(File* stream)
if (fileReadInt32(stream, &a2) == -1) return -1;
if (a2 == -1) {
ptr->field_0 = 0;
ptr->friendlyDead = NULL;
} else {
ptr->field_0 = objectFindById(a2);
if (ptr->field_0 == NULL) return -1;
ptr->friendlyDead = objectFindById(a2);
if (ptr->friendlyDead == NULL) return -1;
}
if (fileReadInt32(stream, &a2) == -1) return -1;
if (a2 == -1) {
ptr->field_4 = 0;
ptr->lastTarget = NULL;
} else {
ptr->field_4 = objectFindById(a2);
if (ptr->field_4 == NULL) return -1;
ptr->lastTarget = objectFindById(a2);
if (ptr->lastTarget == NULL) return -1;
}
if (fileReadInt32(stream, &a2) == -1) return -1;
if (a2 == -1) {
ptr->field_8 = 0;
ptr->lastItem = NULL;
} else {
ptr->field_8 = objectFindById(a2);
if (ptr->field_8 == NULL) return -1;
ptr->lastItem = objectFindById(a2);
if (ptr->lastItem == NULL) return -1;
}
if (fileReadInt32(stream, &(ptr->field_C)) == -1) return -1;
if (fileReadInt32(stream, &(ptr->lastMove)) == -1) return -1;
}
_combat_begin_extra(gDude);
@ -2138,12 +2138,12 @@ int combatSave(File* stream)
}
for (int index = 0; index < _list_total; index++) {
STRUCT_510948* ptr = &(_aiInfoList[index]);
CombatAIInfo* ptr = &(_aiInfoList[index]);
if (fileWriteInt32(stream, ptr->field_0 != NULL ? ptr->field_0->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->field_4 != NULL ? ptr->field_4->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->field_8 != NULL ? ptr->field_8->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->field_C) == -1) return -1;
if (fileWriteInt32(stream, ptr->friendlyDead != NULL ? ptr->friendlyDead->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastTarget != NULL ? ptr->lastTarget->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastItem != NULL ? ptr->lastItem->id : -1) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastMove) == -1) return -1;
}
return 0;
@ -2285,16 +2285,16 @@ void _combat_data_init(Object* obj)
// 0x421850
static int _combatCopyAIInfo(int a1, int a2)
{
STRUCT_510948* v3;
STRUCT_510948* v4;
CombatAIInfo* v3;
CombatAIInfo* v4;
v3 = &_aiInfoList[a1];
v4 = &_aiInfoList[a2];
v4->field_0 = v3->field_0;
v4->field_4 = v3->field_4;
v4->field_8 = v3->field_8;
v4->field_C = v3->field_C;
v4->friendlyDead = v3->friendlyDead;
v4->lastTarget = v3->lastTarget;
v4->lastItem = v3->lastItem;
v4->lastMove = v3->lastMove;
return 0;
}
@ -2314,7 +2314,7 @@ Object* _combatAIInfoGetFriendlyDead(Object* obj)
return NULL;
}
return _aiInfoList[obj->cid].field_0;
return _aiInfoList[obj->cid].friendlyDead;
}
// 0x4218AC
@ -2336,7 +2336,7 @@ int _combatAIInfoSetFriendlyDead(Object* a1, Object* a2)
return -1;
}
_aiInfoList[a1->cid].field_0 = a2;
_aiInfoList[a1->cid].friendlyDead = a2;
return 0;
}
@ -2356,7 +2356,7 @@ Object* _combatAIInfoGetLastTarget(Object* obj)
return NULL;
}
return _aiInfoList[obj->cid].field_4;
return _aiInfoList[obj->cid].lastTarget;
}
// 0x421918
@ -2382,7 +2382,7 @@ int _combatAIInfoSetLastTarget(Object* a1, Object* a2)
a2 = NULL;
}
_aiInfoList[a1->cid].field_4 = a2;
_aiInfoList[a1->cid].lastTarget = a2;
return 0;
}
@ -2405,7 +2405,7 @@ Object* _combatAIInfoGetLastItem(Object* obj)
return NULL;
}
return _aiInfoList[v1].field_8;
return _aiInfoList[v1].lastItem;
}
// 0x421998
@ -2426,7 +2426,7 @@ int _combatAIInfoSetLastItem(Object* obj, Object* a2)
return -1;
}
_aiInfoList[v2].field_8 = NULL;
_aiInfoList[v2].lastItem = NULL;
return 0;
}
@ -2446,24 +2446,24 @@ static void _combat_begin(Object* a1)
_list_total = objectListCreate(-1, _combat_elev, OBJ_TYPE_CRITTER, &_combat_list);
_list_noncom = _list_total;
_list_com = 0;
_aiInfoList = (STRUCT_510948*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
_aiInfoList = (CombatAIInfo*)internal_malloc(sizeof(*_aiInfoList) * _list_total);
if (_aiInfoList == NULL) {
return;
}
for (int index = 0; index < _list_total; index++) {
STRUCT_510948* ptr = &(_aiInfoList[index]);
ptr->field_0 = NULL;
ptr->field_4 = NULL;
ptr->field_8 = NULL;
ptr->field_C = 0;
CombatAIInfo* ptr = &(_aiInfoList[index]);
ptr->friendlyDead = NULL;
ptr->lastTarget = NULL;
ptr->lastItem = NULL;
ptr->lastMove = 0;
}
Object* v1 = NULL;
for (int index = 0; index < _list_total; index++) {
Object* critter = _combat_list[index];
CritterCombatData* combatData = &(critter->data.critter.combat);
combatData->maneuver &= 0x01;
combatData->maneuver &= CRITTER_MANEUVER_0x01;
combatData->damageLastTurn = 0;
combatData->whoHitMe = NULL;
combatData->ap = 0;
@ -2471,7 +2471,7 @@ static void _combat_begin(Object* a1)
// NOTE: Not sure about this code, field_C is already reset.
if (isInCombat() && critter != NULL && index != -1) {
_aiInfoList[index].field_C = 0;
_aiInfoList[index].lastMove = 0;
}
scriptSetObjects(critter->sid, NULL, NULL);
@ -2495,16 +2495,16 @@ static void _combat_begin(Object* a1)
_gmouse_enable_scrolling();
if (v1 != NULL && !_isLoadingGame()) {
int fid = buildFid((v1->fid & 0xF000000) >> 24,
int fid = buildFid(FID_TYPE(v1->fid),
100,
(v1->fid & 0xFF0000) >> 16,
FID_ANIM_TYPE(v1->fid),
(v1->fid & 0xF000) >> 12,
(v1->fid & 0x70000000) >> 28);
reg_anim_clear(v1);
reg_anim_begin(2);
reg_anim_animate(v1, 6, -1);
reg_anim_17(v1, fid, -1);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterAnimate(v1, ANIM_UP_STAIRS_RIGHT, -1);
animationRegisterSetFid(v1, fid, -1);
reg_anim_end();
while (animationIsBusy(v1)) {
@ -2536,7 +2536,7 @@ static void _combat_begin_extra(Object* a1)
// 0x421D50
void _combat_update_critter_outline_for_los(Object* critter, bool a2)
{
if (critter->pid >> 24 != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return;
}
@ -2636,7 +2636,7 @@ static void _combat_over()
for (int index = 0; index < _list_noncom + _list_com; index++) {
Object* critter = _combat_list[index];
critter->data.critter.combat.damageLastTurn = 0;
critter->data.critter.combat.maneuver = 0;
critter->data.critter.combat.maneuver = CRITTER_MANEUVER_NONE;
}
for (int index = 0; index < _list_total; index++) {
@ -2649,15 +2649,15 @@ static void _combat_over()
scriptSetFixedParam(critter->sid, 0);
if (critter->pid == 0x1000098 && !critterIsDead(critter) && !_isLoadingGame()) {
int fid = buildFid((critter->fid & 0xF000000) >> 24,
int fid = buildFid(FID_TYPE(critter->fid),
99,
(critter->fid & 0xFF0000) >> 16,
FID_ANIM_TYPE(critter->fid),
(critter->fid & 0xF000) >> 12,
(critter->fid & 0x70000000) >> 28);
reg_anim_clear(critter);
reg_anim_begin(2);
reg_anim_animate(critter, 6, -1);
reg_anim_17(critter, fid, -1);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterAnimate(critter, ANIM_UP_STAIRS_RIGHT, -1);
animationRegisterSetFid(critter, fid, -1);
reg_anim_end();
while (animationIsBusy(critter)) {
@ -2766,7 +2766,7 @@ static void _combat_add_noncoms()
for (int index = _list_com; index < _list_com + _list_noncom; index++) {
Object* obj = _combat_list[index];
if (_combatai_want_to_join(obj)) {
obj->data.critter.combat.maneuver = 0;
obj->data.critter.combat.maneuver = CRITTER_MANEUVER_NONE;
Object** objectPtr1 = &(_combat_list[index]);
Object** objectPtr2 = &(_combat_list[_list_com]);
@ -3056,7 +3056,7 @@ static void _combat_set_move_all()
if (isInCombat()) {
if (object->cid != -1) {
_aiInfoList[object->cid].field_C = 0;
_aiInfoList[object->cid].lastMove = 0;
}
}
}
@ -3330,7 +3330,7 @@ void attackInit(Attack* attack, Object* attacker, Object* defender, int hitMode,
int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
{
if (a1 != gDude && hitMode == HIT_MODE_PUNCH && randomBetween(1, 4) == 1) {
int fid = buildFid(1, a1->fid & 0xFFF, ANIM_KICK_LEG, (a1->fid & 0xF000) >> 12, (a1->fid & 0x70000000) >> 28);
int fid = buildFid(OBJ_TYPE_CRITTER, a1->fid & 0xFFF, ANIM_KICK_LEG, (a1->fid & 0xF000) >> 12, (a1->fid & 0x70000000) >> 28);
if (artExists(fid)) {
hitMode = HIT_MODE_KICK;
}
@ -3422,7 +3422,7 @@ static bool _check_ranged_miss(Attack* attack)
_make_straight_path_func(attack->attacker, curr, to, NULL, &critter, 32, _obj_shoot_blocking_at);
if (critter != NULL) {
if ((critter->flags & OBJECT_SHOOT_THRU) == 0) {
if ((critter->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER) {
if (FID_TYPE(critter->fid) != OBJ_TYPE_CRITTER) {
roll = ROLL_SUCCESS;
break;
}
@ -3479,7 +3479,7 @@ static int _shoot_along_path(Attack* attack, int a2, int a3, int anim)
_make_straight_path_func(attack->attacker, v7, a2, NULL, &critter, 32, _obj_shoot_blocking_at);
if (critter != NULL) {
if (((critter->fid & 0xF000000) >> 24) != OBJ_TYPE_CRITTER) {
if (FID_TYPE(critter->fid) != OBJ_TYPE_CRITTER) {
break;
}
@ -3809,7 +3809,7 @@ static int attackCompute(Attack* attack)
// compute_explosion_on_extras
// 0x423C10
void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4)
void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4)
{
Object* attacker;
@ -3852,9 +3852,9 @@ void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4)
}
} else {
v22++;
if (a3 && _item_w_grenade_dmg_radius(attack->weapon) < v22) {
if (isGrenade && _item_w_grenade_dmg_radius(attack->weapon) < v22) {
v5 = -1;
} else if (a3 || _item_w_rocket_dmg_radius(attack->weapon) >= v22) {
} else if (isGrenade || _item_w_rocket_dmg_radius(attack->weapon) >= v22) {
v5 = tileGetTileInDirection(v19, ROTATION_NE, 1);
} else {
v5 = -1;
@ -3869,13 +3869,13 @@ void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4)
break;
}
Object* v11 = _obj_blocking_at(attacker, v5, attack->attacker->elevation);
if (v11 != NULL
&& (v11->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER
&& (v11->data.critter.combat.results & DAM_DEAD) == 0
&& (v11->flags & OBJECT_SHOOT_THRU) == 0
&& !_combat_is_shot_blocked(v11, v11->tile, tile, NULL, NULL)) {
if (v11 == attack->attacker) {
Object* obstacle = _obj_blocking_at(attacker, v5, attack->attacker->elevation);
if (obstacle != NULL
&& FID_TYPE(obstacle->fid) == OBJ_TYPE_CRITTER
&& (obstacle->data.critter.combat.results & DAM_DEAD) == 0
&& (obstacle->flags & OBJECT_SHOOT_THRU) == 0
&& !_combat_is_shot_blocked(obstacle, obstacle->tile, tile, NULL, NULL)) {
if (obstacle == attack->attacker) {
attack->attackerFlags &= ~DAM_HIT;
attackComputeDamage(attack, 1, 2);
attack->attackerFlags |= DAM_HIT;
@ -3883,15 +3883,15 @@ void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4)
} else {
int index;
for (index = 0; index < attack->extrasLength; index++) {
if (attack->extras[index] == v11) {
if (attack->extras[index] == obstacle) {
break;
}
}
if (index == attack->extrasLength) {
attack->extrasHitLocation[index] = HIT_LOCATION_TORSO;
attack->extras[index] = v11;
attackInit(&_explosion_ctd, attack->attacker, v11, attack->hitMode, HIT_LOCATION_TORSO);
attack->extras[index] = obstacle;
attackInit(&_explosion_ctd, attack->attacker, obstacle, attack->hitMode, HIT_LOCATION_TORSO);
if (!a4) {
_explosion_ctd.attackerFlags |= DAM_HIT;
attackComputeDamage(&_explosion_ctd, 1, 2);
@ -3911,11 +3911,11 @@ void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4)
static int attackComputeCriticalHit(Attack* attack)
{
Object* defender = attack->defender;
if (defender != NULL && _critter_flag_check(defender->pid, 1024)) {
if (defender != NULL && _critter_flag_check(defender->pid, CRITTER_FLAG_0x400)) {
return 2;
}
if (defender != NULL && (defender->pid >> 24) != OBJ_TYPE_CRITTER) {
if (defender != NULL && PID_TYPE(defender->pid) != OBJ_TYPE_CRITTER) {
return 2;
}
@ -3999,7 +3999,7 @@ static int _attackFindInvalidFlags(Object* critter, Object* item)
{
int flags = 0;
if (critter != NULL && (critter->pid >> 24) == OBJ_TYPE_CRITTER && _critter_flag_check(critter->pid, 64)) {
if (critter != NULL && PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER && _critter_flag_check(critter->pid, CRITTER_FLAG_0x40)) {
flags |= DAM_DROP;
}
@ -4015,7 +4015,7 @@ static int attackComputeCriticalFailure(Attack* attack)
{
attack->attackerFlags |= DAM_HIT;
if (attack->attacker != NULL && _critter_flag_check(attack->attacker->pid, 1024)) {
if (attack->attacker != NULL && _critter_flag_check(attack->attacker->pid, CRITTER_FLAG_0x400)) {
return 0;
}
@ -4141,7 +4141,7 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
Object* weapon = critterGetWeaponForHitMode(attacker, hitMode);
bool targetIsCritter = defender != NULL
? ((defender->fid & 0xF000000) >> 24) == OBJ_TYPE_CRITTER
? FID_TYPE(defender->fid) == OBJ_TYPE_CRITTER
: false;
bool isRangedWeapon = false;
@ -4323,7 +4323,7 @@ static int attackDetermineToHit(Object* attacker, int tile, Object* defender, in
}
// 0x4247B8
static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3)
static void attackComputeDamage(Attack* attack, int ammoQuantity, int bonusDamageMultiplier)
{
int* damagePtr;
Object* critter;
@ -4344,7 +4344,7 @@ static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3)
*damagePtr = 0;
if ((critter->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER) {
if (FID_TYPE(critter->fid) != OBJ_TYPE_CRITTER) {
return;
}
@ -4398,7 +4398,7 @@ static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3)
damageResistance = 0;
}
int damageMultiplier = a3 * weaponGetAmmoDamageMultiplier(attack->weapon);
int damageMultiplier = bonusDamageMultiplier * weaponGetAmmoDamageMultiplier(attack->weapon);
int damageDivisor = weaponGetAmmoDamageDivisor(attack->weapon);
for (int index = 0; index < ammoQuantity; index++) {
@ -4447,8 +4447,8 @@ static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3)
if (knockbackDistancePtr != NULL
&& (critter->flags & OBJECT_MULTIHEX) == 0
&& (damageType == DAMAGE_TYPE_EXPLOSION || attack->weapon == NULL || weaponGetAttackTypeForHitMode(attack->weapon, attack->hitMode) == ATTACK_TYPE_MELEE)
&& (critter->pid >> 24) == OBJ_TYPE_CRITTER
&& _critter_flag_check(critter->pid, 0x4000) == 0) {
&& PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER
&& _critter_flag_check(critter->pid, CRITTER_FLAG_0x4000) == 0) {
bool shouldKnockback = true;
bool hasStonewall = false;
if (critter == gDude) {
@ -4488,7 +4488,7 @@ void attackComputeDeathFlags(Attack* attack)
void _apply_damage(Attack* attack, bool animated)
{
Object* attacker = attack->attacker;
bool attackerIsCritter = attacker != NULL && (attacker->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER;
bool attackerIsCritter = attacker != NULL && FID_TYPE(attacker->fid) == OBJ_TYPE_CRITTER;
bool v5 = attack->defender != attack->oops;
if (attackerIsCritter && (attacker->data.critter.combat.results & DAM_DEAD) != 0) {
@ -4503,7 +4503,7 @@ void _apply_damage(Attack* attack, bool animated)
}
Object* defender = attack->defender;
bool defenderIsCritter = defender != NULL && (defender->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER;
bool defenderIsCritter = defender != NULL && FID_TYPE(defender->fid) == OBJ_TYPE_CRITTER;
if (!defenderIsCritter && !v5) {
bool v9 = objectIsPartyMember(attack->defender) && objectIsPartyMember(attack->attacker) ? false : true;
@ -4549,7 +4549,7 @@ void _apply_damage(Attack* attack, bool animated)
for (int index = 0; index < attack->extrasLength; index++) {
Object* obj = attack->extras[index];
if ((obj->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER && (obj->data.critter.combat.results & DAM_DEAD) == 0) {
if (FID_TYPE(obj->fid) == OBJ_TYPE_CRITTER && (obj->data.critter.combat.results & DAM_DEAD) == 0) {
_set_new_results(obj, attack->extrasFlags[index]);
if (defenderIsCritter) {
@ -4579,8 +4579,8 @@ void _apply_damage(Attack* attack, bool animated)
// 0x424EE8
static void _check_for_death(Object* object, int damage, int* flags)
{
if (object == NULL || !_critter_flag_check(object->pid, 0x0400)) {
if (object == NULL || (object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (object == NULL || !_critter_flag_check(object->pid, CRITTER_FLAG_0x400)) {
if (object == NULL || PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
if (damage > 0) {
if (critterGetHitPoints(object) - damage <= 0) {
*flags |= DAM_DEAD;
@ -4597,15 +4597,15 @@ static void _set_new_results(Object* critter, int flags)
return;
}
if (((critter->fid & 0xF000000) >> 24) != OBJ_TYPE_CRITTER) {
if (FID_TYPE(critter->fid) != OBJ_TYPE_CRITTER) {
return;
}
if (_critter_flag_check(critter->pid, 0x0400)) {
if (_critter_flag_check(critter->pid, CRITTER_FLAG_0x400)) {
return;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return;
}
@ -4635,11 +4635,11 @@ static void _damage_object(Object* a1, int damage, bool animated, int a4, Object
return;
}
if ((a1->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER) {
if (FID_TYPE(a1->fid) != OBJ_TYPE_CRITTER) {
return;
}
if (_critter_flag_check(a1->pid, 1024)) {
if (_critter_flag_check(a1->pid, CRITTER_FLAG_0x400)) {
return;
}
@ -4764,7 +4764,7 @@ void _combat_display(Attack* attack)
&& attack->oops != NULL
&& attack->defender != attack->oops
&& (attack->attackerFlags & DAM_HIT) != 0) {
if ((attack->defender->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER) {
if (FID_TYPE(attack->defender->fid) == OBJ_TYPE_CRITTER) {
if (attack->oops == gDude) {
// 608 (male) - Oops! %s was hit instead of you!
// 708 (female) - Oops! %s was hit instead of you!
@ -4820,7 +4820,7 @@ void _combat_display(Attack* attack)
if (v21 != NULL && (v21->data.critter.combat.results & DAM_DEAD) == 0) {
text[0] = '\0';
if ((v21->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER) {
if (FID_TYPE(v21->fid) == OBJ_TYPE_CRITTER) {
if (attack->defenderHitLocation == HIT_LOCATION_TORSO) {
if ((attack->attackerFlags & DAM_CRITICAL) != 0) {
switch (attack->defenderDamage) {
@ -5233,7 +5233,7 @@ static void _combat_standup(Object* a1)
static void _print_tohit(unsigned char* dest, int destPitch, int accuracy)
{
CacheEntry* numbersFrmHandle;
int numbersFrmFid = buildFid(6, 82, 0, 0, 0);
int numbersFrmFid = buildFid(OBJ_TYPE_INTERFACE, 82, 0, 0, 0);
unsigned char* numbersFrmData = artLockFrameData(numbersFrmFid, 0, 0, &numbersFrmHandle);
if (numbersFrmData == NULL) {
return;
@ -5325,7 +5325,7 @@ static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hi
unsigned char* windowBuffer = windowGetBuffer(gCalledShotWindow);
fid = buildFid(6, 118, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 118, 0, 0, 0);
data = artLockFrameData(fid, 0, 0, &handle);
if (data == NULL) {
windowDestroy(gCalledShotWindow);
@ -5335,14 +5335,14 @@ static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hi
blitBufferToBuffer(data, CALLED_SHOT_WINDOW_WIDTH, CALLED_SHOT_WINDOW_HEIGHT, CALLED_SHOT_WINDOW_WIDTH, windowBuffer, CALLED_SHOT_WINDOW_WIDTH);
artUnlock(handle);
fid = buildFid(1, critter->fid & 0xFFF, ANIM_CALLED_SHOT_PIC, 0, 0);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, ANIM_CALLED_SHOT_PIC, 0, 0);
data = artLockFrameData(fid, 0, 0, &handle);
if (data != NULL) {
blitBufferToBuffer(data, 170, 225, 170, windowBuffer + CALLED_SHOT_WINDOW_WIDTH * 31 + 168, CALLED_SHOT_WINDOW_WIDTH);
artUnlock(handle);
}
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
CacheEntry* upHandle;
unsigned char* up = artLockFrameData(fid, 0, 0, &upHandle);
@ -5351,7 +5351,7 @@ static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hi
return -1;
}
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
CacheEntry* downHandle;
unsigned char* down = artLockFrameData(fid, 0, 0, &downHandle);
@ -5710,7 +5710,7 @@ bool _combat_is_shot_blocked(Object* a1, int from, int to, Object* a4, int* a5)
while (obstacle != NULL && current != to) {
_make_straight_path_func(a1, current, to, 0, &obstacle, 32, _obj_shoot_blocking_at);
if (obstacle != NULL) {
if ((obstacle->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER && obstacle != a4) {
if (FID_TYPE(obstacle->fid) != OBJ_TYPE_CRITTER && obstacle != a4) {
return true;
}

View File

@ -1,8 +1,8 @@
#ifndef COMBAT_H
#define COMBAT_H
#include "db.h"
#include "combat_defs.h"
#include "db.h"
#include "obj_types.h"
#include "proto_types.h"
@ -35,7 +35,7 @@ void _combat(STRUCT_664980* attack);
void attackInit(Attack* attack, Object* a2, Object* a3, int a4, int a5);
int _combat_attack(Object* a1, Object* a2, int a3, int a4);
int _combat_bullet_start(const Object* a1, const Object* a2);
void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4);
void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4);
int _determine_to_hit(Object* a1, Object* a2, int hitLocation, int hitMode);
int _determine_to_hit_no_range(Object* a1, Object* a2, int a3, int a4, unsigned char* a5);
int _determine_to_hit_from_tile(Object* a1, int a2, Object* a3, int a4, int a5);

View File

@ -568,7 +568,7 @@ int aiLoad(File* stream)
{
for (int index = 0; index < gPartyMemberDescriptionsLength; index++) {
int pid = gPartyMemberPids[index];
if (pid != -1 && (pid >> 24) == OBJ_TYPE_CRITTER) {
if (pid != -1 && PID_TYPE(pid) == OBJ_TYPE_CRITTER) {
Proto* proto;
if (protoGetProto(pid, &proto) == -1) {
return -1;
@ -589,7 +589,7 @@ int aiSave(File* stream)
{
for (int index = 0; index < gPartyMemberDescriptionsLength; index++) {
int pid = gPartyMemberPids[index];
if (pid != -1 && (pid >> 24) == OBJ_TYPE_CRITTER) {
if (pid != -1 && PID_TYPE(pid) == OBJ_TYPE_CRITTER) {
Proto* proto;
if (protoGetProto(pid, &proto) == -1) {
return -1;
@ -897,9 +897,9 @@ int aiSetDisposition(Object* obj, int disposition)
// 0x428398
static int _ai_magic_hands(Object* critter, Object* item, int num)
{
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
reg_anim_animate(critter, ANIM_MAGIC_HANDS_MIDDLE, 0);
animationRegisterAnimate(critter, ANIM_MAGIC_HANDS_MIDDLE, 0);
if (reg_anim_end() == 0) {
if (isInCombat()) {
@ -1128,9 +1128,9 @@ static void _ai_run_away(Object* a1, Object* a2)
}
if (actionPoints > 0) {
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
_combatai_msg(a1, NULL, AI_MESSAGE_TYPE_RUN, 0);
reg_anim_obj_run_to_tile(a1, destination, a1->elevation, combatData->ap, 0);
animationRegisterRunToTile(a1, destination, a1->elevation, combatData->ap, 0);
if (reg_anim_end() == 0) {
_combat_turn_run();
}
@ -1175,8 +1175,8 @@ static int _ai_move_away(Object* a1, Object* a2, int a3)
}
if (actionPoints > 0) {
reg_anim_begin(2);
reg_anim_obj_move_to_tile(a1, destination, a1->elevation, actionPoints, 0);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterMoveToTile(a1, destination, a1->elevation, actionPoints, 0);
if (reg_anim_end() == 0) {
_combat_turn_run();
}
@ -1560,8 +1560,8 @@ int _caiSetupTeamCombat(Object* a1, Object* a2)
obj = objectFindFirstAtElevation(a1->elevation);
while (obj != NULL) {
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER && obj != gDude) {
obj->data.critter.combat.maneuver |= 0x01;
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER && obj != gDude) {
obj->data.critter.combat.maneuver |= CRITTER_MANEUVER_0x01;
}
obj = objectFindNextAtElevation();
}
@ -1719,7 +1719,7 @@ static Object* _ai_best_weapon(Object* attacker, Object* weapon1, Object* weapon
avgDamage1 = (maxDamage - minDamage) / 2;
if (_item_w_area_damage_radius(weapon1, HIT_MODE_RIGHT_WEAPON_PRIMARY) > 0 && defender != NULL) {
attack.weapon = weapon1;
_compute_explosion_on_extras(&attack, 0, _item_w_is_grenade(weapon1), 1);
_compute_explosion_on_extras(&attack, 0, weaponIsGrenade(weapon1), 1);
avgDamage1 *= attack.extrasLength + 1;
}
@ -1763,7 +1763,7 @@ static Object* _ai_best_weapon(Object* attacker, Object* weapon1, Object* weapon
avgDamage2 = (maxDamage - minDamage) / 2;
if (_item_w_area_damage_radius(weapon2, HIT_MODE_RIGHT_WEAPON_PRIMARY) > 0 && defender != NULL) {
attack.weapon = weapon2;
_compute_explosion_on_extras(&attack, 0, _item_w_is_grenade(weapon2), 1);
_compute_explosion_on_extras(&attack, 0, weaponIsGrenade(weapon2), 1);
avgDamage2 *= attack.extrasLength + 1;
}
@ -1842,7 +1842,7 @@ static bool _ai_can_use_weapon(Object* critter, Object* weapon, int hitMode)
int rotation = critter->rotation + 1;
int animationCode = weaponGetAnimationCode(weapon);
int v9 = weaponGetAnimationForHitMode(weapon, hitMode);
int fid = buildFid(1, critter->fid & 0xFFF, v9, animationCode, rotation);
int fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, v9, animationCode, rotation);
if (!artExists(fid)) {
return false;
}
@ -2194,7 +2194,7 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a
return -1;
}
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
if (a4) {
_combatai_msg(a1, NULL, AI_MESSAGE_TYPE_MOVE, 0);
@ -2214,7 +2214,7 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a
_moveBlockObj = NULL;
if (pathfinderFindPath(a1, a1->tile, a2->tile, NULL, 0, _obj_ai_blocking_at) == 0
&& _moveBlockObj != NULL
&& (_moveBlockObj->pid >> 24) == OBJ_TYPE_CRITTER) {
&& PID_TYPE(_moveBlockObj->pid) == OBJ_TYPE_CRITTER) {
if (shouldUnhide) {
a2->flags &= ~OBJECT_HIDDEN;
}
@ -2240,15 +2240,15 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a
if (actionPoints >= critterGetStat(a1, STAT_MAXIMUM_ACTION_POINTS) / 2 && artCritterFidShouldRun(a1->fid)) {
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
reg_anim_obj_run_to_obj(a1, a2, actionPoints, 0);
animationRegisterRunToObject(a1, a2, actionPoints, 0);
} else {
reg_anim_obj_run_to_tile(a1, tile, a1->elevation, actionPoints, 0);
animationRegisterRunToTile(a1, tile, a1->elevation, actionPoints, 0);
}
} else {
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
reg_anim_obj_move_to_obj(a1, a2, actionPoints, 0);
animationRegisterMoveToObject(a1, a2, actionPoints, 0);
} else {
reg_anim_obj_move_to_tile(a1, tile, a1->elevation, actionPoints, 0);
animationRegisterMoveToTile(a1, tile, a1->elevation, actionPoints, 0);
}
}
@ -2490,8 +2490,8 @@ static int _ai_attack(Object* a1, Object* a2, int a3)
return -1;
}
reg_anim_begin(2);
reg_anim_set_rotation_to_tile(a1, a2->tile);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterRotateToTile(a1, a2->tile);
reg_anim_end();
_combat_turn_run();
@ -2527,7 +2527,7 @@ static int _ai_try_attack(Object* a1, Object* a2)
if (weapon == NULL) {
if (critterGetBodyType(a2) != BODY_TYPE_BIPED
|| ((a2->fid & 0xF000) >> 12 != 0)
|| !artExists(buildFid(1, a1->fid & 0xFFF, ANIM_THROW_PUNCH, 0, a1->rotation + 1))
|| !artExists(buildFid(OBJ_TYPE_CRITTER, a1->fid & 0xFFF, ANIM_THROW_PUNCH, 0, a1->rotation + 1))
|| _combat_safety_invalidate_weapon(a1, weapon, HIT_MODE_RIGHT_WEAPON_PRIMARY, a2, &v31)) {
_ai_switch_weapons(a1, &hitMode, &weapon, a2);
}
@ -2813,8 +2813,8 @@ int _cai_perform_distance_prefs(Object* a1, Object* a2)
int tile = a1->tile;
if (_cai_retargetTileFromFriendlyFire(a1, a2, &tile) == 0 && tile != a1->tile) {
reg_anim_begin(2);
reg_anim_obj_move_to_tile(a1, tile, a1->elevation, a1->data.critter.combat.ap, 0);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterMoveToTile(a1, tile, a1->elevation, a1->data.critter.combat.ap, 0);
if (reg_anim_end() != 0) {
return -1;
}
@ -3017,7 +3017,7 @@ bool _combatai_want_to_stop(Object* a1)
// 0x42B504
int critterSetTeam(Object* obj, int team)
{
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
@ -3065,7 +3065,7 @@ int critterSetTeam(Object* obj, int team)
// 0x42B5D4
int critterSetAiPacket(Object* object, int aiPacket)
{
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return -1;
}
@ -3087,7 +3087,7 @@ int critterSetAiPacket(Object* object, int aiPacket)
// 0x42B634
int _combatai_msg(Object* a1, Attack* attack, int type, int delay)
{
if ((a1->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(a1->pid) != OBJ_TYPE_CRITTER) {
return -1;
}
@ -3162,7 +3162,7 @@ int _combatai_msg(Object* a1, Attack* attack, int type, int delay)
strncpy(string, messageListItem.text, 259);
// TODO: Get rid of casts.
return reg_anim_11_0(a1, (Object*)type, (AnimationProc*)_ai_print_msg, delay);
return animationRegisterCallback(a1, (void*)type, (AnimationCallback*)_ai_print_msg, delay);
}
// 0x42B80C
@ -3245,7 +3245,7 @@ static int _combatai_rating(Object* obj)
return 0;
}
if ((obj->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER) {
if (FID_TYPE(obj->fid) != OBJ_TYPE_CRITTER) {
return 0;
}

View File

@ -84,12 +84,12 @@ typedef enum HitLocation {
HIT_LOCATION_SPECIFIC_COUNT = HIT_LOCATION_COUNT - 1,
} HitLocation;
typedef struct STRUCT_510948 {
Object* field_0;
Object* field_4;
Object* field_8;
int field_C;
} STRUCT_510948;
typedef struct CombatAIInfo {
Object* friendlyDead;
Object* lastTarget;
Object* lastItem;
int lastMove;
} CombatAIInfo;
typedef struct STRUCT_664980 {
Object* attacker;

View File

@ -81,25 +81,20 @@ bool configParseCommandLineArguments(Config* config, int argc, char** argv)
}
for (int arg = 0; arg < argc; arg++) {
char* pch = argv[arg];
char* pch;
char* string = argv[arg];
// Find opening bracket.
while (*pch != '\0' && *pch != '[') {
pch++;
}
if (*pch == '\0') {
pch = strchr(string, '[');
if (pch == NULL) {
continue;
}
char* sectionKey = pch + 1;
// Find closing bracket.
while (*pch != '\0' && *pch != ']') {
pch++;
}
if (*pch == '\0') {
pch = strchr(sectionKey, ']');
if (pch == NULL) {
continue;
}
@ -189,7 +184,7 @@ bool configSetString(Config* config, const char* sectionKey, const char* key, co
}
// 0x42C05C
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr, unsigned char base /* = 0 */ )
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr, unsigned char base /* = 0 */)
{
if (valuePtr == NULL) {
return false;
@ -233,36 +228,30 @@ bool configGetIntList(Config* config, const char* sectionKey, const char* key, i
}
char temp[CONFIG_FILE_MAX_LINE_LENGTH];
strncpy(temp, string, CONFIG_FILE_MAX_LINE_LENGTH - 1);
string = strncpy(temp, string, CONFIG_FILE_MAX_LINE_LENGTH - 1);
char* beginning = temp;
char* pch = beginning;
while (*pch != '\0') {
if (*pch == ',') {
*pch = '\0';
*arr++ = atoi(beginning);
*pch = ',';
pch++;
beginning = pch;
count--;
if (count < 0) {
break;
}
while (1) {
char* pch = strchr(string, ',');
if (pch == NULL) {
break;
}
pch++;
count--;
if (count == 0) {
break;
}
*pch = '\0';
*arr++ = atoi(string);
string = pch + 1;
}
if (count <= 1) {
*arr = atoi(beginning);
*arr = atoi(string);
return true;
}
return true;
return false;
}
// 0x42C160
@ -383,30 +372,19 @@ static bool configParseLine(Config* config, char* string)
char* pch;
// Find comment marker and truncate the string.
pch = string;
while (*pch != '\0' && *pch != ';') {
pch++;
}
if (*pch != '\0') {
pch = strchr(string, ';');
if (pch != NULL) {
*pch = '\0';
}
// Find opening bracket.
pch = string;
while (*pch != '\0' && *pch != '[') {
pch++;
}
if (*pch == '[') {
pch = strchr(string, '[');
if (pch != NULL) {
char* sectionKey = pch + 1;
// Find closing bracket.
while (*pch != '\0' && *pch != ']') {
pch++;
}
if (*pch == ']') {
pch = strchr(sectionKey, ']');
if (pch != NULL) {
*pch = '\0';
strcpy(gConfigLastSectionKey, sectionKey);
return configTrimString(gConfigLastSectionKey);
@ -435,12 +413,8 @@ static bool configParseKeyValue(char* string, char* key, char* value)
}
// Find equals character.
char* pch = string;
while (*pch != '\0' && *pch != '=') {
pch++;
}
if (*pch == '\0') {
char* pch = strchr(string, '=');
if (pch == NULL) {
return false;
}

View File

@ -1,8 +1,8 @@
#include "core.h"
#include "audio_engine.h"
#include "config.h"
#include "color.h"
#include "config.h"
#include "dinput.h"
#include "draw.h"
#include "interface.h"
@ -13,9 +13,9 @@
#include "window_manager.h"
#include "window_manager_private.h"
#include <SDL.h>
#include <limits.h>
#include <string.h>
#include <SDL.h>
// NOT USED.
void (*_idle_func)() = NULL;
@ -116,39 +116,48 @@ int gModifierKeysState = 0;
int (*_kb_scan_to_ascii)() = keyboardDequeueLogicalKeyCode;
// 0x51E2F0
STRUCT_51E2F0* _vcr_buffer = NULL;
VcrEntry* _vcr_buffer = NULL;
// number of entries in _vcr_buffer
// 0x51E2F4
int _vcr_buffer_index = 0;
// 0x51E2F8
int _vcr_state = 2;
unsigned int gVcrState = VCR_STATE_TURNED_OFF;
// 0x51E2FC
int _vcr_time = 0;
unsigned int _vcr_time = 0;
// 0x51E300
int _vcr_counter = 0;
unsigned int _vcr_counter = 0;
// 0x51E304
int _vcr_terminate_flags = 0;
unsigned int gVcrTerminateFlags = 0;
// 0x51E308
int _vcr_terminated_condition = 0;
int gVcrPlaybackCompletionReason = VCR_PLAYBACK_COMPLETION_REASON_NONE;
// 0x51E30C
int _vcr_start_time = 0;
unsigned int _vcr_start_time = 0;
// 0x51E310
int _vcr_registered_atexit = 0;
// 0x51E314
File* _vcr_file = NULL;
File* gVcrFile = NULL;
// 0x51E318
int _vcr_buffer_end = 0;
// 0x51E31C
VcrPlaybackCompletionCallback* gVcrPlaybackCompletionCallback = NULL;
// 0x51E320
unsigned int gVcrRequestedTerminationFlags = 0;
// 0x51E324
int gVcrOldKeyboardLayout = 0;
// A map of SDL_SCANCODE_* constants normalized for QWERTY keyboard.
//
// 0x6ABC70
@ -355,6 +364,9 @@ int gKeyboardLayout;
// 0x6AD93C
unsigned char gPressedPhysicalKeysCount;
// 0x6AD940
VcrEntry stru_6AD940;
SDL_Window* gSdlWindow = NULL;
SDL_Surface* gSdlSurface = NULL;
SDL_Renderer* gSdlRenderer = NULL;
@ -446,7 +458,7 @@ void _process_bk()
tickersExecute();
if (_vcr_update() != 3) {
if (vcrUpdate() != 3) {
_mouse_info();
}
@ -629,31 +641,37 @@ void pauseGame()
// 0x4C8E38
int pauseHandlerDefaultImpl()
{
int len;
int v1;
int v2;
int win;
unsigned char* buf;
int v6;
int v7;
int windowWidth = fontGetStringWidth("Paused") + 32;
int windowHeight = 3 * fontGetLineHeight() + 16;
len = fontGetStringWidth("Paused") + 32;
v1 = fontGetLineHeight();
v2 = 3 * v1 + 16;
win = windowCreate((_scr_size.right - _scr_size.left + 1 - len) / 2, (_scr_size.bottom - _scr_size.top + 1 - v2) / 2, len, v2, 256, 20);
int win = windowCreate((rectGetWidth(&_scr_size) - windowWidth) / 2,
(rectGetHeight(&_scr_size) - windowHeight) / 2,
windowWidth,
windowHeight,
256,
WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
if (win == -1) {
return -1;
}
windowDrawBorder(win);
buf = windowGetBuffer(win);
fontDrawText(buf + 8 * len + 16, "Paused", len, len, _colorTable[31744]);
v6 = v2 - 8 - v1;
v7 = fontGetStringWidth("Done");
// TODO: Incomplete.
// _win_register_text_button(win, (len - v7 - 16) / 2, v6 - 6, -1, -1, -1, 27, "Done", 0);
unsigned char* windowBuffer = windowGetBuffer(win);
fontDrawText(windowBuffer + 8 * windowWidth + 16,
"Paused",
windowWidth,
windowWidth,
_colorTable[31744]);
_win_register_text_button(win,
(windowWidth - fontGetStringWidth("Done") - 16) / 2,
windowHeight - 8 - fontGetLineHeight() - 6,
-1,
-1,
-1,
KEY_ESCAPE,
"Done",
0);
windowRefresh(win);
@ -720,7 +738,7 @@ int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, uns
for (index = 0; index < 100000; index++) {
sprintf(fileName, "scr%.5d.bmp", index);
stream = compat_fopen(fileName, "rb");
if (stream == NULL) {
break;
@ -784,7 +802,7 @@ int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, uns
// biCompression
intValue = 0;
fwrite(&intValue, sizeof(intValue), 1, stream);
// biSizeImage
intValue = 0;
fwrite(&intValue, sizeof(intValue), 1, stream);
@ -1324,10 +1342,10 @@ void _GNW95_process_key(KeyboardData* data)
{
data->key = gNormalizedQwertyKeys[data->key];
if (_vcr_state == 1) {
if (_vcr_terminate_flags & 1) {
_vcr_terminated_condition = 2;
_vcr_stop();
if (gVcrState == VCR_STATE_PLAYING) {
if ((gVcrTerminateFlags & VCR_TERMINATE_ON_KEY_PRESS) != 0) {
gVcrPlaybackCompletionReason = VCR_PLAYBACK_COMPLETION_REASON_TERMINATED;
vcrStop();
}
} else {
STRUCT_6ABF50* ptr = &(_GNW95_key_time_stamps[data->key]);
@ -1643,10 +1661,11 @@ void _mouse_info()
x = (int)(x * gMouseSensitivity);
y = (int)(y * gMouseSensitivity);
if (_vcr_state == 1) {
if (((_vcr_terminate_flags & 4) && buttons) || ((_vcr_terminate_flags & 2) && (x || y))) {
_vcr_terminated_condition = 2;
_vcr_stop();
if (gVcrState == VCR_STATE_PLAYING) {
if (((gVcrTerminateFlags & VCR_TERMINATE_ON_MOUSE_PRESS) != 0 && buttons != 0)
|| ((gVcrTerminateFlags & VCR_TERMINATE_ON_MOUSE_MOVE) != 0 && (x != 0 || y != 0))) {
gVcrPlaybackCompletionReason = VCR_PLAYBACK_COMPLETION_REASON_TERMINATED;
vcrStop();
return;
}
x = 0;
@ -1665,18 +1684,18 @@ void _mouse_simulate_input(int delta_x, int delta_y, int buttons)
}
if (delta_x || delta_y || buttons != gMouseButtonsState) {
if (_vcr_state == 0) {
if (_vcr_buffer_index == 4095) {
_vcr_dump_buffer();
if (gVcrState == 0) {
if (_vcr_buffer_index == VCR_BUFFER_CAPACITY - 1) {
vcrDump();
}
STRUCT_51E2F0* ptr = &(_vcr_buffer[_vcr_buffer_index]);
ptr->type = 3;
ptr->field_4 = _vcr_time;
ptr->field_8 = _vcr_counter;
ptr->dx = delta_x;
ptr->dy = delta_y;
ptr->buttons = buttons;
VcrEntry* vcrEntry = &(_vcr_buffer[_vcr_buffer_index]);
vcrEntry->type = VCR_ENTRY_TYPE_MOUSE_EVENT;
vcrEntry->time = _vcr_time;
vcrEntry->counter = _vcr_counter;
vcrEntry->mouseEvent.dx = delta_x;
vcrEntry->mouseEvent.dy = delta_y;
vcrEntry->mouseEvent.buttons = buttons;
_vcr_buffer_index++;
}
@ -1996,10 +2015,10 @@ int _GNW95_init_mode_ex(int width, int height, int bpp)
_zero_mem = _GNW95_zero_vid_mem;
_mouse_blit = _GNW95_ShowRect;
} else {
_zero_mem = NULL;
_mouse_blit = _GNW95_MouseShowRect16;
_mouse_blit_trans = _GNW95_MouseShowTransRect16;
_scr_blit = _GNW95_ShowRect16;
_zero_mem = NULL;
_mouse_blit = _GNW95_MouseShowRect16;
_mouse_blit_trans = _GNW95_MouseShowTransRect16;
_scr_blit = _GNW95_ShowRect16;
}
return 0;
@ -2036,7 +2055,7 @@ int _GNW95_init_window(int width, int height, bool fullscreen)
if (gSdlRenderer == NULL) {
goto err;
}
if (SDL_RenderSetLogicalSize(gSdlRenderer, width, height) != 0) {
goto err;
}
@ -2214,7 +2233,7 @@ void directDrawSetPaletteInRange(unsigned char* palette, int start, int count)
void directDrawSetPalette(unsigned char* palette)
{
if (gSdlSurface != NULL && gSdlSurface->format->palette != NULL) {
SDL_Color colors[256];
SDL_Color colors[256];
for (int index = 0; index < 256; index++) {
colors[index].r = palette[index * 3] << 2;
@ -2251,7 +2270,6 @@ void directDrawSetPalette(unsigned char* palette)
windowRefreshAll(&_scr_size);
}
if (_update_palette_func != NULL) {
_update_palette_func();
}
@ -2555,13 +2573,14 @@ int keyboardGetLayout()
// TODO: Key type is likely short.
void _kb_simulate_key(KeyboardData* data)
{
if (_vcr_state == 0) {
if (_vcr_buffer_index != 4095) {
STRUCT_51E2F0* ptr = &(_vcr_buffer[_vcr_buffer_index]);
ptr->type = 2;
ptr->type_2_field_C = data->key & 0xFFFF;
ptr->field_4 = _vcr_time;
ptr->field_8 = _vcr_counter;
if (gVcrState == 0) {
if (_vcr_buffer_index != VCR_BUFFER_CAPACITY - 1) {
VcrEntry* vcrEntry = &(_vcr_buffer[_vcr_buffer_index]);
vcrEntry->type = VCR_ENTRY_TYPE_KEYBOARD_EVENT;
vcrEntry->keyboardEvent.key = data->key & 0xFFFF;
vcrEntry->time = _vcr_time;
vcrEntry->counter = _vcr_counter;
_vcr_buffer_index++;
}
}
@ -4359,9 +4378,9 @@ int keyboardPeekEvent(int index, KeyboardEvent** keyboardEventPtr)
}
// 0x4D2680
bool _vcr_record(const char* fileName)
bool vcrRecord(const char* fileName)
{
if (_vcr_state != 2) {
if (gVcrState != VCR_STATE_TURNED_OFF) {
return false;
}
@ -4369,77 +4388,260 @@ bool _vcr_record(const char* fileName)
return false;
}
if (_vcr_buffer != NULL) {
// NOTE: Uninline.
if (!vcrInitBuffer()) {
return false;
}
_vcr_buffer = (STRUCT_51E2F0*)internal_malloc(sizeof(*_vcr_buffer) * 4096);
if (_vcr_buffer == NULL) {
return false;
}
_vcr_clear_buffer();
_vcr_file = fileOpen(fileName, "wb");
if (_vcr_file == NULL) {
if (_vcr_buffer != NULL) {
_vcr_clear_buffer();
internal_free(_vcr_buffer);
_vcr_buffer = NULL;
}
gVcrFile = fileOpen(fileName, "wb");
if (gVcrFile == NULL) {
// NOTE: Uninline.
vcrFreeBuffer();
return false;
}
if (_vcr_registered_atexit == 0) {
_vcr_registered_atexit = atexit(_vcr_stop);
_vcr_registered_atexit = atexit(vcrStop);
}
STRUCT_51E2F0* entry = &(_vcr_buffer[_vcr_buffer_index]);
entry->type = 1;
entry->field_4 = 0;
entry->field_8 = 0;
entry->type_1_field_14 = keyboardGetLayout();
VcrEntry* vcrEntry = &(_vcr_buffer[_vcr_buffer_index]);
vcrEntry->type = VCR_ENTRY_TYPE_INITIAL_STATE;
vcrEntry->time = 0;
vcrEntry->counter = 0;
vcrEntry->initial.keyboardLayout = keyboardGetLayout();
while (mouseGetEvent() != 0) {
_mouse_info();
}
mouseGetPosition(&(entry->type_1_field_C), &(entry->type_1_field_10));
mouseGetPosition(&(vcrEntry->initial.mouseX), &(vcrEntry->initial.mouseY));
_vcr_counter = 1;
_vcr_buffer_index++;
_vcr_start_time = _get_time();
keyboardReset();
_vcr_state = 0;
gVcrState = VCR_STATE_RECORDING;
return true;
}
// 0x4D27EC
bool vcrPlay(const char* fileName, unsigned int terminationFlags, VcrPlaybackCompletionCallback* callback)
{
if (gVcrState != VCR_STATE_TURNED_OFF) {
return false;
}
if (fileName == NULL) {
return false;
}
// NOTE: Uninline.
if (!vcrInitBuffer()) {
return false;
}
gVcrFile = fileOpen(fileName, "rb");
if (gVcrFile == NULL) {
// NOTE: Uninline.
vcrFreeBuffer();
return false;
}
if (!vcrLoad()) {
fileClose(gVcrFile);
// NOTE: Uninline.
vcrFreeBuffer();
return false;
}
while (mouseGetEvent() != 0) {
_mouse_info();
}
keyboardReset();
gVcrRequestedTerminationFlags = terminationFlags;
gVcrPlaybackCompletionCallback = callback;
gVcrPlaybackCompletionReason = VCR_PLAYBACK_COMPLETION_REASON_COMPLETED;
gVcrTerminateFlags = 0;
_vcr_counter = 0;
_vcr_time = 0;
_vcr_start_time = _get_time();
gVcrState = VCR_STATE_PLAYING;
stru_6AD940.time = 0;
stru_6AD940.counter = 0;
return true;
}
// 0x4D28F4
void _vcr_stop()
void vcrStop()
{
if (_vcr_state == 0 || _vcr_state == 1) {
_vcr_state |= 0x80000000;
if (gVcrState == VCR_STATE_RECORDING || gVcrState == VCR_STATE_PLAYING) {
gVcrState |= VCR_STATE_STOP_REQUESTED;
}
keyboardReset();
}
// 0x4D2918
int _vcr_status()
int vcrGetState()
{
return _vcr_state;
return gVcrState;
}
// 0x4D2930
int _vcr_update()
int vcrUpdate()
{
// TODO: Incomplete.
if ((gVcrState & VCR_STATE_STOP_REQUESTED) != 0) {
gVcrState &= ~VCR_STATE_STOP_REQUESTED;
switch (gVcrState) {
case VCR_STATE_RECORDING:
vcrDump();
fileClose(gVcrFile);
gVcrFile = NULL;
// NOTE: Uninline.
vcrFreeBuffer();
break;
case VCR_STATE_PLAYING:
fileClose(gVcrFile);
gVcrFile = NULL;
// NOTE: Uninline.
vcrFreeBuffer();
keyboardSetLayout(gVcrOldKeyboardLayout);
if (gVcrPlaybackCompletionCallback != NULL) {
gVcrPlaybackCompletionCallback(gVcrPlaybackCompletionReason);
}
break;
}
gVcrState = VCR_STATE_TURNED_OFF;
}
switch (gVcrState) {
case VCR_STATE_RECORDING:
_vcr_counter++;
_vcr_time = getTicksSince(_vcr_start_time);
if (_vcr_buffer_index == VCR_BUFFER_CAPACITY - 1) {
vcrDump();
}
break;
case VCR_STATE_PLAYING:
if (_vcr_buffer_index < _vcr_buffer_end || vcrLoad()) {
VcrEntry* vcrEntry = &(_vcr_buffer[_vcr_buffer_index]);
if (stru_6AD940.counter < vcrEntry->counter) {
if (vcrEntry->time > stru_6AD940.time) {
unsigned int delay = stru_6AD940.time;
delay += (_vcr_counter - stru_6AD940.counter)
* (vcrEntry->time - stru_6AD940.time)
/ (vcrEntry->counter - stru_6AD940.counter);
while (getTicksSince(_vcr_start_time) < delay) {
}
}
}
_vcr_counter++;
int rc = 0;
while (_vcr_counter >= _vcr_buffer[_vcr_buffer_index].counter) {
_vcr_time = getTicksSince(_vcr_start_time);
if (_vcr_time > _vcr_buffer[_vcr_buffer_index].time + 5
|| _vcr_time < _vcr_buffer[_vcr_buffer_index].time - 5) {
_vcr_start_time += _vcr_time - _vcr_buffer[_vcr_buffer_index].time;
}
switch (_vcr_buffer[_vcr_buffer_index].type) {
case VCR_ENTRY_TYPE_INITIAL_STATE:
gVcrState = VCR_STATE_TURNED_OFF;
gVcrOldKeyboardLayout = keyboardGetLayout();
keyboardSetLayout(_vcr_buffer[_vcr_buffer_index].initial.keyboardLayout);
while (mouseGetEvent() != 0) {
_mouse_info();
}
gVcrState = VCR_ENTRY_TYPE_INITIAL_STATE;
mouseHideCursor();
_mouse_set_position(_vcr_buffer[_vcr_buffer_index].initial.mouseX, _vcr_buffer[_vcr_buffer_index].initial.mouseY);
mouseShowCursor();
keyboardReset();
gVcrTerminateFlags = gVcrRequestedTerminationFlags;
_vcr_start_time = _get_time();
_vcr_counter = 0;
break;
case VCR_ENTRY_TYPE_KEYBOARD_EVENT:
if (1) {
KeyboardData keyboardData;
keyboardData.key = _vcr_buffer[_vcr_buffer_index].keyboardEvent.key;
_kb_simulate_key(&keyboardData);
}
break;
case VCR_ENTRY_TYPE_MOUSE_EVENT:
rc = 3;
_mouse_simulate_input(_vcr_buffer[_vcr_buffer_index].mouseEvent.dx, _vcr_buffer[_vcr_buffer_index].mouseEvent.dy, _vcr_buffer[_vcr_buffer_index].mouseEvent.buttons);
break;
}
memcpy(&stru_6AD940, &(_vcr_buffer[_vcr_buffer_index]), sizeof(stru_6AD940));
_vcr_buffer_index++;
}
return rc;
} else {
// NOTE: Uninline.
vcrStop();
}
break;
}
return 0;
}
// NOTE: Inlined.
//
// 0x4D2C64
bool vcrInitBuffer()
{
if (_vcr_buffer == NULL) {
_vcr_buffer = (VcrEntry*)internal_malloc(sizeof(*_vcr_buffer) * VCR_BUFFER_CAPACITY);
if (_vcr_buffer == NULL) {
return false;
}
}
// NOTE: Uninline.
vcrClear();
return true;
}
// NOTE: Inlined.
//
// 0x4D2C98
bool vcrFreeBuffer()
{
if (_vcr_buffer == NULL) {
return false;
}
// NOTE: Uninline.
vcrClear();
internal_free(_vcr_buffer);
_vcr_buffer = NULL;
return true;
}
// 0x4D2CD0
bool _vcr_clear_buffer()
bool vcrClear()
{
if (_vcr_buffer == NULL) {
return false;
@ -4451,81 +4653,104 @@ bool _vcr_clear_buffer()
}
// 0x4D2CF0
int _vcr_dump_buffer()
bool vcrDump()
{
if (!_vcr_buffer || !_vcr_file) {
return 0;
if (_vcr_buffer == NULL) {
return false;
}
if (gVcrFile == NULL) {
return false;
}
for (int index = 0; index < _vcr_buffer_index; index++) {
if (_vcr_save_record(&(_vcr_buffer[index]), _vcr_file)) {
_vcr_buffer_index = 0;
return 1;
if (!vcrWriteEntry(&(_vcr_buffer[index]), gVcrFile)) {
return false;
}
}
return 0;
// NOTE: Uninline.
if (!vcrClear()) {
return false;
}
return true;
}
// 0x4D2D74
bool vcrLoad()
{
if (gVcrFile == NULL) {
return false;
}
// NOTE: Uninline.
if (!vcrClear()) {
return false;
}
for (_vcr_buffer_end = 0; _vcr_buffer_end < VCR_BUFFER_CAPACITY; _vcr_buffer_end++) {
if (!vcrReadEntry(&(_vcr_buffer[_vcr_buffer_end]), gVcrFile)) {
break;
}
}
if (_vcr_buffer_end == 0) {
return false;
}
return true;
}
// 0x4D2E00
bool _vcr_save_record(STRUCT_51E2F0* ptr, File* stream)
bool vcrWriteEntry(VcrEntry* vcrEntry, File* stream)
{
if (_db_fwriteLong(stream, ptr->type) == -1) goto err;
if (_db_fwriteLong(stream, ptr->field_4) == -1) goto err;
if (_db_fwriteLong(stream, ptr->field_8) == -1) goto err;
switch (ptr->type) {
case 1:
if (_db_fwriteLong(stream, ptr->type_1_field_C) == -1) goto err;
if (_db_fwriteLong(stream, ptr->type_1_field_10) == -1) goto err;
if (_db_fwriteLong(stream, ptr->type_1_field_14) == -1) goto err;
if (fileWriteUInt32(stream, vcrEntry->type) == -1) return false;
if (fileWriteUInt32(stream, vcrEntry->time) == -1) return false;
if (fileWriteUInt32(stream, vcrEntry->counter) == -1) return false;
switch (vcrEntry->type) {
case VCR_ENTRY_TYPE_INITIAL_STATE:
if (fileWriteInt32(stream, vcrEntry->initial.mouseX) == -1) return false;
if (fileWriteInt32(stream, vcrEntry->initial.mouseY) == -1) return false;
if (fileWriteInt32(stream, vcrEntry->initial.keyboardLayout) == -1) return false;
return true;
case 2:
if (fileWriteInt16(stream, ptr->type_2_field_C) == -1) goto err;
case VCR_ENTRY_TYPE_KEYBOARD_EVENT:
if (fileWriteInt16(stream, vcrEntry->keyboardEvent.key) == -1) return false;
return true;
case 3:
if (_db_fwriteLong(stream, ptr->dx) == -1) goto err;
if (_db_fwriteLong(stream, ptr->dy) == -1) goto err;
if (_db_fwriteLong(stream, ptr->buttons) == -1) goto err;
case VCR_ENTRY_TYPE_MOUSE_EVENT:
if (fileWriteInt32(stream, vcrEntry->mouseEvent.dx) == -1) return false;
if (fileWriteInt32(stream, vcrEntry->mouseEvent.dy) == -1) return false;
if (fileWriteInt32(stream, vcrEntry->mouseEvent.buttons) == -1) return false;
return true;
}
err:
return false;
}
// 0x4D2EE4
bool _vcr_load_record(STRUCT_51E2F0* ptr, File* stream)
bool vcrReadEntry(VcrEntry* vcrEntry, File* stream)
{
if (_db_freadInt(stream, &(ptr->type)) == -1) goto err;
if (_db_freadInt(stream, &(ptr->field_4)) == -1) goto err;
if (_db_freadInt(stream, &(ptr->field_8)) == -1) goto err;
switch (ptr->type) {
case 1:
if (_db_freadInt(stream, &(ptr->type_1_field_C)) == -1) goto err;
if (_db_freadInt(stream, &(ptr->type_1_field_10)) == -1) goto err;
if (_db_freadInt(stream, &(ptr->type_1_field_14)) == -1) goto err;
if (fileReadUInt32(stream, &(vcrEntry->type)) == -1) return false;
if (fileReadUInt32(stream, &(vcrEntry->time)) == -1) return false;
if (fileReadUInt32(stream, &(vcrEntry->counter)) == -1) return false;
switch (vcrEntry->type) {
case VCR_ENTRY_TYPE_INITIAL_STATE:
if (fileReadInt32(stream, &(vcrEntry->initial.mouseX)) == -1) return false;
if (fileReadInt32(stream, &(vcrEntry->initial.mouseY)) == -1) return false;
if (fileReadInt32(stream, &(vcrEntry->initial.keyboardLayout)) == -1) return false;
return true;
case 2:
if (fileReadInt16(stream, &(ptr->type_2_field_C)) == -1) goto err;
case VCR_ENTRY_TYPE_KEYBOARD_EVENT:
if (fileReadInt16(stream, &(vcrEntry->keyboardEvent.key)) == -1) return false;
return true;
case 3:
if (_db_freadInt(stream, &(ptr->dx)) == -1) goto err;
if (_db_freadInt(stream, &(ptr->dy)) == -1) goto err;
if (_db_freadInt(stream, &(ptr->buttons)) == -1) goto err;
case VCR_ENTRY_TYPE_MOUSE_EVENT:
if (fileReadInt32(stream, &(vcrEntry->mouseEvent.dx)) == -1) return false;
if (fileReadInt32(stream, &(vcrEntry->mouseEvent.dy)) == -1) return false;
if (fileReadInt32(stream, &(vcrEntry->mouseEvent.buttons)) == -1) return false;
return true;
}
err:
return false;
}

View File

@ -360,6 +360,44 @@ typedef enum KeyboardLayout {
KEYBOARD_LAYOUT_SPANISH,
} KeyboardLayout;
#define VCR_BUFFER_CAPACITY 4096
typedef enum VcrState {
VCR_STATE_RECORDING,
VCR_STATE_PLAYING,
VCR_STATE_TURNED_OFF,
} VcrState;
#define VCR_STATE_STOP_REQUESTED 0x80000000
typedef enum VcrTerminationFlags {
// Specifies that VCR playback should stop if any key is pressed.
VCR_TERMINATE_ON_KEY_PRESS = 0x01,
// Specifies that VCR playback should stop if mouse is mouved.
VCR_TERMINATE_ON_MOUSE_MOVE = 0x02,
// Specifies that VCR playback should stop if any mouse button is pressed.
VCR_TERMINATE_ON_MOUSE_PRESS = 0x04,
} VcrTerminationFlags;
typedef enum VcrPlaybackCompletionReason {
VCR_PLAYBACK_COMPLETION_REASON_NONE = 0,
// Indicates that VCR playback completed normally.
VCR_PLAYBACK_COMPLETION_REASON_COMPLETED = 1,
// Indicates that VCR playback terminated according to termination flags.
VCR_PLAYBACK_COMPLETION_REASON_TERMINATED = 2,
} VcrPlaybackCompletionReason;
typedef enum VcrEntryType {
VCR_ENTRY_TYPE_NONE = 0,
VCR_ENTRY_TYPE_INITIAL_STATE = 1,
VCR_ENTRY_TYPE_KEYBOARD_EVENT = 2,
VCR_ENTRY_TYPE_MOUSE_EVENT = 3,
} VcrEntryType;
typedef struct STRUCT_6ABF50 {
// Time when appropriate key was pressed down or -1 if it's up.
int tick;
@ -383,26 +421,26 @@ typedef struct TickerListNode {
struct TickerListNode* next;
} TickerListNode;
typedef struct STRUCT_51E2F0 {
int type;
int field_4;
int field_8;
typedef struct VcrEntry {
unsigned int type;
unsigned int time;
unsigned int counter;
union {
struct {
int type_1_field_C; // mouse x
int type_1_field_10; // mouse y
int type_1_field_14; // keyboard layout
};
int mouseX;
int mouseY;
int keyboardLayout;
} initial;
struct {
short type_2_field_C;
};
short key;
} keyboardEvent;
struct {
int dx;
int dy;
int buttons;
};
} mouseEvent;
};
} STRUCT_51E2F0;
} VcrEntry;
typedef struct LogicalKeyEntry {
short field_0;
@ -420,6 +458,7 @@ typedef struct KeyboardEvent {
typedef int(PauseHandler)();
typedef int(ScreenshotHandler)(int width, int height, unsigned char* buffer, unsigned char* palette);
typedef void(VcrPlaybackCompletionCallback)(int reason);
extern void (*_idle_func)();
extern void (*_focus_func)(int);
@ -448,17 +487,20 @@ extern int gKeyboardEventQueueReadIndex;
extern short word_51E2E8;
extern int gModifierKeysState;
extern int (*_kb_scan_to_ascii)();
extern STRUCT_51E2F0* _vcr_buffer;
extern VcrEntry* _vcr_buffer;
extern int _vcr_buffer_index;
extern int _vcr_state;
extern int _vcr_time;
extern int _vcr_counter;
extern int _vcr_terminate_flags;
extern int _vcr_terminated_condition;
extern int _vcr_start_time;
extern unsigned int gVcrState;
extern unsigned int _vcr_time;
extern unsigned int _vcr_counter;
extern unsigned int gVcrTerminateFlags;
extern int gVcrPlaybackCompletionReason;
extern unsigned int _vcr_start_time;
extern int _vcr_registered_atexit;
extern File* _vcr_file;
extern File* gVcrFile;
extern int _vcr_buffer_end;
extern VcrPlaybackCompletionCallback* gVcrPlaybackCompletionCallback;
extern unsigned int gVcrRequestedTerminationFlags;
extern int gVcrOldKeyboardLayout;
extern int gNormalizedQwertyKeys[SDL_NUM_SCANCODES];
extern InputEvent gInputEventQueue[40];
@ -520,6 +562,7 @@ extern unsigned int _kb_idle_start_time;
extern KeyboardEvent gLastKeyboardEvent;
extern int gKeyboardLayout;
extern unsigned char gPressedPhysicalKeysCount;
extern VcrEntry stru_6AD940;
extern SDL_Window* gSdlWindow;
extern SDL_Surface* gSdlSurface;
@ -621,14 +664,18 @@ void keyboardBuildItalianConfiguration();
void keyboardBuildSpanishConfiguration();
void _kb_init_lock_status();
int keyboardPeekEvent(int index, KeyboardEvent** keyboardEventPtr);
bool _vcr_record(const char* fileName);
void _vcr_stop();
int _vcr_status();
int _vcr_update();
bool _vcr_clear_buffer();
int _vcr_dump_buffer();
bool _vcr_save_record(STRUCT_51E2F0* ptr, File* stream);
bool _vcr_load_record(STRUCT_51E2F0* ptr, File* stream);
bool vcrRecord(const char* fileName);
bool vcrPlay(const char* fileName, unsigned int terminationFlags, VcrPlaybackCompletionCallback* callback);
void vcrStop();
int vcrGetState();
int vcrUpdate();
bool vcrInitBuffer();
bool vcrFreeBuffer();
bool vcrClear();
bool vcrDump();
bool vcrLoad();
bool vcrWriteEntry(VcrEntry* ptr, File* stream);
bool vcrReadEntry(VcrEntry* ptr, File* stream);
int screenGetWidth();
int screenGetHeight();

View File

@ -276,18 +276,18 @@ void dudeResetName()
// 0x42D18C
int critterGetHitPoints(Object* critter)
{
return (critter->pid >> 24) == OBJ_TYPE_CRITTER ? critter->data.critter.hp : 0;
return PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER ? critter->data.critter.hp : 0;
}
// 0x42D1A4
int critterAdjustHitPoints(Object* critter, int a2)
int critterAdjustHitPoints(Object* critter, int hp)
{
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
int maximumHp = critterGetStat(critter, STAT_MAXIMUM_HIT_POINTS);
int newHp = critter->data.critter.hp + a2;
int newHp = critter->data.critter.hp + hp;
critter->data.critter.hp = newHp;
if (maximumHp >= newHp) {
@ -304,7 +304,7 @@ int critterAdjustHitPoints(Object* critter, int a2)
// 0x42D1F8
int critterGetPoison(Object* critter)
{
return (critter->pid >> 24) == OBJ_TYPE_CRITTER ? critter->data.critter.poison : 0;
return PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER ? critter->data.critter.poison : 0;
}
// Adjust critter's current poison by specified amount.
@ -396,7 +396,7 @@ int poisonEventProcess(Object* obj, void* data)
// 0x42D38C
int critterGetRadiation(Object* obj)
{
return (obj->pid >> 24) == OBJ_TYPE_CRITTER ? obj->data.critter.radiation : 0;
return PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER ? obj->data.critter.radiation : 0;
}
// 0x42D3A4
@ -416,7 +416,7 @@ int critterAdjustRadiation(Object* obj, int amount)
}
if (amount > 0) {
proto->critter.data.flags |= 0x02;
proto->critter.data.flags |= CRITTER_FLAG_0x2;
}
if (amount > 0) {
@ -483,7 +483,7 @@ int _critter_check_rads(Object* obj)
Proto* proto;
protoGetProto(obj->pid, &proto);
if ((proto->critter.data.flags & 0x02) == 0) {
if ((proto->critter.data.flags & CRITTER_FLAG_0x2) == 0) {
return 0;
}
@ -521,10 +521,10 @@ int _critter_check_rads(Object* obj)
radiationEvent->radiationLevel = radiationLevel;
radiationEvent->isHealing = 0;
queueAddEvent(36000 * randomBetween(4, 18), obj, radiationEvent, EVENT_TYPE_RADIATION);
queueAddEvent(GAME_TIME_TICKS_PER_HOUR * randomBetween(4, 18), obj, radiationEvent, EVENT_TYPE_RADIATION);
}
proto->critter.data.flags &= ~(0x02);
proto->critter.data.flags &= ~(CRITTER_FLAG_0x2);
return 0;
}
@ -657,7 +657,7 @@ int radiationEventWrite(File* stream, void* data)
// 0x42D82C
int critterGetDamageType(Object* obj)
{
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
@ -723,7 +723,7 @@ int critterGetKillType(Object* obj)
return KILL_TYPE_MAN;
}
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
return -1;
}
@ -766,7 +766,7 @@ char* killTypeGetDescription(int killType)
// 0x42D9F4
int _critter_heal_hours(Object* critter, int a2)
{
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return -1;
}
@ -788,7 +788,7 @@ static int _critterClearObjDrugs(Object* obj, void* data)
// 0x42DA64
void critterKill(Object* critter, int anim, bool a3)
{
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return;
}
@ -800,20 +800,20 @@ void critterKill(Object* critter, int anim, bool a3)
bool shouldChangeFid = false;
int fid;
if (_critter_is_prone(critter)) {
int current = (critter->fid & 0xFF0000) >> 16;
int current = FID_ANIM_TYPE(critter->fid);
if (current == ANIM_FALL_BACK || current == ANIM_FALL_FRONT) {
bool back = false;
if (current == ANIM_FALL_BACK) {
back = true;
} else {
fid = buildFid(1, critter->fid & 0xFFF, ANIM_FALL_FRONT_SF, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, ANIM_FALL_FRONT_SF, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
if (!artExists(fid)) {
back = true;
}
}
if (back) {
fid = buildFid(1, critter->fid & 0xFFF, ANIM_FALL_BACK_SF, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, ANIM_FALL_BACK_SF, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
}
shouldChangeFid = true;
@ -828,12 +828,12 @@ void critterKill(Object* critter, int anim, bool a3)
anim = LAST_SF_DEATH_ANIM;
}
fid = buildFid(1, critter->fid & 0xFFF, anim, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, anim, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
_obj_fix_violence_settings(&fid);
if (!artExists(fid)) {
debugPrint("\nError: Critter Kill: Can't match fid!");
fid = buildFid(1, critter->fid & 0xFFF, ANIM_FALL_BACK_BLOOD_SF, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, ANIM_FALL_BACK_BLOOD_SF, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
_obj_fix_violence_settings(&fid);
}
@ -850,7 +850,7 @@ void critterKill(Object* critter, int anim, bool a3)
rectUnion(&updatedRect, &tempRect, &updatedRect);
}
if (!_critter_flag_check(critter->pid, 2048)) {
if (!_critter_flag_check(critter->pid, CRITTER_FLAG_0x800)) {
critter->flags |= OBJECT_NO_BLOCK;
_obj_toggle_flat(critter, &tempRect);
}
@ -902,7 +902,7 @@ bool critterIsActive(Object* critter)
return false;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -924,7 +924,7 @@ bool critterIsDead(Object* critter)
return false;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -946,7 +946,7 @@ bool critterIsCrippled(Object* critter)
return false;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -960,11 +960,11 @@ bool _critter_is_prone(Object* critter)
return false;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return false;
}
int anim = (critter->fid & 0xFF0000) >> 16;
int anim = FID_ANIM_TYPE(critter->fid);
return (critter->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN)) != 0
|| anim >= FIRST_KNOCKDOWN_AND_DEATH_ANIM && anim <= LAST_KNOCKDOWN_AND_DEATH_ANIM
@ -980,7 +980,7 @@ int critterGetBodyType(Object* critter)
return 0;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
@ -1236,7 +1236,7 @@ int knockoutEventProcess(Object* obj, void* data)
// 0x42E460
int _critter_wake_clear(Object* obj, void* data)
{
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
@ -1246,7 +1246,7 @@ int _critter_wake_clear(Object* obj, void* data)
obj->data.critter.combat.results &= ~(DAM_KNOCKED_OUT | DAM_KNOCKED_DOWN);
int fid = buildFid((obj->fid & 0xF000000) >> 24, obj->fid & 0xFFF, ANIM_STAND, (obj->fid & 0xF000) >> 12, obj->rotation + 1);
int fid = buildFid(FID_TYPE(obj->fid), obj->fid & 0xFFF, ANIM_STAND, (obj->fid & 0xF000) >> 12, obj->rotation + 1);
objectSetFid(obj, fid, 0);
return 0;
@ -1259,11 +1259,11 @@ int _critter_set_who_hit_me(Object* a1, Object* a2)
return -1;
}
if (a2 != NULL && ((a2->fid & 0xF000000) >> 24) != OBJ_TYPE_CRITTER) {
if (a2 != NULL && FID_TYPE(a2->fid) != OBJ_TYPE_CRITTER) {
return -1;
}
if ((a1->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(a1->pid) == OBJ_TYPE_CRITTER) {
if (a2 == NULL || a1->data.critter.combat.team != a2->data.critter.combat.team || statRoll(a1, STAT_INTELLIGENCE, -1, NULL) < 2 && (!objectIsPartyMember(a1) || !objectIsPartyMember(a2))) {
a1->data.critter.combat.whoHitMe = a2;
if (a2 == gDude) {
@ -1319,7 +1319,7 @@ bool _critter_can_obj_dude_rest()
// 0x42E62C
int critterGetMovementPointCostAdjustedForCrippledLegs(Object* critter, int actionPoints)
{
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
@ -1358,7 +1358,7 @@ bool _critter_flag_check(int pid, int flag)
return false;
}
if ((pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(pid) != OBJ_TYPE_CRITTER) {
return false;
}

View File

@ -21,7 +21,7 @@ void critterProtoDataCopy(CritterProtoData* dest, CritterProtoData* src);
int dudeSetName(const char* name);
void dudeResetName();
int critterGetHitPoints(Object* critter);
int critterAdjustHitPoints(Object* critter, int amount);
int critterAdjustHitPoints(Object* critter, int hp);
int critterGetPoison(Object* critter);
int critterAdjustPoison(Object* obj, int amount);
int poisonEventProcess(Object* obj, void* data);

View File

@ -1,10 +1,195 @@
#include "datafile.h"
#include <string.h>
#include "color.h"
#include "db.h"
#include "memory_manager.h"
#include "pcx.h"
#include "platform_compat.h"
// 0x5184AC
DatafileLoader* gDatafileLoader = NULL;
// 0x5184B0
DatafileNameMangler* gDatafileNameMangler = datafileDefaultNameManglerImpl;
// 0x56D7E0
unsigned char _pal[768];
unsigned char gDatafilePalette[768];
// 0x42EE70
char* datafileDefaultNameManglerImpl(char* path)
{
return path;
}
// NOTE: Unused.
//
// 0x42EE74
void datafileSetNameMangler(DatafileNameMangler* mangler)
{
gDatafileNameMangler = mangler;
}
// NOTE: Unused.
//
// 0x42EE7C
void datafileSetLoader(DatafileLoader* loader)
{
gDatafileLoader = loader;
}
// 0x42EE84
void sub_42EE84(unsigned char* data, unsigned char* palette, int width, int height)
{
unsigned char indexedPalette[256];
indexedPalette[0] = 0;
for (int index = 1; index < 256; index++) {
// TODO: Check.
int r = palette[index * 3 + 2] >> 3;
int g = palette[index * 3 + 1] >> 3;
int b = palette[index * 3] >> 3;
int colorTableIndex = (r << 10) | (g << 5) | b;
indexedPalette[index] = _colorTable[colorTableIndex];
}
int size = width * height;
for (int index = 0; index < size; index++) {
data[index] = indexedPalette[data[index]];
}
}
// NOTE: Unused.
//
// 0x42EEF8
void sub_42EEF8(unsigned char* data, unsigned char* palette, int width, int height)
{
unsigned char indexedPalette[256];
indexedPalette[0] = 0;
for (int index = 1; index < 256; index++) {
// TODO: Check.
int r = palette[index * 3 + 2] >> 1;
int g = palette[index * 3 + 1] >> 1;
int b = palette[index * 3] >> 1;
int colorTableIndex = (r << 10) | (g << 5) | b;
indexedPalette[index] = _colorTable[colorTableIndex];
}
int size = width * height;
for (int index = 0; index < size; index++) {
data[index] = indexedPalette[data[index]];
}
}
// 0x42EF60
unsigned char* datafileReadRaw(char* path, int* widthPtr, int* heightPtr)
{
char* mangledPath = gDatafileNameMangler(path);
char* dot = strrchr(mangledPath, '.');
if (dot != NULL) {
if (compat_stricmp(dot + 1, "pcx")) {
return pcxRead(mangledPath, widthPtr, heightPtr, gDatafilePalette);
}
}
if (gDatafileLoader != NULL) {
return gDatafileLoader(mangledPath, gDatafilePalette, widthPtr, heightPtr);
}
return NULL;
}
// 0x42EFCC
unsigned char* datafileRead(char* path, int* widthPtr, int* heightPtr)
{
unsigned char* v1 = datafileReadRaw(path, widthPtr, heightPtr);
if (v1 != NULL) {
sub_42EE84(v1, gDatafilePalette, *widthPtr, *heightPtr);
}
return v1;
}
// NOTE: Unused
//
// 0x42EFF4
unsigned char* sub_42EFF4(char* path)
{
int width;
int height;
unsigned char* v3 = datafileReadRaw(path, &width, &height);
if (v3 != NULL) {
internal_free_safe(v3, __FILE__, __LINE__); // "..\\int\\DATAFILE.C", 148
return gDatafilePalette;
}
return NULL;
}
// NOTE: Unused.
//
// 0x42F024
void sub_42F024(unsigned char* data, int* widthPtr, int* heightPtr)
{
int width = *widthPtr;
int height = *heightPtr;
unsigned char* temp = (unsigned char*)internal_malloc_safe(width * height, __FILE__, __LINE__); // "..\\int\\DATAFILE.C", 157
// NOTE: Original code does not initialize `x`.
int y = 0;
int x = 0;
unsigned char* src1 = data;
for (y = 0; y < height; y++) {
if (*src1 == 0) {
break;
}
unsigned char* src2 = src1;
for (x = 0; x < width; x++) {
if (*src2 == 0) {
break;
}
*temp++ = *src2++;
}
src1 += width;
}
memcpy(data, temp, x * y);
internal_free_safe(temp, __FILE__, __LINE__); // // "..\\int\\DATAFILE.C", 171
}
// 0x42F0E4
unsigned char* _datafileGetPalette()
unsigned char* datafileGetPalette()
{
return _pal;
return gDatafilePalette;
}
// NOTE: Unused.
//
// 0x42F0EC
unsigned char* datafileLoad(char* path, int* sizePtr)
{
const char* mangledPath = gDatafileNameMangler(path);
File* stream = fileOpen(mangledPath, "rb");
if (stream == NULL) {
return NULL;
}
int size = fileGetSize(stream);
unsigned char* data = (unsigned char*)internal_malloc_safe(size, __FILE__, __LINE__); // "..\\int\\DATAFILE.C", 185
if (data == NULL) {
// NOTE: This code is unreachable, internal_malloc_safe never fails.
// Otherwise it leaks stream.
*sizePtr = 0;
return NULL;
}
fileRead(data, 1, size, stream);
fileClose(stream);
*sizePtr = size;
return data;
}

View File

@ -1,8 +1,24 @@
#ifndef DATAFILE_H
#define DATAFILE_H
extern unsigned char _pal[768];
typedef unsigned char*(DatafileLoader)(char* path, unsigned char* palette, int* widthPtr, int* heightPtr);
typedef char*(DatafileNameMangler)(char* path);
unsigned char* _datafileGetPalette();
extern DatafileLoader* gDatafileLoader;
extern DatafileNameMangler* gDatafileNameMangler;
extern unsigned char gDatafilePalette[768];
char* datafileDefaultNameManglerImpl(char* path);
void datafileSetNameMangler(DatafileNameMangler* mangler);
void datafileSetLoader(DatafileLoader* loader);
void sub_42EE84(unsigned char* data, unsigned char* palette, int width, int height);
void sub_42EEF8(unsigned char* data, unsigned char* palette, int width, int height);
unsigned char* datafileReadRaw(char* path, int* widthPtr, int* heightPtr);
unsigned char* datafileRead(char* path, int* widthPtr, int* heightPtr);
unsigned char* sub_42EFF4(char* path);
void sub_42F024(unsigned char* data, int* widthPtr, int* heightPtr);
unsigned char* datafileGetPalette();
unsigned char* datafileLoad(char* path, int* sizePtr);
#endif /* DATAFILE_H */

View File

@ -638,7 +638,7 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a
}
}
bool v1 = *pattern == '*';
bool isWildcard = *pattern == '*';
for (int index = 0; index < fileNamesLength; index += 1) {
const char* name = xlist->fileNames[index];
@ -647,16 +647,7 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a
char extension[COMPAT_MAX_EXT];
compat_splitpath(name, NULL, dir, fileName, extension);
bool v2 = false;
if (v1) {
char* pch = dir;
while (*pch != '\0' && *pch != '\\') {
pch++;
}
v2 = *pch != '\0';
}
if (!v2) {
if (!isWildcard || *dir == '\0' || strchr(dir, '\\') == NULL) {
// NOTE: Quick and dirty fix to buffer overflow. See RE to
// understand the problem.
char path[COMPAT_MAX_PATH];

View File

@ -196,7 +196,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
CacheEntry* backgroundHandle;
int backgroundWidth;
int backgroundHeight;
int fid = buildFid(6, gDialogBoxBackgroundFrmIds[dialogType], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gDialogBoxBackgroundFrmIds[dialogType], 0, 0, 0);
unsigned char* background = artLockFrameDataReturningSize(fid, &backgroundHandle, &backgroundWidth, &backgroundHeight);
if (background == NULL) {
fontSetCurrent(savedFont);
@ -230,7 +230,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
unsigned char* upButton = NULL;
if ((flags & DIALOG_BOX_0x20) == 0) {
int doneBoxFid = buildFid(6, 209, 0, 0, 0);
int doneBoxFid = buildFid(OBJ_TYPE_INTERFACE, 209, 0, 0, 0);
doneBox = artLockFrameDataReturningSize(doneBoxFid, &doneBoxHandle, &doneBoxWidth, &doneBoxHeight);
if (doneBox == NULL) {
artUnlock(backgroundHandle);
@ -239,7 +239,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
return -1;
}
int downButtonFid = buildFid(6, 9, 0, 0, 0);
int downButtonFid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
downButton = artLockFrameDataReturningSize(downButtonFid, &downButtonHandle, &downButtonWidth, &downButtonHeight);
if (downButton == NULL) {
artUnlock(doneBoxHandle);
@ -249,7 +249,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
return -1;
}
int upButtonFid = buildFid(6, 8, 0, 0, 0);
int upButtonFid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
upButton = artLockFrameData(upButtonFid, 0, 0, &upButtonHandle);
if (upButton == NULL) {
artUnlock(downButtonHandle);
@ -331,7 +331,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
buttonSetCallbacks(btn, _gsound_red_butt_press, _gsound_red_butt_release);
}
} else {
int doneBoxFid = buildFid(6, 209, 0, 0, 0);
int doneBoxFid = buildFid(OBJ_TYPE_INTERFACE, 209, 0, 0, 0);
unsigned char* doneBox = artLockFrameDataReturningSize(doneBoxFid, &doneBoxHandle, &doneBoxWidth, &doneBoxHeight);
if (doneBox == NULL) {
artUnlock(backgroundHandle);
@ -340,7 +340,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
return -1;
}
int downButtonFid = buildFid(6, 9, 0, 0, 0);
int downButtonFid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
unsigned char* downButton = artLockFrameDataReturningSize(downButtonFid, &downButtonHandle, &downButtonWidth, &downButtonHeight);
if (downButton == NULL) {
artUnlock(doneBoxHandle);
@ -350,7 +350,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
return -1;
}
int upButtonFid = buildFid(6, 8, 0, 0, 0);
int upButtonFid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
unsigned char* upButton = artLockFrameData(upButtonFid, 0, 0, &upButtonHandle);
if (upButton == NULL) {
artUnlock(downButtonHandle);
@ -517,7 +517,7 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
}
// 0x41DE90
int showLoadFileDialog(char *title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
{
int oldFont = fontGetCurrent();
@ -541,7 +541,7 @@ int showLoadFileDialog(char *title, char** fileList, char* dest, int fileListLen
Size frmSizes[FILE_DIALOG_FRM_COUNT];
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
int fid = buildFid(6, gLoadFileDialogFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gLoadFileDialogFrmIds[index], 0, 0, 0);
frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
if (frmBuffers[index] == NULL) {
while (--index >= 0) {
@ -551,7 +551,6 @@ int showLoadFileDialog(char *title, char** fileList, char* dest, int fileListLen
}
}
int backgroundWidth = frmSizes[FILE_DIALOG_FRM_BACKGROUND].width;
int backgroundHeight = frmSizes[FILE_DIALOG_FRM_BACKGROUND].height;
@ -922,7 +921,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
Size frmSizes[FILE_DIALOG_FRM_COUNT];
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
int fid = buildFid(6, gSaveFileDialogFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gSaveFileDialogFrmIds[index], 0, 0, 0);
frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
if (frmBuffers[index] == NULL) {
while (--index >= 0) {
@ -1090,7 +1089,7 @@ int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLen
char fileNameCopy[32];
strncpy(fileNameCopy, dest, 32);
int fileNameCopyLength = strlen(fileNameCopy);
fileNameCopy[fileNameCopyLength + 1] = '\0';
fileNameCopy[fileNameCopyLength] = ' ';

View File

@ -76,7 +76,7 @@ int dword_56DB6C;
int dword_56DB70;
// 0x56DB74
int _rand2plus;
char* off_56DB74;
// 0x56DB7C
int dword_56DB7C;
@ -91,7 +91,7 @@ int dword_56DB84;
int dword_56DB88;
// 0x56DB8C
int dword_56DB8C;
char* off_56DB8C;
// 0x56DB90
int _replyPlaying;
@ -127,16 +127,16 @@ int dword_56DBB8;
int dword_56DBBC;
// 0x56DBC0
void* off_56DBC0;
char* off_56DBC0;
// 0x56DBC4
void* off_56DBC4;
char* off_56DBC4;
// 0x56DBC8
void* off_56DBC8;
char* off_56DBC8;
// 0x56DBCC
void* off_56DBCC;
char* off_56DBCC;
// 0x56DBD0
char* gDialogReplyTitle;
@ -151,16 +151,16 @@ int dword_56DBD8;
int dword_56DBDC;
// 0x56DBE0
void* off_56DBE0;
char* off_56DBE0;
// 0x56DBE4
void* off_56DBE4;
char* off_56DBE4;
// 0x56DBE8
void* off_56DBE8;
char* off_56DBE8;
// 0x56DBEC
void* off_56DBEC;
char* off_56DBEC;
// 0x42F434
STRUCT_56DAE0_FIELD_4* _getReply()
@ -191,7 +191,7 @@ void _replyAddOption(const char* a1, const char* a2, int a3)
v18 = _getReply();
v17 = v18->field_14 - 1;
v18->field_C[v17].field_8 = 2;
v18->field_C[v17].kind = 2;
if (a1 != NULL) {
v14 = (char*)internal_malloc_safe(strlen(a1) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 805
@ -204,9 +204,9 @@ void _replyAddOption(const char* a1, const char* a2, int a3)
if (a2 != NULL) {
v15 = (char*)internal_malloc_safe(strlen(a2) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 810
strcpy(v15, a2);
v18->field_C[v17].field_4 = v15;
v18->field_C[v17].string = v15;
} else {
v18->field_C[v17].field_4 = NULL;
v18->field_C[v17].string = NULL;
}
v18->field_C[v17].field_18 = widgetGetFont();
@ -215,7 +215,7 @@ void _replyAddOption(const char* a1, const char* a2, int a3)
}
// 0x42F624
void _replyAddOptionProc(const char* a1, const char* a2, int a3)
void _replyAddOptionProc(const char* a1, int a2, int a3)
{
STRUCT_56DAE0_FIELD_4* v5;
int v13;
@ -224,7 +224,7 @@ void _replyAddOptionProc(const char* a1, const char* a2, int a3)
v5 = _getReply();
v13 = v5->field_14 - 1;
v5->field_C[v13].field_8 = 1;
v5->field_C[v13].kind = 1;
if (a1 != NULL) {
v11 = (char*)internal_malloc_safe(strlen(a1) + 1, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 830
@ -234,7 +234,7 @@ void _replyAddOptionProc(const char* a1, const char* a2, int a3)
v5->field_C[v13].field_0 = NULL;
}
v5->field_C[v13].field_4 = (char*)a2;
v5->field_C[v13].proc = a2;
v5->field_C[v13].field_18 = widgetGetFont();
v5->field_C[v13].field_1A = word_56DB60;
@ -248,9 +248,9 @@ void _optionFree(STRUCT_56DAE0_FIELD_4_FIELD_C* a1)
internal_free_safe(a1->field_0, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 844
}
if (a1->field_8 == 2) {
if (a1->field_4 != NULL) {
internal_free_safe(a1->field_4, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 846
if (a1->kind == 2) {
if (a1->string != NULL) {
internal_free_safe(a1->string, __FILE__, __LINE__); // "..\\int\\DIALOG.C", 846
}
}
}
@ -503,7 +503,7 @@ int _dialogOption(const char* a1, const char* a2)
}
// 0x430F38
int _dialogOptionProc(const char* a1, const char* a2)
int _dialogOptionProc(const char* a1, int a2)
{
if (_dialog[_tods].field_C == -1) {
return 1;
@ -514,6 +514,20 @@ int _dialogOptionProc(const char* a1, const char* a2)
return 0;
}
// 0x430FD4
int sub_430FD4(const char* a1, const char* a2, int timeout)
{
// TODO: Incomplete.
return -1;
}
// 0x431088
int sub_431088(int a1)
{
// TODO: Incomplete.
return -1;
}
// 0x431184
int _dialogGetExitPoint()
{
@ -533,24 +547,24 @@ int _dialogQuit()
}
// 0x4311B8
int dialogSetOptionWindow(int a1, int a2, int a3, int a4, int a5)
int dialogSetOptionWindow(int a1, int a2, int a3, int a4, char* a5)
{
dword_56DB6C = a1;
dword_56DB70 = a2;
dword_56DB64 = a3;
dword_56DB68 = a4;
_rand2plus = a5;
off_56DB74 = a5;
return 0;
}
// 0x4311E0
int dialogSetReplyWindow(int a1, int a2, int a3, int a4, int a5)
int dialogSetReplyWindow(int a1, int a2, int a3, int a4, char* a5)
{
dword_56DB84 = a1;
dword_56DB88 = a2;
dword_56DB7C = a3;
dword_56DB80 = a4;
dword_56DB8C = a5;
off_56DB8C = a5;
return 0;
}
@ -565,7 +579,7 @@ int dialogSetBorder(int a1, int a2)
}
// 0x431218
int _dialogSetScrollUp(int a1, int a2, void* a3, void* a4, void* a5, void* a6, int a7)
int _dialogSetScrollUp(int a1, int a2, char* a3, char* a4, char* a5, char* a6, int a7)
{
_upButton = a1;
dword_56DBD8 = a2;
@ -596,7 +610,7 @@ int _dialogSetScrollUp(int a1, int a2, void* a3, void* a4, void* a5, void* a6, i
}
// 0x4312C0
int _dialogSetScrollDown(int a1, int a2, void* a3, void* a4, void* a5, void* a6, int a7)
int _dialogSetScrollDown(int a1, int a2, char* a3, char* a4, char* a5, char* a6, int a7)
{
_downButton = a1;
dword_56DBB8 = a2;
@ -666,6 +680,11 @@ int _dialogSetOptionFlags(int flags)
return 1;
}
// 0x431430
void dialogInit()
{
}
// 0x431434
void _dialogClose()
{

View File

@ -8,8 +8,11 @@ typedef void DialogFunc2(int win);
typedef struct STRUCT_56DAE0_FIELD_4_FIELD_C {
char* field_0;
char* field_4;
int field_8;
union {
int proc;
char* string;
};
int kind;
int field_C;
int field_10;
int field_14;
@ -60,12 +63,12 @@ extern int dword_56DB64;
extern int dword_56DB68;
extern int dword_56DB6C;
extern int dword_56DB70;
extern int _rand2plus;
extern char* off_56DB74;
extern int dword_56DB7C;
extern int dword_56DB80;
extern int dword_56DB84;
extern int dword_56DB88;
extern int dword_56DB8C;
extern char* off_56DB8C;
extern int _replyPlaying;
extern int _replyWin;
extern int gDialogReplyColorG;
@ -77,22 +80,22 @@ extern int gDialogOptionColorR;
extern int _downButton;
extern int dword_56DBB8;
extern int dword_56DBBC;
extern void* off_56DBC0;
extern void* off_56DBC4;
extern void* off_56DBC8;
extern void* off_56DBCC;
extern char* off_56DBC0;
extern char* off_56DBC4;
extern char* off_56DBC8;
extern char* off_56DBCC;
extern char* gDialogReplyTitle;
extern int _upButton;
extern int dword_56DBD8;
extern int dword_56DBDC;
extern void* off_56DBE0;
extern void* off_56DBE4;
extern void* off_56DBE8;
extern void* off_56DBEC;
extern char* off_56DBE0;
extern char* off_56DBE4;
extern char* off_56DBE8;
extern char* off_56DBEC;
STRUCT_56DAE0_FIELD_4* _getReply();
void _replyAddOption(const char* a1, const char* a2, int a3);
void _replyAddOptionProc(const char* a1, const char* a2, int a3);
void _replyAddOptionProc(const char* a1, int a2, int a3);
void _optionFree(STRUCT_56DAE0_FIELD_4_FIELD_C* a1);
void _replyFree();
int _endDialog();
@ -107,18 +110,21 @@ int _dialogGotoReply(const char* a1);
int dialogSetReplyTitle(const char* a1);
int _dialogReply(const char* a1, const char* a2);
int _dialogOption(const char* a1, const char* a2);
int _dialogOptionProc(const char* a1, const char* a2);
int _dialogOptionProc(const char* a1, int a2);
int sub_430FD4(const char* a1, const char* a2, int timeout);
int sub_431088(int a1);
int _dialogGetExitPoint();
int _dialogQuit();
int dialogSetOptionWindow(int a1, int a2, int a3, int a4, int a5);
int dialogSetReplyWindow(int a1, int a2, int a3, int a4, int a5);
int dialogSetOptionWindow(int a1, int a2, int a3, int a4, char* a5);
int dialogSetReplyWindow(int a1, int a2, int a3, int a4, char* a5);
int dialogSetBorder(int a1, int a2);
int _dialogSetScrollUp(int a1, int a2, void* a3, void* a4, void* a5, void* a6, int a7);
int _dialogSetScrollDown(int a1, int a2, void* a3, void* a4, void* a5, void* a6, int a7);
int _dialogSetScrollUp(int a1, int a2, char* a3, char* a4, char* a5, char* a6, int a7);
int _dialogSetScrollDown(int a1, int a2, char* a3, char* a4, char* a5, char* a6, int a7);
int dialogSetOptionSpacing(int value);
int dialogSetOptionColor(float a1, float a2, float a3);
int dialogSetReplyColor(float a1, float a2, float a3);
int _dialogSetOptionFlags(int flags);
void dialogInit();
void _dialogClose();
int _dialogGetDialogDepth();
void _dialogRegisterWinDrawCallbacks(DialogFunc1* a1, DialogFunc2* a2);

View File

@ -44,24 +44,19 @@ static void dictionaryFreeDefaultImpl(void* ptr)
}
// 0x4D9BA8
int dictionaryInit(Dictionary* dictionary, int initialCapacity, size_t valueSize, void* a4)
int dictionaryInit(Dictionary* dictionary, int initialCapacity, size_t valueSize, DictionaryIO* io)
{
dictionary->entriesCapacity = initialCapacity;
dictionary->valueSize = valueSize;
dictionary->entriesLength = 0;
if (a4 != NULL) {
// NOTE: There is some structure pointed by [a4] with 5 fields. They are
// either memcopied or assigned one by one into field_10 - field_20
// respectively. This parameter is always NULL, so I doubt it's possible
// to understand it's meaning. There are some hints in the unused
// functions though.
assert(false && "Not implemented");
if (io != NULL) {
memcpy(&(dictionary->io), io, sizeof(*io));
} else {
dictionary->field_10 = 0;
dictionary->field_14 = 0;
dictionary->field_18 = 0;
dictionary->field_1C = 0;
dictionary->io.readProc = NULL;
dictionary->io.writeProc = NULL;
dictionary->io.field_8 = 0;
dictionary->io.field_C = 0;
}
int rc = 0;
@ -302,6 +297,248 @@ int dictionaryRemoveValue(Dictionary* dictionary, const char* key)
return 0;
}
// NOTE: Unused.
//
// 0x4D9F84
int dictionaryCopy(Dictionary* dest, Dictionary* src)
{
if (src->marker != DICTIONARY_MARKER) {
return -1;
}
if (dictionaryInit(dest, src->entriesCapacity, src->valueSize, &(src->io)) != 0) {
// FIXME: Should return -1, as we were unable to initialize dictionary.
return 0;
}
for (int index = 0; index < src->entriesLength; index++) {
DictionaryEntry* entry = &(src->entries[index]);
if (dictionaryAddValue(dest, entry->key, entry->value) == -1) {
return -1;
}
}
return 0;
}
// NOTE: Unused.
//
// 0x4DA090
int dictionaryReadInt(FILE* stream, int* valuePtr)
{
int ch;
int value;
ch = fgetc(stream);
if (ch == -1) {
return -1;
}
value = (ch & 0xFF);
ch = fgetc(stream);
if (ch == -1) {
return -1;
}
value = (value << 8) | (ch & 0xFF);
ch = fgetc(stream);
if (ch == -1) {
return -1;
}
value = (value << 8) | (ch & 0xFF);
ch = fgetc(stream);
if (ch == -1) {
return -1;
}
value = (value << 8) | (ch & 0xFF);
*valuePtr = value;
return 0;
}
// NOTE: Unused.
//
// 0x4DA0F4
int dictionaryReadHeader(FILE* stream, Dictionary* dictionary)
{
int value;
if (dictionaryReadInt(stream, &value) != 0) return -1;
dictionary->entriesLength = value;
if (dictionaryReadInt(stream, &value) != 0) return -1;
dictionary->entriesCapacity = value;
if (dictionaryReadInt(stream, &value) != 0) return -1;
dictionary->valueSize = value;
// NOTE: Originally reads `values` pointer.
if (dictionaryReadInt(stream, &value) != 0) return -1;
return 0;
}
// NOTE: Unused.
//
// 0x4DA158
int dictionaryLoad(FILE* stream, Dictionary* dictionary, int a3)
{
if (dictionary->marker != DICTIONARY_MARKER) {
return -1;
}
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
if (entry->key != NULL) {
gDictionaryFreeProc(entry->key);
}
if (entry->value != NULL) {
gDictionaryFreeProc(entry->value);
}
}
if (dictionary->entries != NULL) {
gDictionaryFreeProc(dictionary->entries);
}
if (dictionaryReadHeader(stream, dictionary) != 0) {
return -1;
}
dictionary->entries = NULL;
if (dictionary->entriesCapacity <= 0) {
return 0;
}
dictionary->entries = (DictionaryEntry*)gDictionaryMallocProc(sizeof(*dictionary->entries) * dictionary->entriesCapacity);
if (dictionary->entries == NULL) {
return -1;
}
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
entry->key = NULL;
entry->value = NULL;
}
if (dictionary->entriesLength <= 0) {
return 0;
}
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
int keyLength = fgetc(stream);
if (keyLength == -1) {
return -1;
}
entry->key = (char*)gDictionaryMallocProc(keyLength + 1);
if (entry->key == NULL) {
return -1;
}
if (fgets(entry->key, keyLength, stream) == NULL) {
return -1;
}
if (dictionary->valueSize != 0) {
entry->value = gDictionaryMallocProc(dictionary->valueSize);
if (entry->value == NULL) {
return -1;
}
if (dictionary->io.readProc != NULL) {
if (dictionary->io.readProc(stream, entry->value, dictionary->valueSize, a3) != 0) {
return -1;
}
} else {
if (fread(entry->value, dictionary->valueSize, 1, stream) != 1) {
return -1;
}
}
}
}
return 0;
}
// NOTE: Unused.
//
// 0x4DA2EC
int dictionaryWriteInt(FILE* stream, int value)
{
if (fputc((value >> 24) & 0xFF, stream) == -1) return -1;
if (fputc((value >> 16) & 0xFF, stream) == -1) return -1;
if (fputc((value >> 8) & 0xFF, stream) == -1) return -1;
if (fputc(value & 0xFF, stream) == -1) return -1;
return 0;
}
// NOTE: Unused.
//
// 0x4DA360
int dictionaryWriteHeader(FILE* stream, Dictionary* dictionary)
{
if (dictionaryWriteInt(stream, dictionary->entriesLength) != 0) return -1;
if (dictionaryWriteInt(stream, dictionary->entriesCapacity) != 0) return -1;
if (dictionaryWriteInt(stream, dictionary->valueSize) != 0) return -1;
// NOTE: Originally writes `entries` pointer.
if (dictionaryWriteInt(stream, 0) != 0) return -1;
return 0;
}
// NOTE: Unused.
//
// 0x4DA3A4
int dictionaryWrite(FILE* stream, Dictionary* dictionary, int a3)
{
if (dictionary->marker != DICTIONARY_MARKER) {
return -1;
}
if (dictionaryWriteHeader(stream, dictionary) != 0) {
return -1;
}
for (int index = 0; index < dictionary->entriesLength; index++) {
DictionaryEntry* entry = &(dictionary->entries[index]);
int keyLength = strlen(entry->key);
if (fputc(keyLength, stream) == -1) {
return -1;
}
if (fputs(entry->key, stream) == -1) {
return -1;
}
if (dictionary->io.writeProc != NULL) {
if (dictionary->valueSize != 0) {
if (dictionary->io.writeProc(stream, entry->value, dictionary->valueSize, a3) != 0) {
return -1;
}
}
} else {
if (dictionary->valueSize != 0) {
if (fwrite(entry->value, dictionary->valueSize, 1, stream) != 1) {
return -1;
}
}
}
}
return 0;
}
// 0x4DA498
void dictionarySetMemoryProcs(MallocProc* mallocProc, ReallocProc* reallocProc, FreeProc* freeProc)
{

View File

@ -3,6 +3,20 @@
#include "memory_defs.h"
#include <stdio.h>
typedef int(DictionaryReadProc)(FILE* stream, void* buffer, unsigned int size, int a4);
typedef int(DictionaryWriteProc)(FILE* stream, void* buffer, unsigned int size, int a4);
// NOTE: Last unnamed fields are likely seek, tell, and filelength.
typedef struct DictionaryIO {
DictionaryReadProc* readProc;
DictionaryWriteProc* writeProc;
int field_8;
int field_C;
int field_10;
} DictionaryIO;
// A tuple containing individual key-value pair of a dictionary.
typedef struct DictionaryEntry {
char* key;
@ -27,22 +41,26 @@ typedef struct Dictionary {
// The size of the dictionary values in bytes.
size_t valueSize;
int field_10;
int field_14;
int field_18;
int field_1C;
int field_20;
// IO callbacks.
DictionaryIO io;
// The array of key-value pairs.
DictionaryEntry* entries;
} Dictionary;
int dictionaryInit(Dictionary* dictionary, int initialCapacity, size_t valueSize, void* a4);
int dictionaryInit(Dictionary* dictionary, int initialCapacity, size_t valueSize, DictionaryIO* io);
int dictionarySetCapacity(Dictionary* dictionary, int newCapacity);
int dictionaryFree(Dictionary* dictionary);
int dictionaryGetIndexByKey(Dictionary* dictionary, const char* key);
int dictionaryAddValue(Dictionary* dictionary, const char* key, const void* value);
int dictionaryRemoveValue(Dictionary* dictionary, const char* key);
int dictionaryCopy(Dictionary* dest, Dictionary* src);
int dictionaryReadInt(FILE* stream, int* valuePtr);
int dictionaryReadHeader(FILE* stream, Dictionary* dictionary);
int dictionaryLoad(FILE* stream, Dictionary* dictionary, int a3);
int dictionaryWriteInt(FILE* stream, int value);
int dictionaryWriteHeader(FILE* stream, Dictionary* dictionary);
int dictionaryWrite(FILE* stream, Dictionary* dictionary, int a3);
void dictionarySetMemoryProcs(MallocProc* mallocProc, ReallocProc* reallocProc, FreeProc* freeProc);
#endif /* DICTIONARY_H */

View File

@ -105,7 +105,7 @@ int displayMonitorInit()
}
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 16, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
Art* backgroundFrm = artLock(backgroundFid, &backgroundFrmHandle);
if (backgroundFrm == NULL) {
internal_free(gDisplayMonitorBackgroundFrmData);

View File

@ -1,7 +1,7 @@
#ifndef DRAW_H
#define DRAW_H
void bufferDrawLine(unsigned char* buf, int pitch, int left, int top, int right, int bottom, int color);
void bufferDrawLine(unsigned char* buf, int pitch, int left, int top, int right, int bottom, int color);
void bufferDrawRect(unsigned char* buf, int a2, int a3, int a4, int a5, int a6, int a7);
void bufferDrawRectShadowed(unsigned char* buf, int a2, int a3, int a4, int a5, int a6, int a7, int a8);
void blitBufferToBufferStretch(unsigned char* src, int srcWidth, int srcHeight, int srcPitch, unsigned char* dest, int destWidth, int destHeight, int destPitch);

View File

@ -503,7 +503,7 @@ static int elevatorWindowInit(int elevator)
int index;
for (index = 0; index < ELEVATOR_FRM_COUNT; index++) {
int fid = buildFid(6, gElevatorFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gElevatorFrmIds[index], 0, 0, 0);
gElevatorFrmData[index] = artLockFrameDataReturningSize(fid, &(gElevatorFrmHandles[index]), &(gElevatorFrmSizes[index].width), &(gElevatorFrmSizes[index].height));
if (gElevatorFrmData[index] == NULL) {
break;
@ -530,11 +530,11 @@ static int elevatorWindowInit(int elevator)
const ElevatorBackground* elevatorBackground = &(gElevatorBackgrounds[elevator]);
bool backgroundsLoaded = true;
int backgroundFid = buildFid(6, elevatorBackground->backgroundFrmId, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, elevatorBackground->backgroundFrmId, 0, 0, 0);
gElevatorBackgroundFrmData = artLockFrameDataReturningSize(backgroundFid, &gElevatorBackgroundFrmHandle, &gElevatorBackgroundFrmWidth, &gElevatorBackgroundFrmHeight);
if (gElevatorBackgroundFrmData != NULL) {
if (elevatorBackground->panelFrmId != -1) {
int panelFid = buildFid(6, elevatorBackground->panelFrmId, 0, 0, 0);
int panelFid = buildFid(OBJ_TYPE_INTERFACE, elevatorBackground->panelFrmId, 0, 0, 0);
gElevatorPanelFrmData = artLockFrameDataReturningSize(panelFid, &gElevatorPanelFrmHandle, &gElevatorPanelFrmWidth, &gElevatorPanelFrmHeight);
if (gElevatorPanelFrmData == NULL) {
gElevatorPanelFrmData = ELEVATOR_BACKGROUND_NULL;

View File

@ -217,7 +217,7 @@ void endgamePlaySlideshow()
if (ending->art_num == 327) {
endgameEndingRenderPanningScene(ending->direction, ending->voiceOverBaseName);
} else {
int fid = buildFid(6, ending->art_num, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, ending->art_num, 0, 0, 0);
endgameEndingRenderStaticScene(fid, ending->voiceOverBaseName);
}
}
@ -309,7 +309,7 @@ static int endgameEndingHandleContinuePlaying()
// 0x43FBDC
static void endgameEndingRenderPanningScene(int direction, const char* narratorFileName)
{
int fid = buildFid(6, 327, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 327, 0, 0, 0);
CacheEntry* backgroundHandle;
Art* background = artLock(fid, &backgroundHandle);
@ -441,7 +441,7 @@ static void endgameEndingRenderStaticScene(int fid, const char* narratorFileName
blitBufferToBuffer(backgroundData, ENDGAME_ENDING_WINDOW_WIDTH, ENDGAME_ENDING_WINDOW_HEIGHT, ENDGAME_ENDING_WINDOW_WIDTH, gEndgameEndingSlideshowWindowBuffer, ENDGAME_ENDING_WINDOW_WIDTH);
windowRefresh(gEndgameEndingSlideshowWindow);
endgameEndingLoadPalette((fid & 0xF000000) >> 24, fid & 0xFFF);
endgameEndingLoadPalette(FID_TYPE(fid), fid & 0xFFF);
endgameEndingVoiceOverInit(narratorFileName);
@ -746,23 +746,15 @@ static int endgameEndingSubtitlesLoad(const char* filePath)
char* pch;
// Find and clamp string at EOL.
pch = string;
while (*pch != '\0' && *pch != '\n') {
pch++;
}
if (*pch != '\0') {
pch = strchr(string, '\n');
if (pch != NULL) {
*pch = '\0';
}
// Find separator. The value before separator is ignored (as opposed to
// movie subtitles, where the value before separator is a timing).
pch = string;
while (*pch != '\0' && *pch != ':') {
pch++;
}
if (*pch != '\0') {
pch = strchr(string, ':');
if (pch != NULL) {
if (gEndgameEndingSubtitlesLength < ENDGAME_ENDING_MAX_SUBTITLES) {
gEndgameEndingSubtitles[gEndgameEndingSubtitlesLength] = internal_strdup(pch + 1);
gEndgameEndingSubtitlesLength++;

View File

@ -176,12 +176,11 @@ int externalVariableSetValue(Program* program, const char* name, ProgramValue& p
return 1;
}
if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) {
if ((exportedVariable->value.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 169
}
if ((programValue.opcode & 0xF7FF) == VALUE_TYPE_STRING) {
if ((programValue.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
if (program != NULL) {
const char* stringValue = programGetString(program, programValue.opcode, programValue.integerValue);
exportedVariable->value.opcode = VALUE_TYPE_DYNAMIC_STRING;
@ -204,7 +203,7 @@ int externalVariableGetValue(Program* program, const char* name, ProgramValue& v
return 1;
}
if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) {
if ((exportedVariable->value.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
value.opcode = exportedVariable->value.opcode;
value.integerValue = programPushString(program, exportedVariable->stringValue);
} else {
@ -225,7 +224,7 @@ int externalVariableCreate(Program* program, const char* identifier)
return 1;
}
if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) {
if ((exportedVariable->value.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 234
}
} else {
@ -261,7 +260,7 @@ void _removeProgramReferences(Program* program)
// 0x44152C
void _initExport()
{
_interpretRegisterProgramDeleteCallback(_removeProgramReferences);
intLibRegisterProgramDeleteCallback(_removeProgramReferences);
}
// 0x441538
@ -328,7 +327,7 @@ void _exportClearAllVariables()
for (int index = 0; index < 1013; index++) {
ExternalVariable* exportedVariable = &(gExternalVariables[index]);
if (exportedVariable->name[0] != '\0') {
if ((exportedVariable->value.opcode & 0xF7FF) == VALUE_TYPE_STRING) {
if ((exportedVariable->value.opcode & VALUE_TYPE_MASK) == VALUE_TYPE_STRING) {
if (exportedVariable->stringValue != NULL) {
internal_free_safe(exportedVariable->stringValue, __FILE__, __LINE__); // "..\\int\\EXPORT.C", 387
}

View File

@ -720,14 +720,14 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
case KEY_COMMA:
case KEY_LESS:
if (reg_anim_begin(0) == 0) {
reg_anim_rotate_counter_clockwise(gDude);
animationRegisterRotateCounterClockwise(gDude);
reg_anim_end();
}
break;
case KEY_DOT:
case KEY_GREATER:
if (reg_anim_begin(0) == 0) {
reg_anim_rotate_clockwise(gDude);
animationRegisterRotateClockwise(gDude);
reg_anim_end();
}
break;
@ -930,68 +930,56 @@ static int gameLoadGlobalVars()
}
// 0x443CE8
int globalVarsRead(const char* path, const char* section, int* out_vars_num, int** out_vars)
int globalVarsRead(const char* path, const char* section, int* variablesListLengthPtr, int** variablesListPtr)
{
File* stream;
char str[258];
char* ch;
_inven_reset_dude();
stream = fileOpen(path, "rt");
File* stream = fileOpen(path, "rt");
if (stream == NULL) {
return -1;
}
if (*out_vars_num != 0) {
internal_free(*out_vars);
*out_vars = NULL;
*out_vars_num = 0;
if (*variablesListLengthPtr != 0) {
internal_free(*variablesListPtr);
*variablesListPtr = NULL;
*variablesListLengthPtr = 0;
}
char string[260];
if (section != NULL) {
while (fileReadString(str, sizeof(str), stream)) {
if (strncmp(str, section, 16) == 0) {
while (fileReadString(string, 258, stream)) {
if (strncmp(string, section, 16) == 0) {
break;
}
}
}
while (fileReadString(str, sizeof(str), stream)) {
if (str[0] == '\n') {
while (fileReadString(string, 258, stream)) {
if (string[0] == '\n') {
continue;
}
if (str[0] == '/' && str[1] == '/') {
if (string[0] == '/' && string[1] == '/') {
continue;
}
ch = str;
while (*ch != '\0' && *ch != ';') {
ch++;
char* semicolon = strchr(string, ';');
if (semicolon != NULL) {
*semicolon = '\0';
}
if (*ch != '\0') {
*ch = '\0';
}
*variablesListLengthPtr = *variablesListLengthPtr + 1;
*variablesListPtr = (int*)internal_realloc(*variablesListPtr, sizeof(int) * *variablesListLengthPtr);
*out_vars_num = *out_vars_num + 1;
*out_vars = (int*)internal_realloc(*out_vars, sizeof(int) * *out_vars_num);
if (*out_vars == NULL) {
if (*variablesListPtr == NULL) {
exit(1);
}
ch = str;
while (*ch != '\0' && *ch != '=') {
ch++;
}
if (*ch != '\0') {
sscanf(ch + 1, "%d", *out_vars + *out_vars_num - 1);
char* equals = strchr(string, '=');
if (equals != NULL) {
sscanf(equals + 1, "%d", *variablesListPtr + *variablesListLengthPtr - 1);
} else {
*out_vars[*out_vars_num - 1] = 0;
*variablesListPtr[*variablesListLengthPtr - 1] = 0;
}
}
@ -1098,7 +1086,7 @@ static void showHelp()
if (win != -1) {
unsigned char* windowBuffer = windowGetBuffer(win);
if (windowBuffer != NULL) {
int backgroundFid = buildFid(6, 297, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 297, 0, 0, 0);
CacheEntry* backgroundHandle;
unsigned char* backgroundData = artLockFrameData(backgroundFid, 0, 0, &backgroundHandle);
if (backgroundData != NULL) {

View File

@ -22,7 +22,7 @@ void gameUiEnable();
bool gameUiIsDisabled();
int gameGetGlobalVar(int var);
int gameSetGlobalVar(int var, int value);
int globalVarsRead(const char* path, const char* section, int* out_vars_num, int** out_vars);
int globalVarsRead(const char* path, const char* section, int* variablesListLengthPtr, int** variablesListPtr);
int _game_state();
int _game_state_request(int a1);
void _game_state_update();

View File

@ -717,7 +717,7 @@ void gameDialogEnter(Object* a1, int a2)
return;
}
if ((a1->pid >> 24) != OBJ_TYPE_ITEM && (a1->sid >> 24) != SCRIPT_TYPE_SPATIAL) {
if (PID_TYPE(a1->pid) != OBJ_TYPE_ITEM && SID_TYPE(a1->sid) != SCRIPT_TYPE_SPATIAL) {
MessageListItem messageListItem;
int rc = _action_can_talk_to(gDude, a1);
@ -915,9 +915,9 @@ int _gdialogInitFromScript(int headFid, int reaction)
gGameDialogSpeakerIsPartyMember = objectIsPartyMember(gGameDialogSpeaker);
_oldFont = fontGetCurrent();
fontSetCurrent(101);
dialogSetReplyWindow(135, 225, 379, 58, 0);
dialogSetReplyWindow(135, 225, 379, 58, NULL);
dialogSetReplyColor(0.3f, 0.3f, 0.3f);
dialogSetOptionWindow(127, 335, 393, 117, 0);
dialogSetOptionWindow(127, 335, 393, 117, NULL);
dialogSetOptionColor(0.2f, 0.2f, 0.2f);
dialogSetReplyTitle(NULL);
_dialogRegisterWinDrawCallbacks(_demo_copy_title, _demo_copy_options);
@ -930,7 +930,7 @@ int _gdialogInitFromScript(int headFid, int reaction)
gameMouseSetCursor(MOUSE_CURSOR_ARROW);
textObjectsReset();
if ((gGameDialogSpeaker->pid >> 24) != OBJ_TYPE_ITEM) {
if (PID_TYPE(gGameDialogSpeaker->pid) != OBJ_TYPE_ITEM) {
_tile_scroll_to(gGameDialogSpeaker->tile, 2);
}
@ -970,7 +970,7 @@ int _gdialogExitFromScript()
dialogReviewEntriesClear();
tickersRemove(gameDialogTicker);
if (gGameDialogSpeaker->pid >> 24 != OBJ_TYPE_ITEM) {
if (PID_TYPE(gGameDialogSpeaker->pid) != OBJ_TYPE_ITEM) {
if (gGameDialogOldDudeTile != gDude->tile) {
gGameDialogOldCenterTile = gDude->tile;
}
@ -1298,7 +1298,7 @@ int gameDialogReviewWindowInit(int* win)
return -1;
}
int fid = buildFid(6, 102, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 102, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(fid, 0, 0, &_reviewBackKey);
if (backgroundFrmData == NULL) {
windowDestroy(*win);
@ -1318,10 +1318,10 @@ int gameDialogReviewWindowInit(int* win)
_reviewBackKey = INVALID_CACHE_ENTRY;
unsigned char* buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_COUNT];
int index;
for (index = 0; index < GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_COUNT; index++) {
int fid = buildFid(6, gGameDialogReviewWindowButtonFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameDialogReviewWindowButtonFrmIds[index], 0, 0, 0);
buttonFrmData[index] = artLockFrameData(fid, 0, 0, &(gGameDialogReviewWindowButtonFrmHandles[index]));
if (buttonFrmData[index] == NULL) {
break;
@ -1360,11 +1360,11 @@ int gameDialogReviewWindowInit(int* win)
gGameDialogReviewWindowButtonHeights[GAME_DIALOG_REVIEW_WINDOW_BUTTON_SCROLL_DOWN],
-1,
-1,
-1,
-1,
KEY_ARROW_DOWN,
buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_ARROW_DOWN_NORMAL],
buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_ARROW_DOWN_PRESSED],
NULL,
buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_ARROW_DOWN_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
if (downBtn == -1) {
gameDialogReviewWindowFree(win);
@ -1373,18 +1373,18 @@ int gameDialogReviewWindowInit(int* win)
buttonSetCallbacks(downBtn, _gsound_med_butt_press, _gsound_med_butt_release);
int doneBtn = buttonCreate(*win,
499,
398,
gGameDialogReviewWindowButtonWidths[GAME_DIALOG_REVIEW_WINDOW_BUTTON_DONE],
int doneBtn = buttonCreate(*win,
499,
398,
gGameDialogReviewWindowButtonWidths[GAME_DIALOG_REVIEW_WINDOW_BUTTON_DONE],
gGameDialogReviewWindowButtonHeights[GAME_DIALOG_REVIEW_WINDOW_BUTTON_DONE],
-1,
-1,
-1,
KEY_ESCAPE,
buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_DONE_NORMAL],
-1,
-1,
KEY_ESCAPE,
buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_DONE_NORMAL],
buttonFrmData[GAME_DIALOG_REVIEW_WINDOW_BUTTON_FRM_DONE_PRESSED],
NULL,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (doneBtn == -1) {
gameDialogReviewWindowFree(win);
@ -1399,7 +1399,7 @@ int gameDialogReviewWindowInit(int* win)
tickersRemove(gameDialogTicker);
int backgroundFid = buildFid(6, 102, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 102, 0, 0, 0);
gGameDialogReviewWindowBackgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &gGameDialogReviewWindowBackgroundFrmHandle);
if (gGameDialogReviewWindowBackgroundFrmData == NULL) {
gameDialogReviewWindowFree(win);
@ -1691,7 +1691,7 @@ int gameDialogSetReviewOptionText(const char* string)
// 0x446288
int _gdProcessInit()
{
int upBtn;
int upBtn;
int downBtn;
int optionsWindowX;
int optionsWindowY;
@ -1735,14 +1735,14 @@ int _gdProcessInit()
}
// di_rdbt2.frm - dialog red button down
fid = buildFid(6, 96, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 96, 0, 0, 0);
gGameDialogRedButtonUpFrmData = artLockFrameData(fid, 0, 0, &gGameDialogRedButtonUpFrmHandle);
if (gGameDialogRedButtonUpFrmData == NULL) {
goto err_3;
}
// di_rdbt1.frm - dialog red button up
fid = buildFid(6, 95, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 95, 0, 0, 0);
gGameDialogRedButtonDownFrmData = artLockFrameData(fid, 0, 0, &gGameDialogRedButtonDownFrmHandle);
if (gGameDialogRedButtonDownFrmData == NULL) {
goto err_3;
@ -3010,7 +3010,7 @@ int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4,
}
}
}
if (*end == ' ') {
*end = '\0';
}
@ -3127,7 +3127,7 @@ int _gdialog_barter_create_win()
frmId = 111;
}
int backgroundFid = buildFid(6, frmId, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
CacheEntry* backgroundHandle;
Art* backgroundFrm = artLock(backgroundFid, &backgroundHandle);
if (backgroundFrm == NULL) {
@ -3236,7 +3236,7 @@ void _gdialog_barter_destroy_win()
}
CacheEntry* backgroundFrmHandle;
int fid = buildFid(6, frmId, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData != NULL) {
unsigned char* windowBuffer = windowGetBuffer(gGameDialogWindow);
@ -3287,7 +3287,7 @@ void _gdialog_barter_cleanup_tables()
int partyMemberControlWindowInit()
{
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 390, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 390, 0, 0, 0);
Art* backgroundFrm = artLock(backgroundFid, &backgroundFrmHandle);
if (backgroundFrm == NULL) {
return -1;
@ -3359,7 +3359,7 @@ int partyMemberControlWindowInit()
GameDialogButtonData* buttonData = &(gGameDialogDispositionButtonsData[index]);
int fid;
fid = buildFid(6, buttonData->upFrmId, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, buttonData->upFrmId, 0, 0, 0);
Art* upButtonFrm = artLock(fid, &(buttonData->upFrmHandle));
if (upButtonFrm == NULL) {
partyMemberControlWindowFree();
@ -3370,7 +3370,7 @@ int partyMemberControlWindowInit()
int height = artGetHeight(upButtonFrm, 0, 0);
unsigned char* upButtonFrmData = artGetFrameData(upButtonFrm, 0, 0);
fid = buildFid(6, buttonData->downFrmId, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, buttonData->downFrmId, 0, 0, 0);
Art* downButtonFrm = artLock(fid, &(buttonData->downFrmHandle));
if (downButtonFrm == NULL) {
partyMemberControlWindowFree();
@ -3379,7 +3379,7 @@ int partyMemberControlWindowInit()
unsigned char* downButtonFrmData = artGetFrameData(downButtonFrm, 0, 0);
fid = buildFid(6, buttonData->disabledFrmId, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, buttonData->disabledFrmId, 0, 0, 0);
Art* disabledButtonFrm = artLock(fid, &(buttonData->disabledFrmHandle));
if (disabledButtonFrm == NULL) {
partyMemberControlWindowFree();
@ -3394,14 +3394,14 @@ int partyMemberControlWindowInit()
buttonData->x,
buttonData->y,
width,
height,
height,
-1,
-1,
buttonData->keyCode,
-1,
upButtonFrmData,
-1,
buttonData->keyCode,
-1,
upButtonFrmData,
downButtonFrmData,
NULL,
NULL,
BUTTON_FLAG_TRANSPARENT | BUTTON_FLAG_0x04 | BUTTON_FLAG_0x01);
if (_gdialog_buttons[v21] == -1) {
partyMemberControlWindowFree();
@ -3463,7 +3463,7 @@ void partyMemberControlWindowFree()
// control.frm - party member control interface
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 390, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 390, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData != NULL) {
_gdialog_scroll_subwin(gGameDialogWindow, 0, backgroundFrmData, windowGetBuffer(gGameDialogWindow), windowGetBuffer(gGameDialogBackgroundWindow) + (GAME_DIALOG_WINDOW_WIDTH) * (480 - _dialogue_subwin_len), _dialogue_subwin_len, 0);
@ -3484,7 +3484,7 @@ void partyMemberControlWindowUpdate()
int windowWidth = windowGetWidth(gGameDialogWindow);
CacheEntry* backgroundHandle;
int backgroundFid = buildFid(6, 390, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 390, 0, 0, 0);
Art* background = artLock(backgroundFid, &backgroundHandle);
if (background != NULL) {
int width = artGetWidth(background, 0, 0);
@ -3523,7 +3523,7 @@ void partyMemberControlWindowUpdate()
// Render preview.
CacheEntry* previewHandle;
int previewFid = buildFid((gGameDialogSpeaker->fid & 0xF000000) >> 24, gGameDialogSpeaker->fid & 0xFFF, ANIM_STAND, (gGameDialogSpeaker->fid & 0xF000) >> 12, ROTATION_SW);
int previewFid = buildFid(FID_TYPE(gGameDialogSpeaker->fid), gGameDialogSpeaker->fid & 0xFFF, ANIM_STAND, (gGameDialogSpeaker->fid & 0xF000) >> 12, ROTATION_SW);
Art* preview = artLock(previewFid, &previewHandle);
if (preview != NULL) {
int width = artGetWidth(preview, 0, ROTATION_SW);
@ -3603,7 +3603,7 @@ int _gdPickAIUpdateMsg(Object* critter)
// 0x449330
int _gdCanBarter()
{
if ((gGameDialogSpeaker->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(gGameDialogSpeaker->pid) != OBJ_TYPE_CRITTER) {
return 1;
}
@ -3612,7 +3612,7 @@ int _gdCanBarter()
return 1;
}
if (proto->critter.data.flags & 0x02) {
if (proto->critter.data.flags & CRITTER_FLAG_0x2) {
return 1;
}
@ -3724,7 +3724,7 @@ int partyMemberCustomizationWindowInit()
}
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 391, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 391, 0, 0, 0);
Art* backgroundFrm = artLock(backgroundFid, &backgroundFrmHandle);
if (backgroundFrm == NULL) {
return -1;
@ -3778,7 +3778,7 @@ int partyMemberCustomizationWindowInit()
for (int index = 0; index < PARTY_MEMBER_CUSTOMIZATION_OPTION_COUNT; index++) {
GameDialogButtonData* buttonData = &(_custom_button_info[index]);
int upButtonFid = buildFid(6, buttonData->upFrmId, 0, 0, 0);
int upButtonFid = buildFid(OBJ_TYPE_INTERFACE, buttonData->upFrmId, 0, 0, 0);
Art* upButtonFrm = artLock(upButtonFid, &(buttonData->upFrmHandle));
if (upButtonFrm == NULL) {
partyMemberCustomizationWindowFree();
@ -3789,7 +3789,7 @@ int partyMemberCustomizationWindowInit()
int height = artGetHeight(upButtonFrm, 0, 0);
unsigned char* upButtonFrmData = artGetFrameData(upButtonFrm, 0, 0);
int downButtonFid = buildFid(6, buttonData->downFrmId, 0, 0, 0);
int downButtonFid = buildFid(OBJ_TYPE_INTERFACE, buttonData->downFrmId, 0, 0, 0);
Art* downButtonFrm = artLock(downButtonFid, &(buttonData->downFrmHandle));
if (downButtonFrm == NULL) {
partyMemberCustomizationWindowFree();
@ -3867,7 +3867,7 @@ void partyMemberCustomizationWindowFree()
CacheEntry* backgroundFrmHandle;
// custom.frm - party member control interface
int fid = buildFid(6, 391, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 391, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData != NULL) {
_gdialog_scroll_subwin(gGameDialogWindow, 0, backgroundFrmData, windowGetBuffer(gGameDialogWindow), windowGetBuffer(gGameDialogBackgroundWindow) + (GAME_DIALOG_WINDOW_WIDTH) * (480 - _dialogue_subwin_len), _dialogue_subwin_len, 0);
@ -3917,7 +3917,7 @@ void partyMemberCustomizationWindowUpdate()
int windowWidth = windowGetWidth(gGameDialogWindow);
CacheEntry* backgroundHandle;
int backgroundFid = buildFid(6, 391, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 391, 0, 0, 0);
Art* background = artLock(backgroundFid, &backgroundHandle);
if (background == NULL) {
return;
@ -4025,7 +4025,7 @@ int _gdCustomSelect(int a1)
int oldFont = fontGetCurrent();
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 419, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 419, 0, 0, 0);
Art* backgroundFrm = artLock(backgroundFid, &backgroundFrmHandle);
if (backgroundFrm == NULL) {
return -1;
@ -4208,7 +4208,7 @@ void _gdCustomUpdateSetting(int option, int value)
// 0x44A52C
void gameDialogBarterButtonUpMouseUp(int btn, int keyCode)
{
if ((gGameDialogSpeaker->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(gGameDialogSpeaker->pid) != OBJ_TYPE_CRITTER) {
return;
}
@ -4219,7 +4219,7 @@ void gameDialogBarterButtonUpMouseUp(int btn, int keyCode)
Proto* proto;
protoGetProto(gGameDialogSpeaker->pid, &proto);
if (proto->critter.data.flags & 2) {
if (proto->critter.data.flags & CRITTER_FLAG_0x2) {
if (gGameDialogLipSyncStarted) {
if (soundIsPlaying(gLipsData.sound)) {
gameDialogEndLips();
@ -4269,7 +4269,7 @@ int _gdialog_window_create()
CacheEntry* backgroundFrmHandle;
// 389 - di_talkp.frm - dialog screen subwindow (party members)
// 99 - di_talk.frm - dialog screen subwindow (NPC's)
int backgroundFid = buildFid(6, gGameDialogSpeakerIsPartyMember ? 389 : 99, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, gGameDialogSpeakerIsPartyMember ? 389 : 99, 0, 0, 0);
Art* backgroundFrm = artLock(backgroundFid, &backgroundFrmHandle);
if (backgroundFrm == NULL) {
return -1;
@ -4306,11 +4306,11 @@ int _gdialog_window_create()
buttonSetCallbacks(_gdialog_buttons[0], _gsound_med_butt_press, _gsound_med_butt_release);
// di_rest1.frm - dialog rest button up
int upFid = buildFid(6, 97, 0, 0, 0);
int upFid = buildFid(OBJ_TYPE_INTERFACE, 97, 0, 0, 0);
unsigned char* reviewButtonUpData = artLockFrameData(upFid, 0, 0, &gGameDialogReviewButtonUpFrmHandle);
if (reviewButtonUpData != NULL) {
// di_rest2.frm - dialog rest button down
int downFid = buildFid(6, 98, 0, 0, 0);
int downFid = buildFid(OBJ_TYPE_INTERFACE, 98, 0, 0, 0);
unsigned char* reivewButtonDownData = artLockFrameData(downFid, 0, 0, &gGameDialogReviewButtonDownFrmHandle);
if (reivewButtonDownData != NULL) {
// REVIEW
@ -4386,7 +4386,7 @@ void _gdialog_window_destroy()
}
CacheEntry* backgroundFrmHandle;
int fid = buildFid(6, frmId, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData != NULL) {
unsigned char* windowBuffer = windowGetBuffer(gGameDialogWindow);
@ -4403,7 +4403,7 @@ int gameDialogWindowRenderBackground()
{
CacheEntry* backgroundFrmHandle;
// alltlk.frm - dialog screen background
int fid = buildFid(6, 103, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 103, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData == NULL) {
return -1;
@ -4434,7 +4434,7 @@ int _talkToRefreshDialogWindowRect(Rect* rect)
}
CacheEntry* backgroundFrmHandle;
int fid = buildFid(6, frmId, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData == NULL) {
return -1;
@ -4550,7 +4550,7 @@ void gameDialogRenderTalkingHead(Art* headFrm, int frame)
unsigned char* src = windowGetBuffer(gIsoWindow);
// Usually rendering functions use `screenGetWidth`/`screenGetHeight` to
// determine rendering position. However in this case `windowGetHeight`
// determine rendering position. However in this case `windowGetHeight`
// is a must because isometric window's height can either include
// interface bar or not. Offset is updated accordingly (332 -> 232, the
// missing 100 is interface bar height, which is already accounted for
@ -4612,13 +4612,13 @@ void gameDialogPrepareHighlights()
_dark_BlendTable = _getColorBlendTable(_colorTable[22187]);
// hilight1.frm - dialogue upper hilight
int upperHighlightFid = buildFid(6, 115, 0, 0, 0);
int upperHighlightFid = buildFid(OBJ_TYPE_INTERFACE, 115, 0, 0, 0);
gGameDialogUpperHighlightFrm = artLock(upperHighlightFid, &gGameDialogUpperHighlightFrmHandle);
gGameDialogUpperHighlightFrmWidth = artGetWidth(gGameDialogUpperHighlightFrm, 0, 0);
gGameDialogUpperHighlightFrmHeight = artGetHeight(gGameDialogUpperHighlightFrm, 0, 0);
// hilight2.frm - dialogue lower hilight
int lowerHighlightFid = buildFid(6, 116, 0, 0, 0);
int lowerHighlightFid = buildFid(OBJ_TYPE_INTERFACE, 116, 0, 0, 0);
gGameDialogLowerHighlightFrm = artLock(lowerHighlightFid, &gGameDialogLowerHighlightFrmHandle);
gGameDialogLowerHighlightFrmWidth = artGetWidth(gGameDialogLowerHighlightFrm, 0, 0);
gGameDialogLowerHighlightFrmHeight = artGetHeight(gGameDialogLowerHighlightFrm, 0, 0);

View File

@ -648,7 +648,7 @@ void gameMouseRefresh()
if (pointedObject != NULL) {
int primaryAction = -1;
switch ((pointedObject->fid & 0xF000000) >> 24) {
switch (FID_TYPE(pointedObject->fid)) {
case OBJ_TYPE_ITEM:
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_USE;
if (gGameMouseItemHighlightEnabled) {
@ -670,7 +670,7 @@ void gameMouseRefresh()
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_TALK;
}
} else {
if (_critter_flag_check(pointedObject->pid, 32)) {
if (_critter_flag_check(pointedObject->pid, CRITTER_FLAG_0x20)) {
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_LOOK;
} else {
primaryAction = GAME_MOUSE_ACTION_MENU_ITEM_USE;
@ -693,7 +693,7 @@ void gameMouseRefresh()
if (primaryAction != -1) {
if (gameMouseRenderPrimaryAction(mouseX, mouseY, primaryAction, _scr_size.right - _scr_size.left + 1, _scr_size.bottom - _scr_size.top - 99) == 0) {
Rect tmp;
int fid = buildFid(6, 282, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 282, 0, 0, 0);
if (objectSetFid(gGameMouseHexCursor, fid, &tmp) == 0) {
tileWindowRefreshRect(&tmp, gElevation);
}
@ -715,7 +715,7 @@ void gameMouseRefresh()
}
if (pointedObject != NULL) {
bool pointedObjectIsCritter = (pointedObject->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER;
bool pointedObjectIsCritter = FID_TYPE(pointedObject->fid) == OBJ_TYPE_CRITTER;
int combatLooks = 0;
configGetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_COMBAT_LOOKS_KEY, &combatLooks);
@ -756,7 +756,7 @@ void gameMouseRefresh()
if (gameMouseRenderAccuracy(formattedAccuracy, color) == 0) {
Rect tmp;
int fid = buildFid(6, 284, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 284, 0, 0, 0);
if (objectSetFid(gGameMouseHexCursor, fid, &tmp) == 0) {
tileWindowRefreshRect(&tmp, gElevation);
}
@ -825,7 +825,7 @@ void gameMouseRefresh()
gGameMouseLastY = mouseY;
if (!_gmouse_mapper_mode) {
int fid = buildFid(6, 0, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 0, 0, 0, 0);
gameMouseSetBouncingCursorFid(fid);
}
@ -936,13 +936,13 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
if (gGameMouseMode == GAME_MOUSE_MODE_ARROW) {
Object* v5 = gameMouseGetObjectUnderCursor(-1, true, gElevation);
if (v5 != NULL) {
switch ((v5->fid & 0xF000000) >> 24) {
switch (FID_TYPE(v5->fid)) {
case OBJ_TYPE_ITEM:
actionPickUp(gDude, v5);
break;
case OBJ_TYPE_CRITTER:
if (v5 == gDude) {
if (((gDude->fid & 0xFF0000) >> 16) == ANIM_STAND) {
if (FID_ANIM_TYPE(gDude->fid) == ANIM_STAND) {
Rect a1;
if (objectRotateClockwise(v5, &a1) == 0) {
tileWindowRefreshRect(&a1, v5->elevation);
@ -1053,7 +1053,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
if (v16 != NULL) {
int actionMenuItemsCount = 0;
int actionMenuItems[6];
switch ((v16->fid & 0xF000000) >> 24) {
switch (FID_TYPE(v16->fid)) {
case OBJ_TYPE_ITEM:
actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE;
actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_LOOK;
@ -1072,7 +1072,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_TALK;
}
} else {
if (!_critter_flag_check(v16->pid, 32)) {
if (!_critter_flag_check(v16->pid, CRITTER_FLAG_0x20)) {
actionMenuItems[actionMenuItemsCount++] = GAME_MOUSE_ACTION_MENU_ITEM_USE;
}
}
@ -1108,7 +1108,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
if (gameMouseRenderActionMenuItems(mouseX, mouseY, actionMenuItems, actionMenuItemsCount, _scr_size.right - _scr_size.left + 1, _scr_size.bottom - _scr_size.top - 99) == 0) {
Rect v43;
int fid = buildFid(6, 283, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 283, 0, 0, 0);
if (objectSetFid(gGameMouseHexCursor, fid, &v43) == 0 && _gmouse_3d_move_to(mouseX, mouseY, gElevation, &v43) == 0) {
tileWindowRefreshRect(&v43, gElevation);
isoDisable();
@ -1171,7 +1171,7 @@ void _gmouse_handle_event(int mouseX, int mouseY, int mouseState)
actionTalk(gDude, v16);
break;
case GAME_MOUSE_ACTION_MENU_ITEM_USE:
switch ((v16->fid & 0xF000000) >> 24) {
switch (FID_TYPE(v16->fid)) {
case OBJ_TYPE_SCENERY:
_action_use_an_object(gDude, v16);
break;
@ -1242,7 +1242,7 @@ int gameMouseSetCursor(int cursor)
}
CacheEntry* mouseCursorFrmHandle;
int fid = buildFid(6, gGameMouseCursorFrmIds[cursor], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseCursorFrmIds[cursor], 0, 0, 0);
Art* mouseCursorFrm = artLock(fid, &mouseCursorFrmHandle);
if (mouseCursorFrm == NULL) {
return -1;
@ -1327,10 +1327,10 @@ void gameMouseSetMode(int mode)
return;
}
int fid = buildFid(6, 0, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 0, 0, 0, 0);
gameMouseSetBouncingCursorFid(fid);
fid = buildFid(6, gGameMouseModeFrmIds[mode], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[mode], 0, 0, 0);
Rect rect;
if (objectSetFid(gGameMouseHexCursor, fid, &rect) == -1) {
@ -1472,7 +1472,7 @@ int gameMouseSetBouncingCursorFid(int fid)
// 0x44CD0C
void gameMouseResetBouncingCursorFid()
{
int fid = buildFid(6, 0, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 0, 0, 0, 0);
gameMouseSetBouncingCursorFid(fid);
}
@ -1601,7 +1601,7 @@ Object* gameMouseGetObjectUnderCursor(int objectType, bool a2, int elevation)
v4 = ptr->object;
if ((ptr->flags & 0x01) != 0) {
if ((ptr->flags & 0x04) == 0) {
if ((ptr->object->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER || (ptr->object->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_DEAD)) == 0) {
if (FID_TYPE(ptr->object->fid) != OBJ_TYPE_CRITTER || (ptr->object->data.critter.combat.results & (DAM_KNOCKED_OUT | DAM_DEAD)) == 0) {
break;
}
}
@ -1620,14 +1620,14 @@ Object* gameMouseGetObjectUnderCursor(int objectType, bool a2, int elevation)
int gameMouseRenderPrimaryAction(int x, int y, int menuItem, int width, int height)
{
CacheEntry* menuItemFrmHandle;
int menuItemFid = buildFid(6, gGameMouseActionMenuItemFrmIds[menuItem], 0, 0, 0);
int menuItemFid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseActionMenuItemFrmIds[menuItem], 0, 0, 0);
Art* menuItemFrm = artLock(menuItemFid, &menuItemFrmHandle);
if (menuItemFrm == NULL) {
return -1;
}
CacheEntry* arrowFrmHandle;
int arrowFid = buildFid(6, gGameMouseModeFrmIds[GAME_MOUSE_MODE_ARROW], 0, 0, 0);
int arrowFid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[GAME_MOUSE_MODE_ARROW], 0, 0, 0);
Art* arrowFrm = artLock(arrowFid, &arrowFrmHandle);
if (arrowFrm == NULL) {
artUnlock(menuItemFrmHandle);
@ -1666,7 +1666,7 @@ int gameMouseRenderPrimaryAction(int x, int y, int menuItem, int width, int heig
} else {
artUnlock(arrowFrmHandle);
arrowFid = buildFid(6, 285, 0, 0, 0);
arrowFid = buildFid(OBJ_TYPE_INTERFACE, 285, 0, 0, 0);
arrowFrm = artLock(arrowFid, &arrowFrmHandle);
arrowFrmData = artGetFrameData(arrowFrm, 0, 0);
arrowFrmDest += menuItemFrmWidth;
@ -1725,7 +1725,7 @@ int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuI
frmId -= 1;
}
int fid = buildFid(6, frmId, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
menuItemFrms[index] = artLock(fid, &(menuItemFrmHandles[index]));
if (menuItemFrms[index] == NULL) {
@ -1736,7 +1736,7 @@ int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuI
}
}
int fid = buildFid(6, gGameMouseModeFrmIds[GAME_MOUSE_MODE_ARROW], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[GAME_MOUSE_MODE_ARROW], 0, 0, 0);
CacheEntry* arrowFrmHandle;
Art* arrowFrm = artLock(fid, &arrowFrmHandle);
if (arrowFrm == NULL) {
@ -1772,7 +1772,7 @@ int gameMouseRenderActionMenuItems(int x, int y, const int* menuItems, int menuI
}
} else {
// Mirrored arrow (from left to right).
fid = buildFid(6, 285, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 285, 0, 0, 0);
arrowFrm = artLock(fid, &arrowFrmHandle);
arrowData = artGetFrameData(arrowFrm, 0, 0);
gGameMouseActionMenuFrm->xOffsets[0] = -gGameMouseActionMenuFrm->xOffsets[0];
@ -1820,7 +1820,7 @@ int gameMouseHighlightActionMenuItemAtIndex(int menuItemIndex)
}
CacheEntry* handle;
int fid = buildFid(6, gGameMouseActionMenuItemFrmIds[gGameMouseActionMenuItems[gGameMouseActionMenuHighlightedItemIndex]], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseActionMenuItemFrmIds[gGameMouseActionMenuItems[gGameMouseActionMenuHighlightedItemIndex]], 0, 0, 0);
Art* art = artLock(fid, &handle);
if (art == NULL) {
return -1;
@ -1832,7 +1832,7 @@ int gameMouseHighlightActionMenuItemAtIndex(int menuItemIndex)
blitBufferToBuffer(data, width, height, width, _gmouse_3d_menu_actions_start + gGameMouseActionMenuFrmWidth * height * gGameMouseActionMenuHighlightedItemIndex, gGameMouseActionMenuFrmWidth);
artUnlock(handle);
fid = buildFid(6, gGameMouseActionMenuItemFrmIds[gGameMouseActionMenuItems[menuItemIndex]] - 1, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseActionMenuItemFrmIds[gGameMouseActionMenuItems[menuItemIndex]] - 1, 0, 0, 0);
art = artLock(fid, &handle);
if (art == NULL) {
return -1;
@ -1851,7 +1851,7 @@ int gameMouseHighlightActionMenuItemAtIndex(int menuItemIndex)
int gameMouseRenderAccuracy(const char* string, int color)
{
CacheEntry* crosshairFrmHandle;
int fid = buildFid(6, gGameMouseModeFrmIds[GAME_MOUSE_MODE_CROSSHAIR], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[GAME_MOUSE_MODE_CROSSHAIR], 0, 0, 0);
Art* crosshairFrm = artLock(fid, &crosshairFrmHandle);
if (crosshairFrm == NULL) {
return -1;
@ -1910,7 +1910,7 @@ int gameMouseRenderActionPoints(const char* string, int color)
fontSetCurrent(oldFont);
int fid = buildFid(6, 1, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 1, 0, 0, 0);
gameMouseSetBouncingCursorFid(fid);
return 0;
@ -1934,12 +1934,12 @@ int gameMouseObjectsInit()
return -1;
}
fid = buildFid(6, 0, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 0, 0, 0, 0);
if (objectCreateWithFidPid(&gGameMouseBouncingCursor, fid, -1) != 0) {
return -1;
}
fid = buildFid(6, 1, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 1, 0, 0, 0);
if (objectCreateWithFidPid(&gGameMouseHexCursor, fid, -1) != 0) {
return -1;
}
@ -2031,35 +2031,35 @@ int gameMouseActionMenuInit()
int fid;
// actmenu.frm - action menu
fid = buildFid(6, 283, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 283, 0, 0, 0);
gGameMouseActionMenuFrm = artLock(fid, &gGameMouseActionMenuFrmHandle);
if (gGameMouseActionMenuFrm == NULL) {
goto err;
}
// actpick.frm - action pick
fid = buildFid(6, 282, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 282, 0, 0, 0);
gGameMouseActionPickFrm = artLock(fid, &gGameMouseActionPickFrmHandle);
if (gGameMouseActionPickFrm == NULL) {
goto err;
}
// acttohit.frm - action to hit
fid = buildFid(6, 284, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 284, 0, 0, 0);
gGameMouseActionHitFrm = artLock(fid, &gGameMouseActionHitFrmHandle);
if (gGameMouseActionHitFrm == NULL) {
goto err;
}
// blank.frm - used be mset000.frm for top of bouncing mouse cursor
fid = buildFid(6, 0, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 0, 0, 0, 0);
gGameMouseBouncingCursorFrm = artLock(fid, &gGameMouseBouncingCursorFrmHandle);
if (gGameMouseBouncingCursorFrm == NULL) {
goto err;
}
// msef000.frm - hex mouse cursor
fid = buildFid(6, 1, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 1, 0, 0, 0);
gGameMouseHexCursorFrm = artLock(fid, &gGameMouseHexCursorFrmHandle);
if (gGameMouseHexCursorFrm == NULL) {
goto err;
@ -2145,7 +2145,7 @@ void gameMouseActionMenuFree()
// 0x44DF40
int gameMouseUpdateHexCursorFid(Rect* rect)
{
int fid = buildFid(6, gGameMouseModeFrmIds[gGameMouseMode], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[gGameMouseMode], 0, 0, 0);
if (gGameMouseHexCursor->fid == fid) {
return -1;
}
@ -2210,7 +2210,7 @@ int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4)
int y1 = 0;
int fid = gGameMouseBouncingCursor->fid;
if ((fid & 0xF000000) >> 24 == OBJ_TYPE_TILE) {
if (FID_TYPE(fid) == OBJ_TYPE_TILE) {
int squareTile = squareTileFromScreenXY(x, y, elevation);
if (squareTile == -1) {
tile = HEX_GRID_WIDTH * (2 * (squareTile / SQUARE_GRID_WIDTH) + 1) + 2 * (squareTile % SQUARE_GRID_WIDTH) + 1;
@ -2398,7 +2398,7 @@ int objectIsDoor(Object* object)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_SCENERY) {
if (PID_TYPE(object->pid) != OBJ_TYPE_SCENERY) {
return false;
}

View File

@ -176,7 +176,7 @@ int gameMoviePlay(int movie, int flags)
int gameMovieWindowY = (screenGetHeight() - GAME_MOVIE_WINDOW_HEIGHT) / 2;
int win = windowCreate(gameMovieWindowX,
gameMovieWindowY,
GAME_MOVIE_WINDOW_WIDTH,
GAME_MOVIE_WINDOW_WIDTH,
GAME_MOVIE_WINDOW_HEIGHT,
0,
WINDOW_FLAG_0x10);

View File

@ -1118,7 +1118,7 @@ Sound* soundEffectLoad(const char* name, Object* object)
}
if (object != NULL) {
if ((object->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER && (name[0] == 'H' || name[0] == 'N')) {
if (FID_TYPE(object->fid) == OBJ_TYPE_CRITTER && (name[0] == 'H' || name[0] == 'N')) {
char v9 = name[1];
if (v9 == 'A' || v9 == 'F' || v9 == 'M') {
if (v9 == 'A') {
@ -1230,7 +1230,7 @@ void soundEffectDelete(Sound* sound)
}
// 0x4514F0
int _gsnd_anim_sound(Sound* sound)
int _gsnd_anim_sound(Sound* sound, void* a2)
{
if (!gGameSoundInitialized) {
return 0;
@ -1287,7 +1287,7 @@ int _gsound_compute_relative_volume(Object* obj)
v3 = 0x7FFF;
if (obj) {
type = (obj->fid & 0xF000000) >> 24;
type = FID_TYPE(obj->fid);
if (type == 0 || type == 1 || type == 2) {
v7 = objectGetOwner(obj);
if (!v7) {
@ -1325,7 +1325,7 @@ char* sfxBuildCharName(Object* a1, int anim, int extra)
char v8;
char v9;
if (artCopyFileName((a1->fid & 0xF000000) >> 24, a1->fid & 0xFFF, v7) == -1) {
if (artCopyFileName(FID_TYPE(a1->fid), a1->fid & 0xFFF, v7) == -1) {
return NULL;
}
@ -1399,12 +1399,10 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
v6 = 1;
}
int damageType = weaponGetDamageType(NULL, weapon);
// TODO: Check damageType conditions.
if (effectTypeCode != 'H' || target == NULL || damageType == DAMAGE_TYPE_EXPLOSION || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP) {
if (effectTypeCode != 'H' || target == NULL || weaponIsGrenade(weapon)) {
materialCode = 'X';
} else {
const int type = (target->fid & 0xF000000) >> 24;
const int type = FID_TYPE(target->fid);
int material;
switch (type) {
case OBJ_TYPE_ITEM:
@ -1466,7 +1464,7 @@ char* sfxBuildSceneryName(int actionType, int action, const char* name)
// 0x4518D
char* sfxBuildOpenName(Object* object, int action)
{
if ((object->fid & 0xF000000) >> 24 == OBJ_TYPE_SCENERY) {
if (FID_TYPE(object->fid) == OBJ_TYPE_SCENERY) {
char scenerySoundId;
Proto* proto;
if (protoGetProto(object->pid, &proto) != -1) {

View File

@ -63,7 +63,7 @@ int _gsound_play_sfx_file_volume(const char* a1, int a2);
Sound* soundEffectLoad(const char* name, Object* a2);
Sound* soundEffectLoadWithVolume(const char* a1, Object* a2, int a3);
void soundEffectDelete(Sound* a1);
int _gsnd_anim_sound(Sound* a1);
int _gsnd_anim_sound(Sound* sound, void* a2);
int soundEffectPlay(Sound* a1);
int _gsound_compute_relative_volume(Object* obj);
char* sfxBuildCharName(Object* a1, int anim, int extra);

View File

@ -438,7 +438,7 @@ int interfaceInit()
goto err;
}
fid = buildFid(6, 16, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData == NULL) {
goto err;
@ -447,13 +447,13 @@ int interfaceInit()
blitBufferToBuffer(backgroundFrmData, INTERFACE_BAR_WIDTH, INTERFACE_BAR_HEIGHT - 1, INTERFACE_BAR_WIDTH, gInterfaceWindowBuffer, 640);
artUnlock(backgroundFrmHandle);
fid = buildFid(6, 47, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 47, 0, 0, 0);
gInventoryButtonUpFrmData = artLockFrameData(fid, 0, 0, &gInventoryButtonUpFrmHandle);
if (gInventoryButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 46, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 46, 0, 0, 0);
gInventoryButtonDownFrmData = artLockFrameData(fid, 0, 0, &gInventoryButtonDownFrmHandle);
if (gInventoryButtonDownFrmData == NULL) {
goto err;
@ -466,13 +466,13 @@ int interfaceInit()
buttonSetCallbacks(gInventoryButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 18, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 18, 0, 0, 0);
gOptionsButtonUpFrmData = artLockFrameData(fid, 0, 0, &gOptionsButtonUpFrmHandle);
if (gOptionsButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 17, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 17, 0, 0, 0);
gOptionsButtonDownFrmData = artLockFrameData(fid, 0, 0, &gOptionsButtonDownFrmHandle);
if (gOptionsButtonDownFrmData == NULL) {
goto err;
@ -485,19 +485,19 @@ int interfaceInit()
buttonSetCallbacks(gOptionsButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 6, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gSkilldexButtonUpFrmData = artLockFrameData(fid, 0, 0, &gSkilldexButtonUpFrmHandle);
if (gSkilldexButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 7, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 7, 0, 0, 0);
gSkilldexButtonDownFrmData = artLockFrameData(fid, 0, 0, &gSkilldexButtonDownFrmHandle);
if (gSkilldexButtonDownFrmData == NULL) {
goto err;
}
fid = buildFid(6, 6, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gSkilldexButtonMaskFrmData = artLockFrameData(fid, 0, 0, &gSkilldexButtonMaskFrmHandle);
if (gSkilldexButtonMaskFrmData == NULL) {
goto err;
@ -511,19 +511,19 @@ int interfaceInit()
buttonSetMask(gSkilldexButton, gSkilldexButtonMaskFrmData);
buttonSetCallbacks(gSkilldexButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 13, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 13, 0, 0, 0);
gMapButtonUpFrmData = artLockFrameData(fid, 0, 0, &gMapButtonUpFrmHandle);
if (gMapButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 10, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 10, 0, 0, 0);
gMapButtonDownFrmData = artLockFrameData(fid, 0, 0, &gMapButtonDownFrmHandle);
if (gMapButtonDownFrmData == NULL) {
goto err;
}
fid = buildFid(6, 13, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 13, 0, 0, 0);
gMapButtonMaskFrmData = artLockFrameData(fid, 0, 0, &gMapButtonMaskFrmHandle);
if (gMapButtonMaskFrmData == NULL) {
goto err;
@ -537,13 +537,13 @@ int interfaceInit()
buttonSetMask(gMapButton, gMapButtonMaskFrmData);
buttonSetCallbacks(gMapButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 59, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 59, 0, 0, 0);
gPipboyButtonUpFrmData = artLockFrameData(fid, 0, 0, &gPipboyButtonUpFrmHandle);
if (gPipboyButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 58, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 58, 0, 0, 0);
gPipboyButtonDownFrmData = artLockFrameData(fid, 0, 0, &gPipboyButtonDownFrmHandle);
if (gPipboyButtonDownFrmData == NULL) {
goto err;
@ -557,13 +557,13 @@ int interfaceInit()
buttonSetMask(gPipboyButton, gMapButtonMaskFrmData);
buttonSetCallbacks(gPipboyButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 57, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 57, 0, 0, 0);
gCharacterButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterButtonUpFrmHandle);
if (gCharacterButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 56, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 56, 0, 0, 0);
gCharacterButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterButtonDownFrmHandle);
if (gCharacterButtonDownFrmData == NULL) {
goto err;
@ -577,19 +577,19 @@ int interfaceInit()
buttonSetMask(gCharacterButton, gMapButtonMaskFrmData);
buttonSetCallbacks(gCharacterButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 32, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 32, 0, 0, 0);
gSingleAttackButtonUpData = artLockFrameData(fid, 0, 0, &gSingleAttackButtonUpHandle);
if (gSingleAttackButtonUpData == NULL) {
goto err;
}
fid = buildFid(6, 31, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 31, 0, 0, 0);
gSingleAttackButtonDownData = artLockFrameData(fid, 0, 0, &gSingleAttackButtonDownHandle);
if (gSingleAttackButtonDownData == NULL) {
goto err;
}
fid = buildFid(6, 73, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 73, 0, 0, 0);
_itemButtonDisabled = artLockFrameData(fid, 0, 0, &_itemButtonDisabledKey);
if (_itemButtonDisabled == NULL) {
goto err;
@ -606,19 +606,19 @@ int interfaceInit()
buttonSetRightMouseCallbacks(gSingleAttackButton, -1, KEY_LOWERCASE_N, NULL, NULL);
buttonSetCallbacks(gSingleAttackButton, _gsound_lrg_butt_press, _gsound_lrg_butt_release);
fid = buildFid(6, 6, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gChangeHandsButtonUpFrmData = artLockFrameData(fid, 0, 0, &gChangeHandsButtonUpFrmHandle);
if (gChangeHandsButtonUpFrmData == NULL) {
goto err;
}
fid = buildFid(6, 7, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 7, 0, 0, 0);
gChangeHandsButtonDownFrmData = artLockFrameData(fid, 0, 0, &gChangeHandsButtonDownFrmHandle);
if (gChangeHandsButtonDownFrmData == NULL) {
goto err;
}
fid = buildFid(6, 6, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gChangeHandsButtonMaskFrmData = artLockFrameData(fid, 0, 0, &gChangeHandsButtonMaskFrmHandle);
if (gChangeHandsButtonMaskFrmData == NULL) {
goto err;
@ -633,25 +633,25 @@ int interfaceInit()
buttonSetMask(gChangeHandsButton, gChangeHandsButtonMaskFrmData);
buttonSetCallbacks(gChangeHandsButton, _gsound_med_butt_press, _gsound_med_butt_release);
fid = buildFid(6, 82, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 82, 0, 0, 0);
gNumbersFrmData = artLockFrameData(fid, 0, 0, &gNumbersFrmHandle);
if (gNumbersFrmData == NULL) {
goto err;
}
fid = buildFid(6, 83, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 83, 0, 0, 0);
gGreenLightFrmData = artLockFrameData(fid, 0, 0, &gGreenLightFrmHandle);
if (gGreenLightFrmData == NULL) {
goto err;
}
fid = buildFid(6, 84, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 84, 0, 0, 0);
gYellowLightFrmData = artLockFrameData(fid, 0, 0, &gYellowLightFrmHandle);
if (gYellowLightFrmData == NULL) {
goto err;
}
fid = buildFid(6, 85, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 85, 0, 0, 0);
gRedLightFrmData = artLockFrameData(fid, 0, 0, &gRedLightFrmHandle);
if (gRedLightFrmData == NULL) {
goto err;
@ -1592,7 +1592,7 @@ void interfaceBarEndButtonsShow(bool animated)
return;
}
int fid = buildFid(6, 104, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 104, 0, 0, 0);
CacheEntry* handle;
Art* art = artLock(fid, &handle);
if (art == NULL) {
@ -1644,7 +1644,7 @@ void interfaceBarEndButtonsHide(bool animated)
return;
}
int fid = buildFid(6, 104, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 104, 0, 0, 0);
CacheEntry* handle;
Art* art = artLock(fid, &handle);
if (art == NULL) {
@ -1693,7 +1693,7 @@ void interfaceBarEndButtonsRenderGreenLights()
buttonEnable(gEndCombatButton);
// endltgrn.frm - green lights around end turn/combat window
int lightsFid = buildFid(6, 109, 0, 0, 0);
int lightsFid = buildFid(OBJ_TYPE_INTERFACE, 109, 0, 0, 0);
CacheEntry* lightsFrmHandle;
unsigned char* lightsFrmData = artLockFrameData(lightsFid, 0, 0, &lightsFrmHandle);
if (lightsFrmData == NULL) {
@ -1717,7 +1717,7 @@ void interfaceBarEndButtonsRenderRedLights()
CacheEntry* lightsFrmHandle;
// endltred.frm - red lights around end turn/combat window
int lightsFid = buildFid(6, 110, 0, 0, 0);
int lightsFid = buildFid(OBJ_TYPE_INTERFACE, 110, 0, 0, 0);
unsigned char* lightsFrmData = artLockFrameData(lightsFid, 0, 0, &lightsFrmHandle);
if (lightsFrmData == NULL) {
return;
@ -1751,10 +1751,10 @@ static int interfaceBarRefreshMainAction()
int fid;
if (_proto_action_can_use_on(itemState->item->pid)) {
// USE ON
fid = buildFid(6, 294, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 294, 0, 0, 0);
} else if (_obj_action_can_use(itemState->item)) {
// USE
fid = buildFid(6, 292, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 292, 0, 0, 0);
} else {
fid = -1;
}
@ -1782,20 +1782,20 @@ static int interfaceBarRefreshMainAction()
// jump table.
switch (itemState->action) {
case INTERFACE_ITEM_ACTION_PRIMARY_AIMING:
bullseyeFid = buildFid(6, 288, 0, 0, 0);
bullseyeFid = buildFid(OBJ_TYPE_INTERFACE, 288, 0, 0, 0);
// FALLTHROUGH
case INTERFACE_ITEM_ACTION_PRIMARY:
hitMode = itemState->primaryHitMode;
break;
case INTERFACE_ITEM_ACTION_SECONDARY_AIMING:
bullseyeFid = buildFid(6, 288, 0, 0, 0);
bullseyeFid = buildFid(OBJ_TYPE_INTERFACE, 288, 0, 0, 0);
// FALLTHROUGH
case INTERFACE_ITEM_ACTION_SECONDARY:
hitMode = itemState->secondaryHitMode;
break;
case INTERFACE_ITEM_ACTION_RELOAD:
actionPoints = _item_mp_cost(gDude, gInterfaceCurrentHand == HAND_LEFT ? HIT_MODE_LEFT_WEAPON_RELOAD : HIT_MODE_RIGHT_WEAPON_RELOAD, false);
primaryFid = buildFid(6, 291, 0, 0, 0);
primaryFid = buildFid(OBJ_TYPE_INTERFACE, 291, 0, 0, 0);
break;
}
@ -1893,7 +1893,7 @@ static int interfaceBarRefreshMainAction()
break;
}
primaryFid = buildFid(6, id, 0, 0, 0);
primaryFid = buildFid(OBJ_TYPE_INTERFACE, id, 0, 0, 0);
}
if (primaryFid != -1) {
@ -1913,7 +1913,7 @@ static int interfaceBarRefreshMainAction()
if (actionPoints >= 0 && actionPoints < 10) {
// movement point text
int fid = buildFid(6, 289, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 289, 0, 0, 0);
CacheEntry* handle;
Art* art = artLock(fid, &handle);
@ -1936,7 +1936,7 @@ static int interfaceBarRefreshMainAction()
int offset = width + 7;
// movement point numbers - ten numbers 0 to 9, each 10 pixels wide.
fid = buildFid(6, 290, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 290, 0, 0, 0);
art = artLock(fid, &handle);
if (art != NULL) {
width = artGetWidth(art, 0, 0);
@ -2018,30 +2018,32 @@ static void interfaceBarSwapHandsAnimatePutAwayTakeOutSequence(int previousWeapo
gInterfaceBarSwapHandsInProgress = true;
reg_anim_clear(gDude);
reg_anim_begin(2);
reg_anim_update_light(gDude, 4, 0);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterSetLightDistance(gDude, 4, 0);
if (previousWeaponAnimationCode != 0) {
const char* sfx = sfxBuildCharName(gDude, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED);
reg_anim_play_sfx(gDude, sfx, 0);
reg_anim_animate(gDude, ANIM_PUT_AWAY, 0);
animationRegisterPlaySoundEffect(gDude, sfx, 0);
animationRegisterAnimate(gDude, ANIM_PUT_AWAY, 0);
}
reg_anim_11_1(NULL, NULL, _intface_redraw_items_callback, -1);
// TODO: Get rid of cast.
animationRegisterCallbackForced(NULL, NULL, (AnimationCallback*)_intface_redraw_items_callback, -1);
Object* item = gInterfaceItemStates[gInterfaceCurrentHand].item;
if (item != NULL && item->lightDistance > 4) {
reg_anim_update_light(gDude, item->lightDistance, 0);
animationRegisterSetLightDistance(gDude, item->lightDistance, 0);
}
if (weaponAnimationCode != 0) {
reg_anim_18(gDude, weaponAnimationCode, -1);
animationRegisterTakeOutWeapon(gDude, weaponAnimationCode, -1);
} else {
int fid = buildFid(1, gDude->fid & 0xFFF, ANIM_STAND, 0, gDude->rotation + 1);
reg_anim_17(gDude, fid, -1);
int fid = buildFid(OBJ_TYPE_CRITTER, gDude->fid & 0xFFF, ANIM_STAND, 0, gDude->rotation + 1);
animationRegisterSetFid(gDude, fid, -1);
}
reg_anim_11_1(NULL, NULL, _intface_change_fid_callback, -1);
// TODO: Get rid of cast.
animationRegisterCallbackForced(NULL, NULL, (AnimationCallback*)_intface_change_fid_callback, -1);
if (reg_anim_end() == -1) {
return;
@ -2084,13 +2086,13 @@ static int endTurnButtonInit()
return -1;
}
fid = buildFid(6, 105, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 105, 0, 0, 0);
gEndTurnButtonUpFrmData = artLockFrameData(fid, 0, 0, &gEndTurnButtonUpFrmHandle);
if (gEndTurnButtonUpFrmData == NULL) {
return -1;
}
fid = buildFid(6, 106, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 106, 0, 0, 0);
gEndTurnButtonDownFrmData = artLockFrameData(fid, 0, 0, &gEndTurnButtonDownFrmHandle);
if (gEndTurnButtonDownFrmData == NULL) {
return -1;
@ -2147,13 +2149,13 @@ static int endCombatButtonInit()
return -1;
}
fid = buildFid(6, 107, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 107, 0, 0, 0);
gEndCombatButtonUpFrmData = artLockFrameData(fid, 0, 0, &gEndCombatButtonUpFrmHandle);
if (gEndCombatButtonUpFrmData == NULL) {
return -1;
}
fid = buildFid(6, 108, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 108, 0, 0, 0);
gEndCombatButtonDownFrmData = artLockFrameData(fid, 0, 0, &gEndCombatButtonDownFrmHandle);
if (gEndCombatButtonDownFrmData == NULL) {
return -1;
@ -2412,7 +2414,7 @@ static int indicatorBarInit()
CacheEntry* indicatorBoxFrmHandle;
int width;
int height;
int indicatorBoxFid = buildFid(6, 126, 0, 0, 0);
int indicatorBoxFid = buildFid(OBJ_TYPE_INTERFACE, 126, 0, 0, 0);
unsigned char* indicatorBoxFrmData = artLockFrameDataReturningSize(indicatorBoxFid, &indicatorBoxFrmHandle, &width, &height);
if (indicatorBoxFrmData == NULL) {
debugPrint("\nINTRFACE: Error initializing indicator box graphics! **\n");

View File

@ -398,7 +398,7 @@ static void _detachProgram(Program* program)
static void _purgeProgram(Program* program)
{
if (!program->exited) {
_removeProgramReferences_(program);
intLibRemoveProgramReferences(program);
program->exited = true;
}
}
@ -781,7 +781,7 @@ static void opCancelAll(Program* program)
static void opIf(Program* program)
{
ProgramValue value = programStackPopValue(program);
if (!value.isEmpty()) {
programStackPopValue(program);
} else {
@ -1963,7 +1963,7 @@ static void opCall(Program* program)
// 0x46B590
static void op801F(Program* program)
{
program->field_84 = programStackPopInteger(program);
program->windowId = programStackPopInteger(program);
program->field_7C = (int (*)(Program*))programStackPopPointer(program);
program->flags = programStackPopInteger(program) & 0xFFFF;
}
@ -2216,7 +2216,7 @@ static void opExportProcedure(Program* program)
unsigned char* proc_ptr = program->procedures + 4 + sizeof(Procedure) * procedureIndex;
char *procedureName = programGetIdentifier(program, stackReadInt32(proc_ptr, 0));
char* procedureName = programGetIdentifier(program, stackReadInt32(proc_ptr, 0));
int procedureAddress = stackReadInt32(proc_ptr, 16);
if (externalProcedureCreate(program, procedureName, procedureAddress, argumentCount) != 0) {
@ -2253,7 +2253,7 @@ static void opExit(Program* program)
}
if (!program->exited) {
_removeProgramReferences_(program);
intLibRemoveProgramReferences(program);
program->exited = true;
}
}
@ -2297,7 +2297,7 @@ static void opCallStart(Program* program)
_interpret(program->child, 24);
program->child->parent = program;
program->child->field_84 = program->field_84;
program->child->windowId = program->windowId;
}
// spawn
@ -2323,7 +2323,7 @@ static void opSpawn(Program* program)
_interpret(program->child, 24);
program->child->parent = program;
program->child->field_84 = program->field_84;
program->child->windowId = program->windowId;
if ((program->flags & PROGRAM_FLAG_CRITICAL_SECTION) != 0) {
program->child->flags |= PROGRAM_FLAG_CRITICAL_SECTION;
@ -2349,7 +2349,7 @@ static Program* forkProgram(Program* program)
_interpret(forked, 24);
forked->field_84 = program->field_84;
forked->windowId = program->windowId;
return forked;
}
@ -2516,7 +2516,7 @@ void interpreterRegisterOpcodeHandlers()
interpreterRegisterOpcode(OPCODE_START_CRITICAL, opEnterCriticalSection);
interpreterRegisterOpcode(OPCODE_END_CRITICAL, opLeaveCriticalSection);
_initIntlib();
intLibInit();
_initExport();
}
@ -2524,7 +2524,7 @@ void interpreterRegisterOpcodeHandlers()
void _interpretClose()
{
externalVariablesClear();
_intlibClose();
intLibExit();
}
// 0x46CCA4
@ -2641,7 +2641,7 @@ static void _setupCallWithReturnVal(Program* program, int address, int returnAdd
programStackPushPointer(program, (void*)program->field_7C);
programStackPushInteger(program, program->field_84);
programStackPushInteger(program, program->windowId);
program->flags &= ~0xFFFF;
program->instructionPointer = address;
@ -2664,11 +2664,11 @@ static void _setupExternalCallWithReturnVal(Program* program1, Program* program2
programStackPushPointer(program2, (void*)program2->field_7C);
programStackPushInteger(program2, program2->field_84);
programStackPushInteger(program2, program2->windowId);
program2->flags &= ~0xFFFF;
program2->instructionPointer = address;
program2->field_84 = program1->field_84;
program2->windowId = program1->windowId;
program1->flags |= PROGRAM_FLAG_0x20;
}
@ -2683,9 +2683,9 @@ void _executeProc(Program* program, int procedure_index)
unsigned char* procedure_ptr;
int flags;
char err[256];
Program* v12;
Program* context;
procedure_ptr = program->procedures + 4 + 24 * procedure_index;
procedure_ptr = program->procedures + 4 + sizeof(Procedure) * procedure_index;
flags = stackReadInt32(procedure_ptr, 4);
if (!(flags & PROCEDURE_FLAG_IMPORTED)) {
address = stackReadInt32(procedure_ptr, 16);
@ -2699,7 +2699,7 @@ void _executeProc(Program* program, int procedure_index)
}
program->flags |= PROGRAM_FLAG_CRITICAL_SECTION;
v12 = program;
context = program;
} else {
identifier = programGetIdentifier(program, stackReadInt32(procedure_ptr, 0));
external_program = externalProcedureGetProgram(identifier, &address, &arguments_count);
@ -2721,7 +2721,7 @@ void _executeProc(Program* program, int procedure_index)
programStackPushInteger(external_program, 0);
procedure_ptr = external_program->procedures + 4 + 24 * procedure_index;
procedure_ptr = external_program->procedures + 4 + sizeof(Procedure) * procedure_index;
flags = stackReadInt32(procedure_ptr, 4);
if (!(flags & PROCEDURE_FLAG_CRITICAL)) {
@ -2729,10 +2729,10 @@ void _executeProc(Program* program, int procedure_index)
}
external_program->flags |= PROGRAM_FLAG_CRITICAL_SECTION;
v12 = external_program;
context = external_program;
}
_interpret(v12, 0);
_interpret(context, 0);
}
// Returns index of the procedure with specified name or -1 if no such
@ -2769,10 +2769,10 @@ void _executeProcedure(Program* program, int procedure_index)
jmp_buf jmp_buf;
Program* v13;
procedure_ptr = program->procedures + 4 + 24 * procedure_index;
procedure_ptr = program->procedures + 4 + sizeof(Procedure) * procedure_index;
flags = stackReadInt32(procedure_ptr, 4);
if (flags & 0x04) {
if (flags & PROCEDURE_FLAG_IMPORTED) {
identifier = programGetIdentifier(program, stackReadInt32(procedure_ptr, 0));
external_program = externalProcedureGetProgram(identifier, &address, &arguments_count);
if (external_program == NULL) {
@ -2875,7 +2875,7 @@ void _updatePrograms()
curr = next;
}
_doEvents();
_updateIntLib();
intLibUpdate();
}
// 0x46E238

View File

@ -167,7 +167,7 @@ typedef struct Program {
int field_78; // time when program begin execution (for the first time)?, -1 - program never executed
int (*field_7C)(struct Program* s); // proc to check timer
int flags; // flags
int field_84;
int windowId;
bool exited;
ProgramStack* stackValues;
ProgramStack* returnStackValues;

View File

@ -19,7 +19,6 @@
#include "game_sound.h"
#include "geometry.h"
#include "interface.h"
#include "interpreter.h"
#include "item.h"
#include "light.h"
#include "loadsave.h"
@ -300,8 +299,8 @@ static void opObjectClose(Program* program);
static void opGameUiDisable(Program* program);
static void opGameUiEnable(Program* program);
static void opGameUiIsDisabled(Program* program);
static void opFadeOut(Program* program);
static void opFadeIn(Program* program);
static void opGameFadeOut(Program* program);
static void opGameFadeIn(Program* program);
static void opItemCapsTotal(Program* program);
static void opItemCapsAdjust(Program* program);
static void _op_anim_action_frame(Program* program);
@ -496,11 +495,11 @@ static int _correctFidForRemovedItem(Object* a1, Object* a2, int flags)
}
if (v8 == 0) {
newFid = buildFid((fid & 0xF000000) >> 24, fid & 0xFFF, (fid & 0xFF0000) >> 16, 0, (fid & 0x70000000) >> 28);
newFid = buildFid(FID_TYPE(fid), fid & 0xFFF, FID_ANIM_TYPE(fid), 0, (fid & 0x70000000) >> 28);
}
} else {
if (a1 == gDude) {
newFid = buildFid((fid & 0xF000000) >> 24, _art_vault_guy_num, (fid & 0xFF0000) >> 16, v8, (fid & 0x70000000) >> 28);
newFid = buildFid(FID_TYPE(fid), _art_vault_guy_num, FID_ANIM_TYPE(fid), v8, (fid & 0x70000000) >> 28);
}
_adjust_ac(a1, a2, NULL);
@ -557,7 +556,7 @@ static void opSetMapStart(Program* program)
int elevation = programStackPopInteger(program);
int y = programStackPopInteger(program);
int x = programStackPopInteger(program);
if (mapSetElevation(elevation) != 0) {
scriptError("\nScript Error: %s: op_set_map_start: map_set_elevation failed", program->name);
return;
@ -619,7 +618,7 @@ static void opHasSkill(Program* program)
int result = 0;
if (object != NULL) {
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
result = skillGetValue(object, skill);
}
} else {
@ -658,7 +657,7 @@ static void opRollVsSkill(Program* program)
int roll = ROLL_CRITICAL_FAILURE;
if (object != NULL) {
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
int sid = scriptGetSid(program);
Script* script;
@ -835,7 +834,7 @@ static void opRandom(Program* program)
}
int result;
if (_vcr_status() == 2) {
if (vcrGetState() == VCR_STATE_TURNED_OFF) {
result = randomBetween(data[1], data[0]);
} else {
result = (data[0] - data[1]) / 2;
@ -899,7 +898,7 @@ static void opMoveTo(Program* program)
Rect before;
objectGetRect(object, &before);
if (object->elevation != elevation && (object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (object->elevation != elevation && PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
_combat_delete_critter(object);
}
@ -964,7 +963,7 @@ static void opCreateObject(Program* program)
if (sid != -1) {
int scriptType = 0;
switch (object->pid >> 24) {
switch (PID_TYPE(object->pid)) {
case OBJ_TYPE_CRITTER:
scriptType = SCRIPT_TYPE_CRITTER;
break;
@ -991,7 +990,7 @@ static void opCreateObject(Program* program)
script->field_14 = sid - 1;
if (scriptType == SCRIPT_TYPE_SPATIAL) {
script->sp.built_tile = ((object->elevation << 29) & 0xE0000000) | object->tile;
script->sp.built_tile = builtTileCreate(object->tile, object->elevation);
script->sp.radius = 3;
}
@ -1020,7 +1019,7 @@ static void opDestroyObject(Program* program)
return;
}
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
if (_isLoadingGame()) {
debugPrint("\nError: attempt to destroy critter in load/save-game: %s!", program->name);
program->flags &= ~PROGRAM_FLAG_0x20;
@ -1030,7 +1029,7 @@ static void opDestroyObject(Program* program)
bool isSelf = object == scriptGetSelf(program);
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
_combat_delete_critter(object);
}
@ -1311,7 +1310,7 @@ static void opGetObjectType(Program* program)
int objectType = -1;
if (object != NULL) {
objectType = (object->fid & 0xF000000) >> 24;
objectType = FID_TYPE(object->fid);
}
programStackPushInteger(program, objectType);
@ -1325,7 +1324,7 @@ static void opGetItemType(Program* program)
int itemType = -1;
if (obj != NULL) {
if ((obj->pid >> 24) == OBJ_TYPE_ITEM) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_ITEM) {
Proto* proto;
if (protoGetProto(obj->pid, &proto) != -1) {
itemType = itemGetType(obj);
@ -1400,8 +1399,8 @@ static void opAnimateStand(Program* program)
}
if (!isInCombat()) {
reg_anim_begin(1);
reg_anim_animate(object, ANIM_STAND, 0);
reg_anim_begin(ANIMATION_REQUEST_UNRESERVED);
animationRegisterAnimate(object, ANIM_STAND, 0);
reg_anim_end();
}
}
@ -1424,8 +1423,8 @@ static void opAnimateStandReverse(Program* program)
}
if (!isInCombat()) {
reg_anim_begin(0x01);
reg_anim_animate_reverse(object, ANIM_STAND, 0);
reg_anim_begin(ANIMATION_REQUEST_UNRESERVED);
animationRegisterAnimateReversed(object, ANIM_STAND, 0);
reg_anim_end();
}
}
@ -1468,12 +1467,12 @@ static void opAnimateMoveObjectToTile(Program* program)
flags &= ~0x10;
}
reg_anim_begin(1);
reg_anim_begin(ANIMATION_REQUEST_UNRESERVED);
if (flags == 0) {
reg_anim_obj_move_to_tile(object, tile, object->elevation, -1, 0);
animationRegisterMoveToTile(object, tile, object->elevation, -1, 0);
} else {
reg_anim_obj_run_to_tile(object, tile, object->elevation, -1, 0);
animationRegisterRunToTile(object, tile, object->elevation, -1, 0);
}
reg_anim_end();
@ -1739,7 +1738,7 @@ static void opWieldItem(Program* program)
return;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
scriptPredefinedError(program, "wield_obj_critter", SCRIPT_ERROR_FOLLOWS);
debugPrint(" Only works for critters! ERROR ERROR ERROR!");
return;
@ -1805,7 +1804,7 @@ static void opUseObject(Program* program)
}
Object* self = scriptGetSelf(program);
if ((self->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) {
_action_use_an_object(script->target, object);
} else {
_obj_use(self, object);
@ -1946,7 +1945,7 @@ static void opStartGameDialog(Program* program)
}
gGameDialogHeadFid = -1;
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
Proto* proto;
if (protoGetProto(obj->pid, &proto) == -1) {
return;
@ -2009,7 +2008,7 @@ static void opMetarule3(Program* program)
ProgramValue param2 = programStackPopValue(program);
ProgramValue param1 = programStackPopValue(program);
int rule = programStackPopInteger(program);
ProgramValue result;
result.opcode = VALUE_TYPE_INT;
result.integerValue = 0;
@ -2048,7 +2047,7 @@ static void opMetarule3(Program* program)
Object* object = objectFindFirstAtLocation(elevation, tile);
while (object != NULL) {
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
if (critterFound) {
result.opcode = VALUE_TYPE_PTR;
result.pointerValue = object;
@ -2069,9 +2068,9 @@ static void opMetarule3(Program* program)
Object* obj = static_cast<Object*>(param1.pointerValue);
int frmId = param2.integerValue;
int fid = buildFid((obj->fid & 0xF000000) >> 24,
int fid = buildFid(FID_TYPE(obj->fid),
frmId,
(obj->fid & 0xFF0000) >> 16,
FID_ANIM_TYPE(obj->fid),
(obj->fid & 0xF000) >> 12,
(obj->fid & 0x70000000) >> 28);
@ -2139,7 +2138,7 @@ static void opSetObjectVisibility(Program* program)
Rect rect;
if (objectHide(obj, &rect) != -1) {
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
obj->flags |= OBJECT_NO_BLOCK;
}
@ -2148,7 +2147,7 @@ static void opSetObjectVisibility(Program* program)
}
} else {
if ((obj->flags & OBJECT_HIDDEN) != 0) {
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
obj->flags &= ~OBJECT_NO_BLOCK;
}
@ -2364,7 +2363,7 @@ static int _correctDeath(Object* critter, int anim, bool forceBack)
if (violenceLevel < VIOLENCE_LEVEL_MAXIMUM_BLOOD) {
useStandardDeath = true;
} else {
int fid = buildFid(1, critter->fid & 0xFFF, anim, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
int fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, anim, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
if (!artExists(fid)) {
useStandardDeath = true;
}
@ -2374,7 +2373,7 @@ static int _correctDeath(Object* critter, int anim, bool forceBack)
if (forceBack) {
anim = ANIM_FALL_BACK;
} else {
int fid = buildFid(1, critter->fid & 0xFFF, ANIM_FALL_FRONT, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
int fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, ANIM_FALL_FRONT, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
if (artExists(fid)) {
anim = ANIM_FALL_FRONT;
} else {
@ -2407,7 +2406,7 @@ static void opKillCritterType(Program* program)
Object* obj = objectFindFirst();
while (obj != NULL) {
if (((obj->fid & 0xFF0000) >> 16) >= ANIM_FALL_BACK_SF) {
if (FID_ANIM_TYPE(obj->fid) >= ANIM_FALL_BACK_SF) {
obj = objectFindNext();
continue;
}
@ -2447,7 +2446,7 @@ static void opKillCritterType(Program* program)
objectFindFirst();
gMapHeader.field_38 = gameTimeGetTime();
gMapHeader.lastVisitTime = gameTimeGetTime();
}
obj = objectFindNext();
@ -2471,7 +2470,7 @@ static void opCritterDamage(Program* program)
return;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
scriptPredefinedError(program, "critter_damage", SCRIPT_ERROR_FOLLOWS);
debugPrint(" Can't call on non-critters!");
return;
@ -2485,7 +2484,7 @@ static void opCritterDamage(Program* program)
bool animate = (damageTypeWithFlags & 0x200) == 0;
bool bypassArmor = (damageTypeWithFlags & 0x100) != 0;
int damageType = damageTypeWithFlags & ~(0x100 | 0x200);
_action_dmg(object->tile, object->elevation, amount, amount, damageType, animate, bypassArmor);
actionDamage(object->tile, object->elevation, amount, amount, damageType, animate, bypassArmor);
program->flags &= ~PROGRAM_FLAG_0x20;
@ -2567,12 +2566,12 @@ static void opHasTrait(Program* program)
case CRITTER_TRAIT_OBJECT:
switch (param) {
case CRITTER_TRAIT_OBJECT_AI_PACKET:
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
result = object->data.critter.combat.aiPacket;
}
break;
case CRITTER_TRAIT_OBJECT_TEAM:
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
result = object->data.critter.combat.team;
}
break;
@ -2681,7 +2680,7 @@ static void opGameDialogSystemEnter(Program* program)
}
Object* self = scriptGetSelf(program);
if ((self->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) {
if (!critterIsActive(self)) {
return;
}
@ -2723,11 +2722,11 @@ static void opGetCritterState(Program* program)
Object* critter = static_cast<Object*>(programStackPopPointer(program));
int state = CRITTER_STATE_DEAD;
if (critter != NULL && (critter->pid >> 24) == OBJ_TYPE_CRITTER) {
if (critter != NULL && PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER) {
if (critterIsActive(critter)) {
state = CRITTER_STATE_NORMAL;
int anim = (critter->fid & 0xFF0000) >> 16;
int anim = FID_ANIM_TYPE(critter->fid);
if (anim >= ANIM_FALL_BACK_SF && anim <= ANIM_FALL_FRONT_SF) {
state = CRITTER_STATE_PRONE;
}
@ -2809,7 +2808,7 @@ static void opCritterAttemptPlacement(Program* program)
return;
}
if (elevation != critter->elevation && critter->pid >> 24 == OBJ_TYPE_CRITTER) {
if (elevation != critter->elevation && PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER) {
_combat_delete_critter(critter);
}
@ -2853,7 +2852,7 @@ static void opCritterAddTrait(Program* program)
Object* object = static_cast<Object*>(programStackPopPointer(program));
if (object != NULL) {
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
switch (kind) {
case CRITTER_TRAIT_PERK:
if (1) {
@ -2928,7 +2927,7 @@ static void opCritterRemoveTrait(Program* program)
return;
}
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
switch (kind) {
case CRITTER_TRAIT_PERK:
while (perkGetRank(object, param) > 0) {
@ -2997,7 +2996,7 @@ static void opCritterGetInventoryObject(Program* program)
int type = programStackPopInteger(program);
Object* critter = static_cast<Object*>(programStackPopPointer(program));
if ((critter->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER) {
switch (type) {
case INVEN_TYPE_WORN:
programStackPushPointer(program, critterGetArmor(critter));
@ -3280,13 +3279,13 @@ static void opMetarule(Program* program)
case METARULE_WEAPON_DAMAGE_TYPE:
if (1) {
Object* object = static_cast<Object*>(param.pointerValue);
if ((object->pid >> 24) == OBJ_TYPE_ITEM) {
if (PID_TYPE(object->pid) == OBJ_TYPE_ITEM) {
if (itemGetType(object) == ITEM_TYPE_WEAPON) {
result = weaponGetDamageType(NULL, object);
break;
}
} else {
if (buildFid(5, 10, 0, 0, 0) == object->fid) {
if (buildFid(OBJ_TYPE_MISC, 10, 0, 0, 0) == object->fid) {
result = DAMAGE_TYPE_EXPLOSION;
break;
}
@ -3299,10 +3298,10 @@ static void opMetarule(Program* program)
case METARULE_CRITTER_BARTERS:
if (1) {
Object* object = static_cast<Object*>(param.pointerValue);
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
Proto* proto;
protoGetProto(object->pid, &proto);
if ((proto->critter.data.flags & 0x02) != 0) {
if ((proto->critter.data.flags & CRITTER_FLAG_0x2) != 0) {
result = 1;
}
}
@ -3348,40 +3347,40 @@ static void opAnim(Program* program)
if (anim < ANIM_COUNT) {
CritterCombatData* combatData = NULL;
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
combatData = &(obj->data.critter.combat);
}
anim = _correctDeath(obj, anim, true);
reg_anim_begin(1);
reg_anim_begin(ANIMATION_REQUEST_UNRESERVED);
// TODO: Not sure about the purpose, why it handles knock down flag?
if (frame == 0) {
reg_anim_animate(obj, anim, 0);
animationRegisterAnimate(obj, anim, 0);
if (anim >= ANIM_FALL_BACK && anim <= ANIM_FALL_FRONT_BLOOD) {
int fid = buildFid(1, obj->fid & 0xFFF, anim + 28, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 28);
reg_anim_17(obj, fid, -1);
int fid = buildFid(OBJ_TYPE_CRITTER, obj->fid & 0xFFF, anim + 28, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 28);
animationRegisterSetFid(obj, fid, -1);
}
if (combatData != NULL) {
combatData->results &= DAM_KNOCKED_DOWN;
}
} else {
int fid = buildFid((obj->fid & 0xF000000) >> 24, obj->fid & 0xFFF, anim, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 24);
reg_anim_animate_reverse(obj, anim, 0);
int fid = buildFid(FID_TYPE(obj->fid), obj->fid & 0xFFF, anim, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 24);
animationRegisterAnimateReversed(obj, anim, 0);
if (anim == ANIM_PRONE_TO_STANDING) {
fid = buildFid((obj->fid & 0xF000000) >> 24, obj->fid & 0xFFF, ANIM_FALL_FRONT_SF, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 24);
fid = buildFid(FID_TYPE(obj->fid), obj->fid & 0xFFF, ANIM_FALL_FRONT_SF, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 24);
} else if (anim == ANIM_BACK_TO_STANDING) {
fid = buildFid((obj->fid & 0xF000000) >> 24, obj->fid & 0xFFF, ANIM_FALL_BACK_SF, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 24);
fid = buildFid(FID_TYPE(obj->fid), obj->fid & 0xFFF, ANIM_FALL_BACK_SF, (obj->fid & 0xF000) >> 12, (obj->fid & 0x70000000) >> 24);
}
if (combatData != NULL) {
combatData->results |= DAM_KNOCKED_DOWN;
}
reg_anim_17(obj, fid, -1);
animationRegisterSetFid(obj, fid, -1);
}
reg_anim_end();
@ -3451,7 +3450,7 @@ static void opRegAnimAnimate(Program* program)
int violenceLevel = VIOLENCE_LEVEL_NONE;
if (anim != 20 || object == NULL || object->pid != 0x100002F || (configGetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_VIOLENCE_LEVEL_KEY, &violenceLevel) && violenceLevel >= 2)) {
if (object != NULL) {
reg_anim_animate(object, anim, delay);
animationRegisterAnimate(object, anim, delay);
} else {
scriptPredefinedError(program, "reg_anim_animate", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -3469,7 +3468,7 @@ static void opRegAnimAnimateReverse(Program* program)
if (!isInCombat()) {
if (object != NULL) {
reg_anim_animate_reverse(object, anim, delay);
animationRegisterAnimateReversed(object, anim, delay);
} else {
scriptPredefinedError(program, "reg_anim_animate_reverse", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -3486,7 +3485,7 @@ static void opRegAnimObjectMoveToObject(Program* program)
if (!isInCombat()) {
if (object != NULL) {
reg_anim_obj_move_to_obj(object, dest, -1, delay);
animationRegisterMoveToObject(object, dest, -1, delay);
} else {
scriptPredefinedError(program, "reg_anim_obj_move_to_obj", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -3503,7 +3502,7 @@ static void opRegAnimObjectRunToObject(Program* program)
if (!isInCombat()) {
if (object != NULL) {
reg_anim_obj_run_to_obj(object, dest, -1, delay);
animationRegisterRunToObject(object, dest, -1, delay);
} else {
scriptPredefinedError(program, "reg_anim_obj_run_to_obj", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -3520,7 +3519,7 @@ static void opRegAnimObjectMoveToTile(Program* program)
if (!isInCombat()) {
if (object != NULL) {
reg_anim_obj_move_to_tile(object, tile, object->elevation, -1, delay);
animationRegisterMoveToTile(object, tile, object->elevation, -1, delay);
} else {
scriptPredefinedError(program, "reg_anim_obj_move_to_tile", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -3537,7 +3536,7 @@ static void opRegAnimObjectRunToTile(Program* program)
if (!isInCombat()) {
if (object != NULL) {
reg_anim_obj_run_to_tile(object, tile, object->elevation, -1, delay);
animationRegisterRunToTile(object, tile, object->elevation, -1, delay);
} else {
scriptPredefinedError(program, "reg_anim_obj_run_to_tile", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -3674,8 +3673,8 @@ static void opGetDaysSinceLastVisit(Program* program)
{
int days;
if (gMapHeader.field_38 != 0) {
days = (gameTimeGetTime() - gMapHeader.field_38) / GAME_TIME_TICKS_PER_DAY;
if (gMapHeader.lastVisitTime != 0) {
days = (gameTimeGetTime() - gMapHeader.lastVisitTime) / GAME_TIME_TICKS_PER_DAY;
} else {
days = -1;
}
@ -3759,7 +3758,6 @@ static void _op_gsay_option(Program* program)
}
} else {
programFatalError("Invalid arg 3 to sayOption");
}
program->flags &= ~PROGRAM_FLAG_0x20;
@ -3868,7 +3866,7 @@ static void opGetPoison(Program* program)
int poison = 0;
if (obj != NULL) {
if (obj->pid >> 24 == 1) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
poison = critterGetPoison(obj);
} else {
debugPrint("\nScript Error: get_poison: who is not a critter!");
@ -3915,7 +3913,7 @@ static void opRegAnimAnimateForever(Program* program)
if (!isInCombat()) {
if (obj != NULL) {
reg_anim_animate_forever(obj, anim, -1);
animationRegisterAnimateForever(obj, anim, -1);
} else {
scriptPredefinedError(program, "reg_anim_animate_forever", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -4119,7 +4117,7 @@ static void opGameUiIsDisabled(Program* program)
// gfade_out
// 0x45B404
static void opFadeOut(Program* program)
static void opGameFadeOut(Program* program)
{
int data = programStackPopInteger(program);
@ -4132,7 +4130,7 @@ static void opFadeOut(Program* program)
// gfade_in
// 0x45B47C
static void opFadeIn(Program* program)
static void opGameFadeIn(Program* program)
{
int data = programStackPopInteger(program);
@ -4186,7 +4184,7 @@ static void _op_anim_action_frame(Program* program)
int actionFrame = 0;
if (object != NULL) {
int fid = buildFid((object->fid & 0xF000000) >> 24, object->fid & 0xFFF, anim, 0, object->rotation);
int fid = buildFid(FID_TYPE(object->fid), object->fid & 0xFFF, anim, 0, object->rotation);
CacheEntry* frmHandle;
Art* frm = artLock(fid, &frmHandle);
if (frm != NULL) {
@ -4214,7 +4212,7 @@ static void opRegAnimPlaySfx(Program* program)
}
if (obj != NULL) {
reg_anim_play_sfx(obj, soundEffectName, delay);
animationRegisterPlaySoundEffect(obj, soundEffectName, delay);
} else {
scriptPredefinedError(program, "reg_anim_play_sfx", SCRIPT_ERROR_OBJECT_IS_NULL);
}
@ -4229,7 +4227,7 @@ static void opCritterModifySkill(Program* program)
Object* critter = static_cast<Object*>(programStackPopPointer(program));
if (critter != NULL && points != 0) {
if (critter->pid >> 24 == OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) == OBJ_TYPE_CRITTER) {
if (critter == gDude) {
int normalizedPoints = abs(points);
if (skillIsTagged(skill)) {
@ -4430,7 +4428,7 @@ static void opDestroyMultipleObjects(Program* program)
int result = 0;
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
_combat_delete_critter(object);
}
@ -4502,7 +4500,7 @@ static void opUseObjectOnObject(Program* program)
}
Object* self = scriptGetSelf(program);
if ((self->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) {
_action_use_an_item_on_object(self, target, item);
} else {
_obj_use_item_on(self, target, item);
@ -4723,7 +4721,7 @@ static void opTerminateCombat(Program* program)
_game_user_wants_to_quit = 1;
Object* self = scriptGetSelf(program);
if (self != NULL) {
if ((self->pid >> 24) == 1) {
if (PID_TYPE(self->pid) == OBJ_TYPE_CRITTER) {
self->data.critter.combat.maneuver |= CRITTER_MANEUVER_STOP_ATTACKING;
self->data.critter.combat.whoHitMe = NULL;
_combatAIInfoSetLastTarget(self, NULL);
@ -4967,8 +4965,8 @@ void _initIntExtra()
interpreterRegisterOpcode(0x8133, opGameUiDisable); // op_game_ui_disable
interpreterRegisterOpcode(0x8134, opGameUiEnable); // op_game_ui_enable
interpreterRegisterOpcode(0x8135, opGameUiIsDisabled); // op_game_ui_is_disabled
interpreterRegisterOpcode(0x8136, opFadeOut); // op_gfade_out
interpreterRegisterOpcode(0x8137, opFadeIn); // op_gfade_in
interpreterRegisterOpcode(0x8136, opGameFadeOut); // op_gfade_out
interpreterRegisterOpcode(0x8137, opGameFadeIn); // op_gfade_in
interpreterRegisterOpcode(0x8138, opItemCapsTotal); // op_item_caps_total
interpreterRegisterOpcode(0x8139, opItemCapsAdjust); // op_item_caps_adjust
interpreterRegisterOpcode(0x813A, _op_anim_action_frame); // op_anim_action_frame
@ -5001,7 +4999,16 @@ void _initIntExtra()
interpreterRegisterOpcode(0x8155, opCritterStopAttacking); // op_critter_stop_attacking
}
// NOTE: Uncollapsed 0x45D878.
//
// 0x45D878
void _intExtraRemoveProgramReferences_()
void intExtraUpdate()
{
}
// NOTE: Uncollapsed 0x45D878.
//
// 0x45D878
void intExtraRemoveProgramReferences(Program* program)
{
}

View File

@ -1,8 +1,11 @@
#ifndef INTERPRETER_EXTRA_H
#define INTERPRETER_EXTRA_H
#include "interpreter.h"
void _intExtraClose_();
void _initIntExtra();
void _intExtraRemoveProgramReferences_();
void intExtraUpdate();
void intExtraRemoveProgramReferences(Program* program);
#endif /* INTERPRETER_EXTRA_H */

File diff suppressed because it is too large Load Diff

View File

@ -3,12 +3,12 @@
#include "interpreter.h"
typedef void (*OFF_59E160)(Program*);
typedef void(IntLibProgramDeleteCallback)(Program*);
void _updateIntLib();
void _intlibClose();
void _initIntlib();
void _interpretRegisterProgramDeleteCallback(OFF_59E160 fn);
void _removeProgramReferences_(Program* program);
void intLibUpdate();
void intLibExit();
void intLibInit();
void intLibRegisterProgramDeleteCallback(IntLibProgramDeleteCallback* callback);
void intLibRemoveProgramReferences(Program* program);
#endif /* INTERPRETER_LIB_H */

View File

@ -675,7 +675,7 @@ static bool _setup_inventory(int inventoryWindowType)
gInventoryWindowMaxY = windowDescription->height + inventoryWindowY;
unsigned char* dest = windowGetBuffer(gInventoryWindow);
int backgroundFid = buildFid(6, windowDescription->field_0, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->field_0, 0, 0, 0);
CacheEntry* backgroundFrmHandle;
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
@ -821,10 +821,10 @@ static bool _setup_inventory(int inventoryWindowType)
unsigned char* buttonDownData;
unsigned char* buttonDisabledData;
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[0]));
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[1]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -853,13 +853,13 @@ static bool _setup_inventory(int inventoryWindowType)
// TODO: Figure out why it building fid in chain.
// Large arrow up (normal).
fid = buildFid(6, 100, 0, 0, 0);
fid = buildFid(6, fid, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 100, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, fid, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[2]));
// Large arrow up (pressed).
fid = buildFid(6, 101, 0, 0, 0);
fid = buildFid(6, fid, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 101, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, fid, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[3]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -877,15 +877,15 @@ static bool _setup_inventory(int inventoryWindowType)
}
} else {
// Large up arrow (normal).
fid = buildFid(6, 49, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 49, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[2]));
// Large up arrow (pressed).
fid = buildFid(6, 50, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 50, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[3]));
// Large up arrow (disabled).
fid = buildFid(6, 53, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 53, 0, 0, 0);
buttonDisabledData = artLockFrameData(fid, 0, 0, &(_ikey[4]));
if (buttonUpData != NULL && buttonDownData != NULL && buttonDisabledData != NULL) {
@ -913,13 +913,13 @@ static bool _setup_inventory(int inventoryWindowType)
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_TRADE) {
// Large dialog down button (normal)
fid = buildFid(6, 93, 0, 0, 0);
fid = buildFid(6, fid, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 93, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, fid, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[5]));
// Dialog down button (pressed)
fid = buildFid(6, 94, 0, 0, 0);
fid = buildFid(6, fid, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 94, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, fid, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[6]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -943,15 +943,15 @@ static bool _setup_inventory(int inventoryWindowType)
}
} else {
// Large arrow down (normal).
fid = buildFid(6, 51, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 51, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[5]));
// Large arrow down (pressed).
fid = buildFid(6, 52, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 52, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[6]));
// Large arrow down (disabled).
fid = buildFid(6, 54, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 54, 0, 0, 0);
buttonDisabledData = artLockFrameData(fid, 0, 0, &(_ikey[7]));
if (buttonUpData != NULL && buttonDownData != NULL && buttonDisabledData != NULL) {
@ -986,11 +986,11 @@ static bool _setup_inventory(int inventoryWindowType)
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) {
if (!_gIsSteal) {
// Take all button (normal)
fid = buildFid(6, 436, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 436, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[8]));
// Take all button (pressed)
fid = buildFid(6, 437, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 437, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[9]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -1004,11 +1004,11 @@ static bool _setup_inventory(int inventoryWindowType)
}
} else {
// Inventory button up (normal)
fid = buildFid(6, 49, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 49, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[8]));
// Inventory button up (pressed)
fid = buildFid(6, 50, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 50, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[9]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -1026,11 +1026,11 @@ static bool _setup_inventory(int inventoryWindowType)
}
// Inventory button down (normal)
fid = buildFid(6, 51, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 51, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_ikey[8]));
// Inventory button down (pressed).
fid = buildFid(6, 52, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 52, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_ikey[9]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -1178,7 +1178,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType)
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_NORMAL) {
pitch = 499;
int backgroundFid = buildFid(6, 48, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 48, 0, 0, 0);
CacheEntry* backgroundFrmHandle;
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
@ -1191,7 +1191,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType)
if (gInventoryLeftHandItem != NULL && gInventoryLeftHandItem == gInventoryRightHandItem) {
// Clear item1.
int itemBackgroundFid = buildFid(6, 32, 0, 0, 0);
int itemBackgroundFid = buildFid(OBJ_TYPE_INTERFACE, 32, 0, 0, 0);
CacheEntry* itemBackgroundFrmHandle;
Art* itemBackgroundFrm = artLock(itemBackgroundFid, &itemBackgroundFrmHandle);
@ -1212,7 +1212,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType)
} else if (inventoryWindowType == INVENTORY_WINDOW_TYPE_USE_ITEM_ON) {
pitch = 292;
int backgroundFid = buildFid(6, 113, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 113, 0, 0, 0);
CacheEntry* backgroundFrmHandle;
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
@ -1224,7 +1224,7 @@ static void _display_inventory(int a1, int a2, int inventoryWindowType)
} else if (inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) {
pitch = 537;
int backgroundFid = buildFid(6, 114, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 114, 0, 0, 0);
CacheEntry* backgroundFrmHandle;
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
@ -1333,7 +1333,7 @@ static void _display_target_inventory(int a1, int a2, Inventory* inventory, int
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_LOOT) {
pitch = 537;
int fid = buildFid(6, 114, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 114, 0, 0, 0);
CacheEntry* handle;
unsigned char* data = artLockFrameData(fid, 0, 0, &handle);
@ -1521,7 +1521,7 @@ static void _display_body(int fid, int inventoryWindowType)
rect.bottom = rect.top + INVENTORY_BODY_VIEW_HEIGHT - 1;
int frmId = gGameDialogSpeakerIsPartyMember ? 420 : 111;
int backgroundFid = buildFid(6, frmId, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, frmId, 0, 0, 0);
unsigned char* src = artLockFrameData(backgroundFid, 0, 0, &backrgroundFrmHandle);
if (src != NULL) {
@ -1563,7 +1563,7 @@ static void _display_body(int fid, int inventoryWindowType)
rect.right = rect.left + INVENTORY_BODY_VIEW_WIDTH - 1;
rect.bottom = rect.top + INVENTORY_BODY_VIEW_HEIGHT - 1;
int backgroundFid = buildFid(6, 114, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 114, 0, 0, 0);
unsigned char* src = artLockFrameData(backgroundFid, 0, 0, &backrgroundFrmHandle);
if (src != NULL) {
blitBufferToBuffer(src + 537 * rect.top + rect.left,
@ -1610,7 +1610,7 @@ static int inventoryCommonInit()
for (index = 0; index < INVENTORY_WINDOW_CURSOR_COUNT; index++) {
InventoryCursorData* cursorData = &(gInventoryCursorData[index]);
int fid = buildFid(6, gInventoryWindowCursorFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gInventoryWindowCursorFrmIds[index], 0, 0, 0);
Art* frm = artLock(fid, &(cursorData->frmHandle));
if (frm == NULL) {
break;
@ -1792,7 +1792,7 @@ static void _inven_pickup(int keyCode, int a2)
}
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 48, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 48, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData != NULL) {
blitBufferToBuffer(backgroundFrmData + 499 * rect.top + rect.left, width, height, 499, windowBuffer + 499 * rect.top + rect.left, 499);
@ -1803,7 +1803,7 @@ static void _inven_pickup(int keyCode, int a2)
rect.bottom = rect.top + height - 1;
} else {
CacheEntry* backgroundFrmHandle;
int backgroundFid = buildFid(6, 48, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 48, 0, 0, 0);
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData != NULL) {
blitBufferToBuffer(backgroundFrmData + 499 * 286 + 154, 180, 61, 499, windowBuffer + 499 * 286 + 154, 499);
@ -2043,7 +2043,7 @@ void _adjust_ac(Object* critter, Object* oldArmor, Object* newArmor)
static void _adjust_fid()
{
int fid;
if ((_inven_dude->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER) {
if (FID_TYPE(_inven_dude->fid) == OBJ_TYPE_CRITTER) {
Proto* proto;
int v0 = _art_vault_guy_num;
@ -2082,7 +2082,7 @@ static void _adjust_fid()
}
}
fid = buildFid(1, v0, 0, animationCode, 0);
fid = buildFid(OBJ_TYPE_CRITTER, v0, 0, animationCode, 0);
} else {
fid = _inven_dude->fid;
}
@ -2325,7 +2325,7 @@ static void inventoryRenderSummary()
unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow);
int fid = buildFid(6, 48, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 48, 0, 0, 0);
CacheEntry* backgroundHandle;
unsigned char* backgroundData = artLockFrameData(fid, 0, 0, &backgroundHandle);
@ -2515,7 +2515,7 @@ static void inventoryRenderSummary()
// Total wt:
messageListItem.num = 20;
if (messageListGetItem(&gInventoryMessageList, &messageListItem)) {
if (_stack[0]->pid >> 24 == OBJ_TYPE_CRITTER) {
if (PID_TYPE(_stack[0]->pid) == OBJ_TYPE_CRITTER) {
int carryWeight = critterGetStat(_stack[0], STAT_CARRY_WEIGHT);
int inventoryWeight = objectGetInventoryWeight(_stack[0]);
sprintf(formattedText, "%s %d/%d", messageListItem.text, inventoryWeight, carryWeight);
@ -2623,7 +2623,7 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4)
{
if (a4) {
if (!isoIsDisabled()) {
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
}
}
@ -2649,8 +2649,8 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4)
if (critter == gDude) {
if (!isoIsDisabled()) {
int fid = buildFid(1, baseFrmId, 0, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
reg_anim_17(critter, fid, 0);
int fid = buildFid(OBJ_TYPE_CRITTER, baseFrmId, 0, (critter->fid & 0xF000) >> 12, critter->rotation + 1);
animationRegisterSetFid(critter, fid, 0);
}
} else {
_adjust_ac(critter, armor, item);
@ -2665,7 +2665,7 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4)
int weaponAnimationCode = weaponGetAnimationCode(item);
int hitModeAnimationCode = weaponGetAnimationForHitMode(item, HIT_MODE_RIGHT_WEAPON_PRIMARY);
int fid = buildFid(1, critter->fid & 0xFFF, hitModeAnimationCode, weaponAnimationCode, critter->rotation + 1);
int fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, hitModeAnimationCode, weaponAnimationCode, critter->rotation + 1);
if (!artExists(fid)) {
debugPrint("\ninven_wield failed! ERROR ERROR ERROR!");
return -1;
@ -2730,21 +2730,21 @@ int _invenWieldFunc(Object* critter, Object* item, int a3, bool a4)
if (a4) {
if (!isoIsDisabled()) {
const char* soundEffectName = sfxBuildCharName(critter, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED);
reg_anim_play_sfx(critter, soundEffectName, 0);
reg_anim_animate(critter, ANIM_PUT_AWAY, 0);
animationRegisterPlaySoundEffect(critter, soundEffectName, 0);
animationRegisterAnimate(critter, ANIM_PUT_AWAY, 0);
}
}
}
if (a4 && !isoIsDisabled()) {
if (weaponAnimationCode != 0) {
reg_anim_18(critter, weaponAnimationCode, -1);
animationRegisterTakeOutWeapon(critter, weaponAnimationCode, -1);
} else {
int fid = buildFid(1, critter->fid & 0xFFF, 0, 0, critter->rotation + 1);
reg_anim_17(critter, fid, -1);
int fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, 0, 0, critter->rotation + 1);
animationRegisterSetFid(critter, fid, -1);
}
} else {
int fid = buildFid(1, critter->fid & 0xFFF, 0, weaponAnimationCode, critter->rotation + 1);
int fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, 0, weaponAnimationCode, critter->rotation + 1);
_dude_stand(critter, critter->rotation, fid);
}
}
@ -2791,20 +2791,20 @@ int _invenUnwieldFunc(Object* obj, int a2, int a3)
if (v6 == a2 && ((obj->fid & 0xF000) >> 12) != 0) {
if (a3 && !isoIsDisabled()) {
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
const char* sfx = sfxBuildCharName(obj, ANIM_PUT_AWAY, CHARACTER_SOUND_EFFECT_UNUSED);
reg_anim_play_sfx(obj, sfx, 0);
animationRegisterPlaySoundEffect(obj, sfx, 0);
reg_anim_animate(obj, 39, 0);
animationRegisterAnimate(obj, ANIM_PUT_AWAY, 0);
fid = buildFid(1, obj->fid & 0xFFF, 0, 0, obj->rotation + 1);
reg_anim_17(obj, fid, -1);
fid = buildFid(OBJ_TYPE_CRITTER, obj->fid & 0xFFF, 0, 0, obj->rotation + 1);
animationRegisterSetFid(obj, fid, -1);
return reg_anim_end();
}
fid = buildFid(1, obj->fid & 0xFFF, 0, 0, obj->rotation + 1);
fid = buildFid(OBJ_TYPE_CRITTER, obj->fid & 0xFFF, 0, 0, obj->rotation + 1);
_dude_stand(obj, obj->rotation, fid);
}
@ -3003,7 +3003,7 @@ static void inventoryExamineItem(Object* critter, Object* item)
unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow);
// Clear item description area.
int backgroundFid = buildFid(6, 48, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 48, 0, 0, 0);
CacheEntry* handle;
unsigned char* backgroundData = artLockFrameData(backgroundFid, 0, 0, &handle);
@ -3226,7 +3226,7 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
windowBuffer + windowDescription->width * rect.top + rect.left,
windowDescription->width);
} else {
int backgroundFid = buildFid(6, windowDescription->field_0, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->field_0, 0, 0, 0);
CacheEntry* backgroundFrmHandle;
unsigned char* backgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &backgroundFrmHandle);
blitBufferToBuffer(backgroundFrmData + windowDescription->width * rect.top + rect.left,
@ -3403,8 +3403,8 @@ int inventoryOpenLooting(Object* a1, Object* a2)
return 0;
}
if (((a2->fid & 0xF000000) >> 24) == OBJ_TYPE_CRITTER) {
if (_critter_flag_check(a2->pid, 0x20)) {
if (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER) {
if (_critter_flag_check(a2->pid, CRITTER_FLAG_0x20)) {
// You can't find anything to take from that.
messageListItem.num = 50;
if (messageListGetItem(&gInventoryMessageList, &messageListItem)) {
@ -3414,7 +3414,7 @@ int inventoryOpenLooting(Object* a1, Object* a2)
}
}
if (((a2->fid & 0xF000000) >> 24) == OBJ_TYPE_ITEM) {
if (FID_TYPE(a2->fid) == OBJ_TYPE_ITEM) {
if (itemGetType(a2) == ITEM_TYPE_CONTAINER) {
if (a2->frame == 0) {
CacheEntry* handle;
@ -3488,7 +3488,7 @@ int inventoryOpenLooting(Object* a1, Object* a2)
int critterCount = 0;
int critterIndex = 0;
if (!_gIsSteal) {
if ((a2->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER) {
if (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER) {
critterCount = objectListCreate(a2->tile, a2->elevation, OBJ_TYPE_CRITTER, &critters);
int endIndex = critterCount - 1;
for (int index = 0; index < critterCount; index++) {
@ -3520,10 +3520,10 @@ int inventoryOpenLooting(Object* a1, Object* a2)
}
// Setup left arrow button.
fid = buildFid(6, arrowFrmIds[INVENTORY_ARROW_FRM_LEFT_ARROW_UP], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, arrowFrmIds[INVENTORY_ARROW_FRM_LEFT_ARROW_UP], 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(arrowFrmHandles[INVENTORY_ARROW_FRM_LEFT_ARROW_UP]));
fid = buildFid(6, arrowFrmIds[INVENTORY_ARROW_FRM_LEFT_ARROW_DOWN], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, arrowFrmIds[INVENTORY_ARROW_FRM_LEFT_ARROW_DOWN], 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(arrowFrmHandles[INVENTORY_ARROW_FRM_LEFT_ARROW_DOWN]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -3534,10 +3534,10 @@ int inventoryOpenLooting(Object* a1, Object* a2)
}
// Setup right arrow button.
fid = buildFid(6, arrowFrmIds[INVENTORY_ARROW_FRM_RIGHT_ARROW_UP], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, arrowFrmIds[INVENTORY_ARROW_FRM_RIGHT_ARROW_UP], 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(arrowFrmHandles[INVENTORY_ARROW_FRM_RIGHT_ARROW_UP]));
fid = buildFid(6, arrowFrmIds[INVENTORY_ARROW_FRM_RIGHT_ARROW_DOWN], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, arrowFrmIds[INVENTORY_ARROW_FRM_RIGHT_ARROW_DOWN], 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(arrowFrmHandles[INVENTORY_ARROW_FRM_RIGHT_ARROW_DOWN]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -3800,7 +3800,7 @@ int inventoryOpenStealing(Object* a1, Object* a2)
return -1;
}
_gIsSteal = (a1->pid >> 24) == OBJ_TYPE_CRITTER && critterIsActive(a2);
_gIsSteal = PID_TYPE(a1->pid) == OBJ_TYPE_CRITTER && critterIsActive(a2);
_gStealCount = 0;
_gStealSize = 0;
@ -3848,7 +3848,7 @@ static int _move_inventory(Object* a1, int a2, Object* a3, bool a4)
unsigned char* windowBuffer = windowGetBuffer(gInventoryWindow);
CacheEntry* handle;
int fid = buildFid(6, 114, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 114, 0, 0, 0);
unsigned char* data = artLockFrameData(fid, 0, 0, &handle);
if (data != NULL) {
blitBufferToBuffer(data + 537 * rect.top + rect.left, INVENTORY_SLOT_WIDTH, INVENTORY_SLOT_HEIGHT, 537, windowBuffer + 537 * rect.top + rect.left, 537);
@ -3931,7 +3931,7 @@ static int _move_inventory(Object* a1, int a2, Object* a3, bool a4)
if (rc != 1) {
if (_item_move(a3, _inven_dude, a1, quantityToMove) == 0) {
if ((a1->flags & OBJECT_IN_RIGHT_HAND) != 0) {
a3->fid = buildFid((a3->fid & 0xF000000) >> 24, a3->fid & 0xFFF, (a3->fid & 0xFF0000) >> 16, 0, a3->rotation + 1);
a3->fid = buildFid(FID_TYPE(a3->fid), a3->fid & 0xFFF, FID_ANIM_TYPE(a3->fid), 0, a3->rotation + 1);
}
a3->flags &= ~OBJECT_EQUIPPED;
@ -4735,7 +4735,7 @@ static void _draw_amount(int value, int inventoryWindowType)
{
// BIGNUM.frm
CacheEntry* handle;
int fid = buildFid(6, 170, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 170, 0, 0, 0);
unsigned char* data = artLockFrameData(fid, 0, 0, &handle);
if (data == NULL) {
return;
@ -4947,7 +4947,7 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item)
unsigned char* windowBuffer = windowGetBuffer(_mt_wid);
CacheEntry* backgroundHandle;
int backgroundFid = buildFid(6, windowDescription->field_0, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, windowDescription->field_0, 0, 0, 0);
unsigned char* backgroundData = artLockFrameData(backgroundFid, 0, 0, &backgroundHandle);
if (backgroundData != NULL) {
blitBufferToBuffer(backgroundData, windowDescription->width, windowDescription->height, windowDescription->width, windowBuffer, windowDescription->width);
@ -4972,7 +4972,7 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item)
// Timer overlay
CacheEntry* overlayFrmHandle;
int overlayFid = buildFid(6, 306, 0, 0, 0);
int overlayFid = buildFid(OBJ_TYPE_INTERFACE, 306, 0, 0, 0);
unsigned char* overlayFrmData = artLockFrameData(overlayFid, 0, 0, &overlayFrmHandle);
if (overlayFrmData != NULL) {
blitBufferToBuffer(overlayFrmData, 105, 81, 105, windowBuffer + 34 * windowDescription->width + 113, windowDescription->width);
@ -4999,10 +4999,10 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item)
int btn;
// Plus button
fid = buildFid(6, 193, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 193, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_mt_key[0]));
fid = buildFid(6, 194, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 194, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_mt_key[1]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -5013,10 +5013,10 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item)
}
// Minus button
fid = buildFid(6, 191, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 191, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_mt_key[2]));
fid = buildFid(6, 192, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 192, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_mt_key[3]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -5026,10 +5026,10 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item)
}
}
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_mt_key[4]));
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_mt_key[5]));
if (buttonUpData != NULL && buttonDownData != NULL) {
@ -5047,10 +5047,10 @@ static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item)
}
if (inventoryWindowType == INVENTORY_WINDOW_TYPE_MOVE_ITEMS) {
fid = buildFid(6, 307, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 307, 0, 0, 0);
buttonUpData = artLockFrameData(fid, 0, 0, &(_mt_key[6]));
fid = buildFid(6, 308, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 308, 0, 0, 0);
buttonDownData = artLockFrameData(fid, 0, 0, &(_mt_key[7]));
if (buttonUpData != NULL && buttonDownData != NULL) {

View File

@ -189,7 +189,7 @@ int itemAttemptAdd(Object* owner, Object* itemToAdd, int quantity)
return -1;
}
int parentType = (owner->fid & 0xF000000) >> 24;
int parentType = FID_TYPE(owner->fid);
if (parentType == OBJ_TYPE_ITEM) {
int itemType = itemGetType(owner);
if (itemType == ITEM_TYPE_CONTAINER) {
@ -205,7 +205,7 @@ int itemAttemptAdd(Object* owner, Object* itemToAdd, int quantity)
Object* containerOwner = objectGetOwner(owner);
if (containerOwner != NULL) {
if (((containerOwner->fid & 0xF000000) >> 24) == OBJ_TYPE_CRITTER) {
if (FID_TYPE(containerOwner->fid) == OBJ_TYPE_CRITTER) {
int weightToAdd = itemGetWeight(itemToAdd);
weightToAdd *= quantity;
@ -473,7 +473,7 @@ int _item_move_all_hidden(Object* a1, Object* a2)
for (int j = i; j < inventory->length;) {
bool v5;
InventoryItem* inventoryItem = &(inventory->items[j]);
if (inventoryItem->item->pid >> 24 == OBJ_TYPE_ITEM) {
if (PID_TYPE(inventoryItem->item->pid) == OBJ_TYPE_ITEM) {
Proto* proto;
if (protoGetProto(inventoryItem->item->pid, &proto) != -1) {
v5 = (proto->item.extendedFlags & ItemProtoExtendedFlags_NaturalWeapon) == 0;
@ -505,7 +505,7 @@ int _item_destroy_all_hidden(Object* a1)
for (int j = i; j < inventory->length;) {
bool v5;
InventoryItem* inventoryItem = &(inventory->items[j]);
if (inventoryItem->item->pid >> 24 == OBJ_TYPE_ITEM) {
if (PID_TYPE(inventoryItem->item->pid) == OBJ_TYPE_ITEM) {
Proto* proto;
if (protoGetProto(inventoryItem->item->pid, &proto) != -1) {
v5 = (proto->item.extendedFlags & ItemProtoExtendedFlags_NaturalWeapon) == 0;
@ -584,9 +584,9 @@ int _item_drop_all(Object* critter, int tile)
if (hasEquippedItems) {
Rect updatedRect;
int fid = buildFid(1, frmId, (critter->fid & 0xFF0000) >> 16, 0, (critter->fid & 0x70000000) >> 28);
int fid = buildFid(OBJ_TYPE_CRITTER, frmId, FID_ANIM_TYPE(critter->fid), 0, (critter->fid & 0x70000000) >> 28);
objectSetFid(critter, fid, &updatedRect);
if (((critter->fid & 0xFF0000) >> 16) == 0) {
if (FID_ANIM_TYPE(critter->fid) == ANIM_STAND) {
tileWindowRefreshRect(&updatedRect, gElevation);
}
}
@ -667,7 +667,7 @@ int itemGetType(Object* item)
return ITEM_TYPE_MISC;
}
if ((item->pid >> 24) != OBJ_TYPE_ITEM) {
if (PID_TYPE(item->pid) != OBJ_TYPE_ITEM) {
return ITEM_TYPE_MISC;
}
@ -845,7 +845,7 @@ int objectGetCost(Object* obj)
}
}
if ((obj->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER) {
if (FID_TYPE(obj->fid) == OBJ_TYPE_CRITTER) {
Object* item2 = critterGetItem2(obj);
if (item2 != NULL && (item2->flags & OBJECT_IN_RIGHT_HAND) == 0) {
cost += itemGetCost(item2);
@ -883,7 +883,7 @@ int objectGetInventoryWeight(Object* obj)
weight += itemGetWeight(item) * inventoryItem->quantity;
}
if (((obj->fid & 0xF000000) >> 24) == OBJ_TYPE_CRITTER) {
if (FID_TYPE(obj->fid) == OBJ_TYPE_CRITTER) {
Object* item2 = critterGetItem2(obj);
if (item2 != NULL) {
if ((item2->flags & OBJECT_IN_RIGHT_HAND) == 0) {
@ -1088,7 +1088,7 @@ int weaponIsNatural(Object* obj)
{
Proto* proto;
if ((obj->pid >> 24) != OBJ_TYPE_ITEM) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_ITEM) {
return 0;
}
@ -1590,7 +1590,7 @@ int _item_w_range(Object* critter, int hitMode)
return range;
}
if (_critter_flag_check(critter->pid, 0x2000)) {
if (_critter_flag_check(critter->pid, CRITTER_FLAG_0x2000)) {
return 2;
}
@ -1942,14 +1942,10 @@ int _item_w_compute_ammo_cost(Object* obj, int* inout_a2)
return 0;
}
// Returns true if weapon's damage is explosion, plasma, or emp.
// Probably checks if weapon is granade.
//
// 0x4790E8
bool _item_w_is_grenade(Object* weapon)
bool weaponIsGrenade(Object* weapon)
{
int damageType = weaponGetDamageType(NULL, weapon);
return damageType == DAMAGE_TYPE_EXPLOSION || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP;
}
@ -1968,7 +1964,7 @@ int _item_w_area_damage_radius(Object* weapon, int hitMode)
}
} else if (attackType == ATTACK_TYPE_THROW) {
// NOTE: Uninline.
if (_item_w_is_grenade(weapon)) {
if (weaponIsGrenade(weapon)) {
// NOTE: Uninline.
v1 = _item_w_grenade_dmg_radius(weapon);
}
@ -2840,7 +2836,7 @@ int drugEffectEventProcess(Object* obj, void* data)
return 0;
}
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
return 0;
}
@ -3009,7 +3005,7 @@ int withdrawalEventWrite(File* stream, void* data)
// 0x47A4C4
static void performWithdrawalStart(Object* obj, int perk, int pid)
{
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
debugPrint("\nERROR: perform_withdrawal_start: Was called on non-critter!");
return;
}
@ -3039,7 +3035,7 @@ static void performWithdrawalStart(Object* obj, int perk, int pid)
// 0x47A558
static void performWithdrawalEnd(Object* obj, int perk)
{
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
debugPrint("\nERROR: perform_withdrawal_end: Was called on non-critter!");
return;
}

View File

@ -76,7 +76,7 @@ Object* _item_w_unload(Object* weapon);
int weaponGetActionPointCost1(Object* weapon);
int weaponGetActionPointCost2(Object* weapon);
int _item_w_compute_ammo_cost(Object* obj, int* inout_a2);
bool _item_w_is_grenade(Object* weapon);
bool weaponIsGrenade(Object* weapon);
int _item_w_area_damage_radius(Object* weapon, int hitMode);
int _item_w_grenade_dmg_radius(Object* weapon);
int _item_w_rocket_dmg_radius(Object* weapon);

View File

@ -1,9 +1,9 @@
#include "light.h"
#include "map_defs.h"
#include "object.h"
#include "perk.h"
#include "tile.h"
#include "object.h"
#include <math.h>
@ -111,7 +111,7 @@ void lightIncreaseIntensity(int elevation, int tile, int lightIntensity)
if (!hexGridTileIsValid(tile)) {
return;
}
gLightIntensity[elevation][tile] += lightIntensity;
}
@ -125,7 +125,7 @@ void lightDecreaseIntensity(int elevation, int tile, int lightIntensity)
if (!hexGridTileIsValid(tile)) {
return;
}
gLightIntensity[elevation][tile] -= lightIntensity;
}

View File

@ -1227,7 +1227,7 @@ static int lsgWindowInit(int windowType)
}
for (int index = 0; index < LOAD_SAVE_FRM_COUNT; index++) {
int fid = buildFid(6, gLoadSaveFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gLoadSaveFrmIds[index], 0, 0, 0);
gLoadSaveFrmData[index] = artLockFrameDataReturningSize(fid,
&(gLoadSaveFrmHandles[index]),
&(gLoadSaveFrmSizes[index].width),

View File

@ -23,13 +23,16 @@
#include "options.h"
#include "palette.h"
#include "platform_compat.h"
#include "proto.h"
#include "random.h"
#include "scripts.h"
#include "sfall_config.h"
#include "selfrun.h"
#include "sfall_config.h"
#include "text_font.h"
#include "version.h"
#include "window.h"
#include "window_manager.h"
#include "window_manager_private.h"
#include "word_wrap.h"
#include "world_map.h"
@ -57,7 +60,7 @@ typedef enum MainMenuOption {
MAIN_MENU_INTRO,
MAIN_MENU_NEW_GAME,
MAIN_MENU_LOAD_GAME,
MAIN_MENU_3,
MAIN_MENU_SCREENSAVER,
MAIN_MENU_TIMEOUT,
MAIN_MENU_CREDITS,
MAIN_MENU_QUOTES,
@ -70,6 +73,8 @@ static bool falloutInit(int argc, char** argv);
static int _main_load_new(char* fname);
static void mainLoop(FpsLimiter& fpsLimiter);
static void _main_selfrun_exit();
static void _main_selfrun_record();
static void _main_selfrun_play();
static void showDeath();
static void _main_death_voiceover_callback();
static int _mainDeathGrabTextFile(const char* fileName, char* dest);
@ -99,6 +104,16 @@ static int _main_selfrun_index = 0;
// 0x5194E8
static bool _main_show_death_scene = false;
// A switch to pick selfrun vs. intro video for screensaver:
// - `false` - will play next selfrun recording
// - `true` - will play intro video
//
// This value will alternate on every attempt, even if there are no selfrun
// recordings.
//
// 0x5194EC
static bool gMainMenuScreensaverCycle = false;
// 0x5194F0
static int gMainMenuWindow = -1;
@ -175,7 +190,7 @@ int falloutMain(int argc, char** argv)
// SFALL: Allow to skip intro movies
int skipOpeningMovies;
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY, &skipOpeningMovies);
if(skipOpeningMovies < 1) {
if (skipOpeningMovies < 1) {
gameMoviePlay(MOVIE_IPLOGO, GAME_MOVIE_FADE_IN);
gameMoviePlay(MOVIE_INTRO, 0);
gameMoviePlay(MOVIE_CREDITS, 0);
@ -207,7 +222,7 @@ int falloutMain(int argc, char** argv)
gameMoviePlay(MOVIE_ELDER, GAME_MOVIE_STOP_MUSIC);
randomSeedPrerandom(-1);
// SFALL: Override starting map.
// SFALL: Override starting map.
char* mapName = NULL;
if (configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_STARTING_MAP_KEY, &mapName)) {
if (*mapName == '\0') {
@ -273,8 +288,8 @@ int falloutMain(int argc, char** argv)
case MAIN_MENU_TIMEOUT:
debugPrint("Main menu timed-out\n");
// FALLTHROUGH
case MAIN_MENU_3:
// _main_selfrun_play();
case MAIN_MENU_SCREENSAVER:
_main_selfrun_play();
break;
case MAIN_MENU_OPTIONS:
mainMenuWindowHide(false);
@ -303,7 +318,7 @@ int falloutMain(int argc, char** argv)
backgroundSoundDelete();
break;
case MAIN_MENU_SELFRUN:
// _main_selfrun_record();
_main_selfrun_record();
break;
}
}
@ -329,7 +344,7 @@ static bool falloutInit(int argc, char** argv)
_main_selfrun_exit();
}
if (_selfrun_get_list(&_main_selfrun_list, &_main_selfrun_count) == 0) {
if (selfrunInitFileList(&_main_selfrun_list, &_main_selfrun_count) == 0) {
_main_selfrun_index = 0;
}
@ -408,7 +423,7 @@ static void mainLoop(FpsLimiter& fpsLimiter)
static void _main_selfrun_exit()
{
if (_main_selfrun_list != NULL) {
_selfrun_free_list(&_main_selfrun_list);
selfrunFreeFileList(&_main_selfrun_list);
}
_main_selfrun_count = 0;
@ -416,6 +431,89 @@ static void _main_selfrun_exit()
_main_selfrun_list = NULL;
}
// 0x480F64
static void _main_selfrun_record()
{
SelfrunData selfrunData;
bool ready = false;
char** fileList;
int fileListLength = fileNameListInit("maps\\*.map", &fileList, 0, 0);
if (fileListLength != 0) {
int selectedFileIndex = _win_list_select("Select Map", fileList, fileListLength, 0, 80, 80, 0x10000 | 0x100 | 4);
if (selectedFileIndex != -1) {
// NOTE: It's size is likely 13 chars (on par with SelfrunData
// fields), but due to the padding it takes 16 chars on stack.
char recordingName[SELFRUN_RECORDING_FILE_NAME_LENGTH];
recordingName[0] = '\0';
if (_win_get_str(recordingName, sizeof(recordingName) - 2, "Enter name for recording (8 characters max, no extension):", 100, 100) == 0) {
memset(&selfrunData, 0, sizeof(selfrunData));
if (selfrunPrepareRecording(recordingName, fileList[selectedFileIndex], &selfrunData) == 0) {
ready = true;
}
}
}
fileNameListFree(&fileList, 0);
}
if (ready) {
mainMenuWindowHide(true);
mainMenuWindowFree();
backgroundSoundDelete();
randomSeedPrerandom(0xBEEFFEED);
gameReset();
_proto_dude_init("premade\\combat.gcd");
_main_load_new(selfrunData.mapFileName);
selfrunRecordingLoop(&selfrunData);
paletteFadeTo(gPaletteWhite);
objectHide(gDude, NULL);
_map_exit();
gameReset();
mainMenuWindowInit();
if (_main_selfrun_list != NULL) {
_main_selfrun_exit();
}
if (selfrunInitFileList(&_main_selfrun_list, &_main_selfrun_count) == 0) {
_main_selfrun_index = 0;
}
}
}
// 0x48109C
static void _main_selfrun_play()
{
if (!gMainMenuScreensaverCycle && _main_selfrun_count > 0) {
SelfrunData selfrunData;
if (selfrunPreparePlayback(_main_selfrun_list[_main_selfrun_index], &selfrunData) == 0) {
mainMenuWindowHide(true);
mainMenuWindowFree();
backgroundSoundDelete();
randomSeedPrerandom(0xBEEFFEED);
gameReset();
_proto_dude_init("premade\\combat.gcd");
_main_load_new(selfrunData.mapFileName);
selfrunPlaybackLoop(&selfrunData);
paletteFadeTo(gPaletteWhite);
objectHide(gDude, NULL);
_map_exit();
gameReset();
mainMenuWindowInit();
}
_main_selfrun_index++;
if (_main_selfrun_index >= _main_selfrun_count) {
_main_selfrun_index = 0;
}
} else {
mainMenuWindowHide(true);
gameMoviePlay(MOVIE_INTRO, GAME_MOVIE_PAUSE_MUSIC);
}
gMainMenuScreensaverCycle = !gMainMenuScreensaverCycle;
}
// 0x48118C
static void showDeath()
{
@ -445,7 +543,7 @@ static void showDeath()
// DEATH.FRM
CacheEntry* backgroundHandle;
int fid = buildFid(6, 309, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 309, 0, 0, 0);
unsigned char* background = artLockFrameData(fid, 0, 0, &backgroundHandle);
if (background == NULL) {
break;
@ -591,32 +689,17 @@ static int _mainDeathGrabTextFile(const char* fileName, char* dest)
// 0x481598
static int _mainDeathWordWrap(char* text, int width, short* beginnings, short* count)
{
// TODO: Probably wrong.
while (true) {
char* p = text;
while (*p != ':') {
if (*p != '\0') {
p++;
if (*p == ':') {
break;
}
if (*p != '\0') {
continue;
}
}
p = NULL;
char* sep = strchr(text, ':');
if (sep == NULL) {
break;
}
if (p == NULL) {
if (sep - 1 < text) {
break;
}
if (p - 1 < text) {
break;
}
p[0] = ' ';
p[-1] = ' ';
sep[0] = ' ';
sep[-1] = ' ';
}
if (wordWrap(text, width, beginnings, count) == -1) {
@ -671,7 +754,7 @@ static int mainMenuWindowInit()
gMainMenuWindowBuffer = windowGetBuffer(gMainMenuWindow);
// mainmenu.frm
int backgroundFid = buildFid(6, 140, 0, 0, 0);
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 140, 0, 0, 0);
gMainMenuBackgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &gMainMenuBackgroundFrmHandle);
if (gMainMenuBackgroundFrmData == NULL) {
mainMenuWindowFree();
@ -692,7 +775,7 @@ static int mainMenuWindowInit()
int fontSettings = _colorTable[21091], fontSettingsSFall = 0;
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_FONT_COLOR_KEY, &fontSettingsSFall);
if (fontSettingsSFall && !(fontSettingsSFall & 0x010000))
fontSettings = fontSettingsSFall & 0xFF;
fontSettings = fontSettingsSFall & 0xFF;
// SFALL: Allow to move copyright text
int offsetX = 0, offsetY = 0;
@ -717,7 +800,7 @@ static int mainMenuWindowInit()
windowDrawText(gMainMenuWindow, version, 0, 615 - len, 460, fontSettings | 0x06000000);
// menuup.frm
fid = buildFid(6, 299, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 299, 0, 0, 0);
gMainMenuButtonUpFrmData = artLockFrameData(fid, 0, 0, &gMainMenuButtonUpFrmHandle);
if (gMainMenuButtonUpFrmData == NULL) {
mainMenuWindowFree();
@ -725,7 +808,7 @@ static int mainMenuWindowInit()
}
// menudown.frm
fid = buildFid(6, 300, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 300, 0, 0, 0);
gMainMenuButtonDownFrmData = artLockFrameData(fid, 0, 0, &gMainMenuButtonDownFrmHandle);
if (gMainMenuButtonDownFrmData == NULL) {
mainMenuWindowFree();
@ -900,7 +983,7 @@ static int mainMenuWindowHandleEvents(FpsLimiter& fpsLimiter)
} else if (keyCode == KEY_MINUS || keyCode == KEY_UNDERSCORE) {
brightnessDecrease();
} else if (keyCode == KEY_UPPERCASE_D || keyCode == KEY_LOWERCASE_D) {
rc = MAIN_MENU_3;
rc = MAIN_MENU_SCREENSAVER;
continue;
} else if (keyCode == 1111) {
if (!(mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT)) {

View File

@ -33,6 +33,7 @@
#include "text_object.h"
#include "tile.h"
#include "window_manager.h"
#include "window_manager_private.h"
#include "world_map.h"
#include <stdio.h>
@ -922,7 +923,7 @@ static int mapLoad(File* stream)
}
Object* object;
int fid = buildFid(5, 12, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_MISC, 12, 0, 0, 0);
objectCreateWithFidPid(&object, fid, -1);
object->flags |= (OBJECT_LIGHT_THRU | OBJECT_TEMPORARY | OBJECT_HIDDEN);
objectSetLocation(object, 1, 0, NULL);
@ -1027,8 +1028,8 @@ int mapLoadSaved(char* fileName)
int rc = mapLoadByName(mapName);
if (gameTimeGetTime() >= gMapHeader.field_38) {
if (((gameTimeGetTime() - gMapHeader.field_38) / 36000) >= 24) {
if (gameTimeGetTime() >= gMapHeader.lastVisitTime) {
if (((gameTimeGetTime() - gMapHeader.lastVisitTime) / GAME_TIME_TICKS_PER_HOUR) >= 24) {
objectUnjamAll();
}
@ -1061,37 +1062,31 @@ static int _map_age_dead_critters()
return 0;
}
int v4 = (gameTimeGetTime() - gMapHeader.field_38) / 36000;
if (v4 == 0) {
int hoursSinceLastVisit = (gameTimeGetTime() - gMapHeader.lastVisitTime) / GAME_TIME_TICKS_PER_HOUR;
if (hoursSinceLastVisit == 0) {
return 0;
}
Object* obj = objectFindFirst();
while (obj != NULL) {
if (obj->pid >> 24 == OBJ_TYPE_CRITTER
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER
&& obj != gDude
&& !objectIsPartyMember(obj)
&& !critterIsDead(obj)) {
obj->data.critter.combat.maneuver &= 0x04;
if (critterGetKillType(obj) != KILL_TYPE_ROBOT && _critter_flag_check(obj->pid, 512) == 0) {
_critter_heal_hours(obj, v4);
obj->data.critter.combat.maneuver &= ~CRITTER_MANUEVER_FLEEING;
if (critterGetKillType(obj) != KILL_TYPE_ROBOT && _critter_flag_check(obj->pid, CRITTER_FLAG_0x200) == 0) {
_critter_heal_hours(obj, hoursSinceLastVisit);
}
}
obj = objectFindNext();
}
int v20;
if (v4 <= 336) {
if (v4 > 144) {
v20 = 1;
} else {
v20 = 0;
}
int agingType;
if (hoursSinceLastVisit > 6 * 24) {
agingType = 1;
} else if (hoursSinceLastVisit > 14 * 24) {
agingType = 2;
} else {
v20 = 2;
}
if (v20 == 0) {
return 0;
}
@ -1101,10 +1096,10 @@ static int _map_age_dead_critters()
obj = objectFindFirst();
while (obj != NULL) {
int type = obj->pid >> 24;
int type = PID_TYPE(obj->pid);
if (type == OBJ_TYPE_CRITTER) {
if (obj != gDude && critterIsDead(obj)) {
if (critterGetKillType(obj) != KILL_TYPE_ROBOT && _critter_flag_check(obj->pid, 512) == 0) {
if (critterGetKillType(obj) != KILL_TYPE_ROBOT && _critter_flag_check(obj->pid, CRITTER_FLAG_0x200) == 0) {
objects[count++] = obj;
if (count >= capacity) {
@ -1117,7 +1112,7 @@ static int _map_age_dead_critters()
}
}
}
} else if (v20 == 2 && type == OBJ_TYPE_MISC && obj->pid == 0x500000B) {
} else if (agingType == 2 && type == OBJ_TYPE_MISC && obj->pid == 0x500000B) {
objects[count++] = obj;
if (count >= capacity) {
capacity *= 2;
@ -1134,18 +1129,18 @@ static int _map_age_dead_critters()
int rc = 0;
for (int index = 0; index < count; index++) {
Object* obj = objects[index];
if (obj->pid >> 24 == OBJ_TYPE_CRITTER) {
if (_critter_flag_check(obj->pid, 64) == 0) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
if (_critter_flag_check(obj->pid, CRITTER_FLAG_0x40) == 0) {
_item_drop_all(obj, obj->tile);
}
Object* a1;
if (objectCreateWithPid(&a1, 0x5000004) == -1) {
Object* blood;
if (objectCreateWithPid(&blood, 0x5000004) == -1) {
rc = -1;
break;
}
objectSetLocation(a1, obj->tile, obj->elevation, NULL);
objectSetLocation(blood, obj->tile, obj->elevation, NULL);
Proto* proto;
protoGetProto(obj->pid, &proto);
@ -1160,7 +1155,7 @@ static int _map_age_dead_critters()
}
}
objectSetFrame(a1, frame, NULL);
objectSetFrame(blood, frame, NULL);
}
reg_anim_clear(obj);
@ -1264,7 +1259,7 @@ static void _map_fix_critter_combat_data()
continue;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
continue;
}
@ -1327,13 +1322,13 @@ static int _map_save_file(File* stream)
for (tile = 0; tile < SQUARE_GRID_SIZE; tile++) {
int fid;
fid = buildFid(4, _square[elevation]->field_0[tile] & 0xFFF, 0, 0, 0);
if (fid != buildFid(4, 1, 0, 0, 0)) {
fid = buildFid(OBJ_TYPE_TILE, _square[elevation]->field_0[tile] & 0xFFF, 0, 0, 0);
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
break;
}
fid = buildFid(4, (_square[elevation]->field_0[tile] >> 16) & 0xFFF, 0, 0, 0);
if (fid != buildFid(4, 1, 0, 0, 0)) {
fid = buildFid(OBJ_TYPE_TILE, (_square[elevation]->field_0[tile] >> 16) & 0xFFF, 0, 0, 0);
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
break;
}
}
@ -1383,14 +1378,12 @@ static int _map_save_file(File* stream)
if (scriptSaveAll(stream) == -1) {
sprintf(err, "Error saving scripts in %s", gMapHeader.name);
// TODO: Incomplete.
// _win_msg(err, 80, 80, _colorTable[31744]);
_win_msg(err, 80, 80, _colorTable[31744]);
}
if (objectSaveAll(stream) == -1) {
sprintf(err, "Error saving objects in %s", gMapHeader.name);
// TODO: Incomplete.
// _win_msg(err, 80, 80, _colorTable[31744]);
_win_msg(err, 80, 80, _colorTable[31744]);
}
scriptsEnable();
@ -1424,7 +1417,7 @@ int _map_save_in_game(bool a1)
}
gMapHeader.flags |= 0x01;
gMapHeader.field_38 = gameTimeGetTime();
gMapHeader.lastVisitTime = gameTimeGetTime();
char name[16];
@ -1545,9 +1538,9 @@ static void _map_place_dude_and_mouse()
_obj_clear_seen();
if (gDude != NULL) {
if (((gDude->fid & 0xFF0000) >> 16) != 0) {
if (FID_ANIM_TYPE(gDude->fid) != ANIM_STAND) {
objectSetFrame(gDude, 0, 0);
gDude->fid = buildFid(1, gDude->fid & 0xFFF, ANIM_STAND, (gDude->fid & 0xF000) >> 12, gDude->rotation + 1);
gDude->fid = buildFid(OBJ_TYPE_CRITTER, gDude->fid & 0xFFF, ANIM_STAND, (gDude->fid & 0xF000) >> 12, gDude->rotation + 1);
}
if (gDude->tile == -1) {
@ -1577,11 +1570,11 @@ static void _square_reset()
// check subsequent calls.
int fid = *p;
fid &= ~0xFFFF;
*p = ((buildFid(4, 1, 0, 0, 0) & 0xFFF | (((fid >> 16) & 0xF000) >> 12)) << 16) | (fid & 0xFFFF);
*p = ((buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) & 0xFFF | (((fid >> 16) & 0xF000) >> 12)) << 16) | (fid & 0xFFFF);
fid = *p;
int v3 = (fid & 0xF000) >> 12;
int v4 = (buildFid(4, 1, 0, 0, 0) & 0xFFF) | v3;
int v4 = (buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) & 0xFFF) | v3;
fid &= ~0xFFFF;
@ -1642,7 +1635,7 @@ static int mapHeaderWrite(MapHeader* ptr, File* stream)
if (fileWriteInt32(stream, ptr->darkness) == -1) return -1;
if (fileWriteInt32(stream, ptr->globalVariablesCount) == -1) return -1;
if (fileWriteInt32(stream, ptr->field_34) == -1) return -1;
if (fileWriteInt32(stream, ptr->field_38) == -1) return -1;
if (fileWriteInt32(stream, ptr->lastVisitTime) == -1) return -1;
if (fileWriteInt32List(stream, ptr->field_3C, 44) == -1) return -1;
return 0;
@ -1662,7 +1655,7 @@ static int mapHeaderRead(MapHeader* ptr, File* stream)
if (fileReadInt32(stream, &(ptr->darkness)) == -1) return -1;
if (fileReadInt32(stream, &(ptr->globalVariablesCount)) == -1) return -1;
if (fileReadInt32(stream, &(ptr->field_34)) == -1) return -1;
if (fileReadInt32(stream, &(ptr->field_38)) == -1) return -1;
if (fileReadInt32(stream, &(ptr->lastVisitTime)) == -1) return -1;
if (fileReadInt32List(stream, ptr->field_3C, 44) == -1) return -1;
return 0;

View File

@ -49,7 +49,9 @@ typedef struct MapHeader {
// map_number
int field_34;
int field_38;
// Time in game ticks when PC last visited this map.
int lastVisitTime;
int field_3C[44];
} MapHeader;

View File

@ -1,57 +1,641 @@
#include "mouse_manager.h"
#include "core.h"
#include "datafile.h"
#include "db.h"
#include "debug.h"
#include "memory_manager.h"
#include "platform_compat.h"
#include <string.h>
// 0x5195A8
char* (*_mouseNameMangler)(char*) = _defaultNameMangler;
MouseManagerNameMangler* gMouseManagerNameMangler = mouseManagerNameManglerDefaultImpl;
// 0x5195AC
int (*_rateCallback)() = _defaultRateCallback;
MouseManagerRateProvider* gMouseManagerRateProvider = mouseManagerRateProviderDefaultImpl;
// 0x5195B0
int (*_currentTimeCallback)() = _defaultTimeCallback;
MouseManagerTimeProvider* gMouseManagerTimeProvider = mouseManagerTimeProviderDefaultImpl;
// 0x5195B4
int _curref = 1;
int gMouseManagerCurrentRef = 1;
// 0x63247C
MouseManagerCacheEntry gMouseManagerCache[MOUSE_MGR_CACHE_CAPACITY];
// 0x638DFC
bool gMouseManagerIsAnimating;
// 0x638E00
unsigned char* gMouseManagerCurrentPalette;
// 0x638E04
MouseManagerAnimatedData* gMouseManagerCurrentAnimatedData;
// 0x638E08
unsigned char* gMouseManagerCurrentStaticData;
// 0x638E0C
int gMouseManagerCurrentCacheEntryIndex;
// 0x485250
char* _defaultNameMangler(char* a1)
char* mouseManagerNameManglerDefaultImpl(char* a1)
{
return a1;
}
// 0x485254
int _defaultRateCallback()
int mouseManagerRateProviderDefaultImpl()
{
return 1000;
}
// 0x48525C
int _defaultTimeCallback()
int mouseManagerTimeProviderDefaultImpl()
{
return _get_time();
}
// 0x485288
void _mousemgrSetNameMangler(char* (*func)(char*))
void mouseManagerSetNameMangler(MouseManagerNameMangler* func)
{
_mouseNameMangler = func;
gMouseManagerNameMangler = func;
}
// 0x4852B8
void mouseManagerFreeCacheEntry(MouseManagerCacheEntry* entry)
{
switch (entry->type) {
case MOUSE_MANAGER_MOUSE_TYPE_STATIC:
if (entry->staticData != NULL) {
if (entry->staticData->data != NULL) {
internal_free_safe(entry->staticData->data, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 120
entry->staticData->data = NULL;
}
internal_free_safe(entry->staticData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 123
entry->staticData = NULL;
}
break;
case MOUSE_MANAGER_MOUSE_TYPE_ANIMATED:
if (entry->animatedData != NULL) {
if (entry->animatedData->field_0 != NULL) {
for (int index = 0; index < entry->animatedData->frameCount; index++) {
internal_free_safe(entry->animatedData->field_0[index], __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 134
internal_free_safe(entry->animatedData->field_4[index], __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 135
}
internal_free_safe(entry->animatedData->field_0, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 137
internal_free_safe(entry->animatedData->field_4, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 138
internal_free_safe(entry->animatedData->field_8, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 139
internal_free_safe(entry->animatedData->field_C, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 140
}
internal_free_safe(entry->animatedData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 143
entry->animatedData = NULL;
}
break;
}
entry->type = 0;
entry->fileName[0] = '\0';
}
// 0x4853F8
int mouseManagerInsertCacheEntry(void** data, int type, unsigned char* palette, const char* fileName)
{
int foundIndex = -1;
int index;
for (index = 0; index < MOUSE_MGR_CACHE_CAPACITY; index++) {
MouseManagerCacheEntry* cacheEntry = &(gMouseManagerCache[index]);
if (cacheEntry->type == MOUSE_MANAGER_MOUSE_TYPE_NONE && foundIndex == -1) {
foundIndex = index;
}
if (compat_stricmp(fileName, cacheEntry->fileName) == 0) {
mouseManagerFreeCacheEntry(cacheEntry);
foundIndex = index;
break;
}
}
if (foundIndex != -1) {
index = foundIndex;
}
if (index == MOUSE_MGR_CACHE_CAPACITY) {
int v2 = -1;
int v1 = gMouseManagerCurrentRef;
for (int index = 0; index < MOUSE_MGR_CACHE_CAPACITY; index++) {
MouseManagerCacheEntry* cacheEntry = &(gMouseManagerCache[index]);
if (v1 > cacheEntry->ref) {
v1 = cacheEntry->ref;
v2 = index;
}
}
if (v2 == -1) {
debugPrint("Mouse cache overflow!!!!\n");
exit(1);
}
index = v2;
mouseManagerFreeCacheEntry(&(gMouseManagerCache[index]));
}
MouseManagerCacheEntry* cacheEntry = &(gMouseManagerCache[index]);
cacheEntry->type = type;
memcpy(cacheEntry->palette, palette, sizeof(cacheEntry->palette));
cacheEntry->ref = gMouseManagerCurrentRef++;
strncpy(cacheEntry->fileName, fileName, sizeof(cacheEntry->fileName) - 1);
cacheEntry->field_32C[0] = '\0';
cacheEntry->data = *data;
return index;
}
// NOTE: Inlined.
//
// 0x4853D4
void mouseManagerFlushCache()
{
for (int index = 0; index < MOUSE_MGR_CACHE_CAPACITY; index++) {
mouseManagerFreeCacheEntry(&(gMouseManagerCache[index]));
}
}
// 0x48554C
MouseManagerCacheEntry* mouseManagerFindCacheEntry(const char* fileName, unsigned char** palettePtr, int* a3, int* a4, int* widthPtr, int* heightPtr, int* typePtr)
{
for (int index = 0; index < MOUSE_MGR_CACHE_CAPACITY; index++) {
MouseManagerCacheEntry* cacheEntry = &(gMouseManagerCache[index]);
if (compat_strnicmp(cacheEntry->fileName, fileName, 31) == 0 || compat_strnicmp(cacheEntry->field_32C, fileName, 31) == 0) {
*palettePtr = cacheEntry->palette;
*typePtr = cacheEntry->type;
gMouseManagerCurrentCacheEntryIndex = index;
switch (cacheEntry->type) {
case MOUSE_MANAGER_MOUSE_TYPE_STATIC:
*a3 = cacheEntry->staticData->field_4;
*a4 = cacheEntry->staticData->field_8;
*widthPtr = cacheEntry->staticData->width;
*heightPtr = cacheEntry->staticData->height;
break;
case MOUSE_MANAGER_MOUSE_TYPE_ANIMATED:
*widthPtr = cacheEntry->animatedData->width;
*heightPtr = cacheEntry->animatedData->height;
*a3 = cacheEntry->animatedData->field_8[cacheEntry->animatedData->field_26];
*a4 = cacheEntry->animatedData->field_C[cacheEntry->animatedData->field_26];
break;
}
return cacheEntry;
}
}
return NULL;
}
// 0x48568C
void _initMousemgr()
void mouseManagerInit()
{
mouseSetSensitivity(1.0);
}
// 0x48569C
void mouseManagerExit()
{
mouseSetFrame(NULL, 0, 0, 0, 0, 0, 0);
if (gMouseManagerCurrentStaticData != NULL) {
internal_free_safe(gMouseManagerCurrentStaticData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 243
gMouseManagerCurrentStaticData = NULL;
}
// NOTE: Uninline.
mouseManagerFlushCache();
gMouseManagerCurrentPalette = NULL;
gMouseManagerCurrentAnimatedData = 0;
}
// 0x485704
void mouseManagerUpdate()
{
if (!gMouseManagerIsAnimating) {
return;
}
if (gMouseManagerCurrentAnimatedData == NULL) {
debugPrint("Animating == 1 but curAnim == 0\n");
}
if (gMouseManagerTimeProvider() >= gMouseManagerCurrentAnimatedData->field_1C) {
gMouseManagerCurrentAnimatedData->field_1C = (int)(gMouseManagerCurrentAnimatedData->field_18 / gMouseManagerCurrentAnimatedData->frameCount * gMouseManagerRateProvider() + gMouseManagerTimeProvider());
if (gMouseManagerCurrentAnimatedData->field_24 != gMouseManagerCurrentAnimatedData->field_26) {
int v1 = gMouseManagerCurrentAnimatedData->field_26 + gMouseManagerCurrentAnimatedData->field_20;
if (v1 < 0) {
v1 = gMouseManagerCurrentAnimatedData->frameCount - 1;
} else if (v1 >= gMouseManagerCurrentAnimatedData->frameCount) {
v1 = 0;
}
gMouseManagerCurrentAnimatedData->field_26 = v1;
memcpy(gMouseManagerCurrentAnimatedData->field_0[gMouseManagerCurrentAnimatedData->field_26],
gMouseManagerCurrentAnimatedData->field_4[gMouseManagerCurrentAnimatedData->field_26],
gMouseManagerCurrentAnimatedData->width * gMouseManagerCurrentAnimatedData->height);
sub_42EE84(gMouseManagerCurrentAnimatedData->field_0[gMouseManagerCurrentAnimatedData->field_26],
gMouseManagerCurrentPalette,
gMouseManagerCurrentAnimatedData->width,
gMouseManagerCurrentAnimatedData->height);
mouseSetFrame(gMouseManagerCurrentAnimatedData->field_0[v1],
gMouseManagerCurrentAnimatedData->width,
gMouseManagerCurrentAnimatedData->height,
gMouseManagerCurrentAnimatedData->width,
gMouseManagerCurrentAnimatedData->field_8[v1],
gMouseManagerCurrentAnimatedData->field_C[v1],
0);
}
}
}
// 0x485868
int mouseManagerSetFrame(char* fileName, int a2)
{
char* mangledFileName = gMouseManagerNameMangler(fileName);
unsigned char* palette;
int temp;
int type;
MouseManagerCacheEntry* cacheEntry = mouseManagerFindCacheEntry(fileName, &palette, &temp, &temp, &temp, &temp, &type);
if (cacheEntry != NULL) {
if (type == MOUSE_MANAGER_MOUSE_TYPE_ANIMATED) {
cacheEntry->animatedData->field_24 = a2;
if (cacheEntry->animatedData->field_24 >= cacheEntry->animatedData->field_26) {
int v1 = cacheEntry->animatedData->field_24 - cacheEntry->animatedData->field_26;
int v2 = cacheEntry->animatedData->frameCount + cacheEntry->animatedData->field_26 - cacheEntry->animatedData->field_24;
if (v1 >= v2) {
cacheEntry->animatedData->field_20 = -1;
} else {
cacheEntry->animatedData->field_20 = 1;
}
} else {
int v1 = cacheEntry->animatedData->field_26 - cacheEntry->animatedData->field_24;
int v2 = cacheEntry->animatedData->frameCount + cacheEntry->animatedData->field_24 - cacheEntry->animatedData->field_26;
if (v1 < v2) {
cacheEntry->animatedData->field_20 = -1;
} else {
cacheEntry->animatedData->field_20 = 1;
}
}
if (!gMouseManagerIsAnimating || gMouseManagerCurrentAnimatedData != cacheEntry->animatedData) {
memcpy(cacheEntry->animatedData->field_0[cacheEntry->animatedData->field_26],
cacheEntry->animatedData->field_4[cacheEntry->animatedData->field_26],
cacheEntry->animatedData->width * cacheEntry->animatedData->height);
mouseSetFrame(cacheEntry->animatedData->field_0[cacheEntry->animatedData->field_26],
cacheEntry->animatedData->width,
cacheEntry->animatedData->height,
cacheEntry->animatedData->width,
cacheEntry->animatedData->field_8[cacheEntry->animatedData->field_26],
cacheEntry->animatedData->field_C[cacheEntry->animatedData->field_26],
0);
gMouseManagerIsAnimating = true;
}
gMouseManagerCurrentAnimatedData = cacheEntry->animatedData;
gMouseManagerCurrentPalette = palette;
gMouseManagerCurrentAnimatedData->field_1C = gMouseManagerTimeProvider();
return true;
}
mouseManagerSetMousePointer(fileName);
return true;
}
if (gMouseManagerIsAnimating) {
gMouseManagerCurrentPalette = 0;
gMouseManagerIsAnimating = 0;
gMouseManagerCurrentAnimatedData = 0;
} else {
if (gMouseManagerCurrentStaticData != NULL) {
internal_free_safe(gMouseManagerCurrentStaticData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 337
gMouseManagerCurrentStaticData = NULL;
}
}
File* stream = fileOpen(mangledFileName, "r");
if (stream == NULL) {
debugPrint("mouseSetFrame: couldn't find %s\n", mangledFileName);
return false;
}
char string[80];
fileReadString(string, sizeof(string), stream);
if (compat_strnicmp(string, "anim", 4) != 0) {
fileClose(stream);
mouseManagerSetMousePointer(fileName);
return true;
}
// NOTE: Uninline.
char* sep = strchr(string, ' ');
if (sep == NULL) {
// FIXME: Leaks stream.
return false;
}
int v3;
float v4;
sscanf(sep + 1, "%d %f", &v3, &v4);
MouseManagerAnimatedData* animatedData = (MouseManagerAnimatedData*)internal_malloc_safe(sizeof(*animatedData), __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 359
animatedData->field_0 = (unsigned char**)internal_malloc_safe(sizeof(*animatedData->field_0) * v3, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 360
animatedData->field_4 = (unsigned char**)internal_malloc_safe(sizeof(*animatedData->field_4) * v3, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 361
animatedData->field_8 = (int*)internal_malloc_safe(sizeof(*animatedData->field_8) * v3, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 362
animatedData->field_C = (int*)internal_malloc_safe(sizeof(*animatedData->field_8) * v3, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 363
animatedData->field_18 = v4;
animatedData->field_1C = gMouseManagerTimeProvider();
animatedData->field_26 = 0;
animatedData->field_24 = a2;
animatedData->frameCount = v3;
if (animatedData->frameCount / 2 <= a2) {
animatedData->field_20 = -1;
} else {
animatedData->field_20 = 1;
}
int width;
int height;
for (int index = 0; index < v3; index++) {
string[0] = '\0';
fileReadString(string, sizeof(string), stream);
if (string[0] == '\0') {
debugPrint("Not enough frames in %s, got %d, needed %d", mangledFileName, index, v3);
break;
}
// NOTE: Uninline.
char* sep = strchr(string, ' ');
if (sep == NULL) {
debugPrint("Bad line %s in %s\n", string, fileName);
// FIXME: Leaking stream.
return false;
}
*sep = '\0';
int v5;
int v6;
sscanf(sep + 1, "%d %d", &v5, &v6);
animatedData->field_4[index] = datafileReadRaw(gMouseManagerNameMangler(string), &width, &height);
animatedData->field_0[index] = (unsigned char*)internal_malloc_safe(width * height, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 390
memcpy(animatedData->field_0[index], animatedData->field_4[index], width * height);
sub_42EE84(animatedData->field_0[index], datafileGetPalette(), width, height);
animatedData->field_8[index] = v5;
animatedData->field_C[index] = v6;
}
fileClose(stream);
animatedData->width = width;
animatedData->height = height;
gMouseManagerCurrentCacheEntryIndex = mouseManagerInsertCacheEntry(reinterpret_cast<void**>(&animatedData), MOUSE_MANAGER_MOUSE_TYPE_ANIMATED, datafileGetPalette(), fileName);
strncpy(gMouseManagerCache[gMouseManagerCurrentCacheEntryIndex].field_32C, fileName, 31);
gMouseManagerCurrentAnimatedData = animatedData;
gMouseManagerCurrentPalette = gMouseManagerCache[gMouseManagerCurrentCacheEntryIndex].palette;
gMouseManagerIsAnimating = true;
mouseSetFrame(animatedData->field_0[0],
animatedData->width,
animatedData->height,
animatedData->width,
animatedData->field_8[0],
animatedData->field_C[0],
0);
return true;
}
// 0x485E58
bool mouseManagerSetMouseShape(char* fileName, int a2, int a3)
{
unsigned char* palette;
int temp;
int width;
int height;
int type;
MouseManagerCacheEntry* cacheEntry = mouseManagerFindCacheEntry(fileName, &palette, &temp, &temp, &width, &height, &type);
char* mangledFileName = gMouseManagerNameMangler(fileName);
if (cacheEntry == NULL) {
MouseManagerStaticData* staticData;
staticData = (MouseManagerStaticData*)internal_malloc_safe(sizeof(*staticData), __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 430
staticData->data = datafileReadRaw(mangledFileName, &height, &width);
staticData->field_4 = a2;
staticData->field_8 = a3;
staticData->width = width;
staticData->height = height;
gMouseManagerCurrentCacheEntryIndex = mouseManagerInsertCacheEntry(reinterpret_cast<void**>(&staticData), MOUSE_MANAGER_MOUSE_TYPE_STATIC, datafileGetPalette(), fileName);
// NOTE: Original code is slightly different. It obtains address of
// `staticData` and sets it's it into `cacheEntry`, which is a bit
// awkward. Maybe there is more level on indirection was used. Any way
// in order to make code path below unaltered take entire cache entry.
cacheEntry = &(gMouseManagerCache[gMouseManagerCurrentCacheEntryIndex]);
type = MOUSE_MANAGER_MOUSE_TYPE_STATIC;
palette = gMouseManagerCache[gMouseManagerCurrentCacheEntryIndex].palette;
}
switch (type) {
case MOUSE_MANAGER_MOUSE_TYPE_STATIC:
if (gMouseManagerCurrentStaticData != NULL) {
internal_free_safe(gMouseManagerCurrentStaticData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 446
}
gMouseManagerCurrentStaticData = (unsigned char*)internal_malloc_safe(width * height, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 448
memcpy(gMouseManagerCurrentStaticData, cacheEntry->staticData->data, width * height);
sub_42EE84(gMouseManagerCurrentStaticData, palette, width, height);
mouseSetFrame(gMouseManagerCurrentStaticData, width, height, width, a2, a3, 0);
gMouseManagerIsAnimating = false;
break;
case MOUSE_MANAGER_MOUSE_TYPE_ANIMATED:
gMouseManagerCurrentAnimatedData = cacheEntry->animatedData;
gMouseManagerIsAnimating = true;
gMouseManagerCurrentPalette = palette;
break;
}
return true;
}
// 0x486010
bool mouseManagerSetMousePointer(char* fileName)
{
unsigned char* palette;
int v1;
int v2;
int width;
int height;
int type;
MouseManagerCacheEntry* cacheEntry = mouseManagerFindCacheEntry(fileName, &palette, &v1, &v2, &width, &height, &type);
if (cacheEntry != NULL) {
if (gMouseManagerCurrentStaticData != NULL) {
internal_free_safe(gMouseManagerCurrentStaticData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 482
gMouseManagerCurrentStaticData = NULL;
}
gMouseManagerCurrentPalette = NULL;
gMouseManagerIsAnimating = false;
gMouseManagerCurrentAnimatedData = 0;
switch (type) {
case MOUSE_MANAGER_MOUSE_TYPE_STATIC:
gMouseManagerCurrentStaticData = (unsigned char*)internal_malloc_safe(width * height, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 492
memcpy(gMouseManagerCurrentStaticData, cacheEntry->staticData->data, width * height);
sub_42EE84(gMouseManagerCurrentStaticData, palette, width, height);
mouseSetFrame(gMouseManagerCurrentStaticData, width, height, width, v1, v2, 0);
gMouseManagerIsAnimating = false;
break;
case MOUSE_MANAGER_MOUSE_TYPE_ANIMATED:
gMouseManagerCurrentAnimatedData = cacheEntry->animatedData;
gMouseManagerCurrentPalette = palette;
gMouseManagerCurrentAnimatedData->field_26 = 0;
gMouseManagerCurrentAnimatedData->field_24 = 0;
mouseSetFrame(gMouseManagerCurrentAnimatedData->field_0[0],
gMouseManagerCurrentAnimatedData->width,
gMouseManagerCurrentAnimatedData->height,
gMouseManagerCurrentAnimatedData->width,
gMouseManagerCurrentAnimatedData->field_8[0],
gMouseManagerCurrentAnimatedData->field_C[0],
0);
gMouseManagerIsAnimating = true;
break;
}
return true;
}
char* dot = strrchr(fileName, '.');
if (dot != NULL && compat_stricmp(dot + 1, "mou") == 0) {
return mouseManagerSetMouseShape(fileName, 0, 0);
}
char* mangledFileName = gMouseManagerNameMangler(fileName);
File* stream = fileOpen(mangledFileName, "r");
if (stream == NULL) {
debugPrint("Can't find %s\n", mangledFileName);
return false;
}
char string[80];
string[0] = '\0';
fileReadString(string, sizeof(string) - 1, stream);
if (string[0] == '\0') {
return false;
}
bool rc;
if (compat_strnicmp(string, "anim", 4) == 0) {
fileClose(stream);
rc = mouseManagerSetFrame(fileName, 0);
} else {
// NOTE: Uninline.
char* sep = strchr(string, ' ');
if (sep != NULL) {
return 0;
}
*sep = '\0';
int v3;
int v4;
sscanf(sep + 1, "%d %d", &v3, &v4);
fileClose(stream);
rc = mouseManagerSetMouseShape(string, v3, v4);
}
strncpy(gMouseManagerCache[gMouseManagerCurrentCacheEntryIndex].field_32C, fileName, 31);
return rc;
}
// 0x4862AC
void mouseManagerResetMouse()
{
MouseManagerCacheEntry* entry = &(gMouseManagerCache[gMouseManagerCurrentCacheEntryIndex]);
int imageWidth;
int imageHeight;
switch (entry->type) {
case MOUSE_MANAGER_MOUSE_TYPE_STATIC:
imageWidth = entry->staticData->width;
imageHeight = entry->staticData->height;
break;
case MOUSE_MANAGER_MOUSE_TYPE_ANIMATED:
imageWidth = entry->animatedData->width;
imageHeight = entry->animatedData->height;
break;
}
switch (entry->type) {
case MOUSE_MANAGER_MOUSE_TYPE_STATIC:
if (gMouseManagerCurrentStaticData != NULL) {
if (gMouseManagerCurrentStaticData != NULL) {
internal_free_safe(gMouseManagerCurrentStaticData, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 572
}
gMouseManagerCurrentStaticData = (unsigned char*)internal_malloc_safe(imageWidth * imageHeight, __FILE__, __LINE__); // "..\\int\\MOUSEMGR.C", 574
memcpy(gMouseManagerCurrentStaticData, entry->staticData->data, imageWidth * imageHeight);
sub_42EE84(gMouseManagerCurrentStaticData, entry->palette, imageWidth, imageHeight);
mouseSetFrame(gMouseManagerCurrentStaticData,
imageWidth,
imageHeight,
imageWidth,
entry->staticData->field_4,
entry->staticData->field_8,
0);
} else {
debugPrint("Hm, current mouse type is M_STATIC, but no current mouse pointer\n");
}
break;
case MOUSE_MANAGER_MOUSE_TYPE_ANIMATED:
if (gMouseManagerCurrentAnimatedData != NULL) {
for (int index = 0; index < gMouseManagerCurrentAnimatedData->frameCount; index++) {
memcpy(gMouseManagerCurrentAnimatedData->field_0[index], gMouseManagerCurrentAnimatedData->field_4[index], imageWidth * imageHeight);
sub_42EE84(gMouseManagerCurrentAnimatedData->field_0[index], entry->palette, imageWidth, imageHeight);
}
mouseSetFrame(gMouseManagerCurrentAnimatedData->field_0[gMouseManagerCurrentAnimatedData->field_26],
imageWidth,
imageHeight,
imageWidth,
gMouseManagerCurrentAnimatedData->field_8[gMouseManagerCurrentAnimatedData->field_26],
gMouseManagerCurrentAnimatedData->field_C[gMouseManagerCurrentAnimatedData->field_26],
0);
} else {
debugPrint("Hm, current mouse type is M_ANIMATED, but no current mouse pointer\n");
}
}
}
// 0x4865C4
void _mouseHide()
void mouseManagerHideMouse()
{
mouseHideCursor();
}
// 0x4865CC
void _mouseShow()
void mouseManagerShowMouse()
{
mouseShowCursor();
}

View File

@ -1,16 +1,81 @@
#ifndef MOUSE_MANAGER_H
#define MOUSE_MANAGER_H
extern char* (*_mouseNameMangler)(char*);
extern int (*_rateCallback)();
extern int (*_currentTimeCallback)();
#define MOUSE_MGR_CACHE_CAPACITY 32
char* _defaultNameMangler(char* a1);
int _defaultRateCallback();
int _defaultTimeCallback();
void _mousemgrSetNameMangler(char* (*func)(char*));
void _initMousemgr();
void _mouseHide();
void _mouseShow();
typedef char*(MouseManagerNameMangler)(char* fileName);
typedef int(MouseManagerRateProvider)();
typedef int(MouseManagerTimeProvider)();
typedef enum MouseManagerMouseType {
MOUSE_MANAGER_MOUSE_TYPE_NONE,
MOUSE_MANAGER_MOUSE_TYPE_STATIC,
MOUSE_MANAGER_MOUSE_TYPE_ANIMATED,
} MouseManagerMouseType;
typedef struct MouseManagerStaticData {
unsigned char* data;
int field_4;
int field_8;
int width;
int height;
} MouseManagerStaticData;
typedef struct MouseManagerAnimatedData {
unsigned char** field_0;
unsigned char** field_4;
int* field_8;
int* field_C;
int width;
int height;
float field_18;
int field_1C;
int field_20;
signed char field_24;
signed char frameCount;
signed char field_26;
} MouseManagerAnimatedData;
typedef struct MouseManagerCacheEntry {
union {
void* data;
MouseManagerStaticData* staticData;
MouseManagerAnimatedData* animatedData;
};
int type;
unsigned char palette[256 * 3];
int ref;
char fileName[32];
char field_32C[32];
} MouseManagerCacheEntry;
extern MouseManagerNameMangler* gMouseManagerNameMangler;
extern MouseManagerRateProvider* gMouseManagerRateProvider;
extern MouseManagerTimeProvider* gMouseManagerTimeProvider;
extern MouseManagerCacheEntry gMouseManagerCache[MOUSE_MGR_CACHE_CAPACITY];
extern bool gMouseManagerIsAnimating;
extern unsigned char* gMouseManagerCurrentPalette;
extern MouseManagerAnimatedData* gMouseManagerCurrentAnimatedData;
extern unsigned char* gMouseManagerCurrentStaticData;
extern int gMouseManagerCurrentCacheEntryIndex;
char* mouseManagerNameManglerDefaultImpl(char* a1);
int mouseManagerRateProviderDefaultImpl();
int mouseManagerTimeProviderDefaultImpl();
void mouseManagerSetNameMangler(MouseManagerNameMangler* func);
void mouseManagerFreeCacheEntry(MouseManagerCacheEntry* entry);
int mouseManagerInsertCacheEntry(void** data, int type, unsigned char* palette, const char* fileName);
void mouseManagerFlushCache();
MouseManagerCacheEntry* mouseManagerFindCacheEntry(const char* fileName, unsigned char** palettePtr, int* a3, int* a4, int* widthPtr, int* heightPtr, int* typePtr);
void mouseManagerInit();
void mouseManagerExit();
void mouseManagerUpdate();
int mouseManagerSetFrame(char* fileName, int a2);
bool mouseManagerSetMouseShape(char* fileName, int a2, int a3);
bool mouseManagerSetMousePointer(char* fileName);
void mouseManagerResetMouse();
void mouseManagerHideMouse();
void mouseManagerShowMouse();
#endif /* MOUSE_MANAGER_H */

View File

@ -14,6 +14,7 @@
#include "pointer_registry.h"
#include "sound.h"
#include "text_font.h"
#include "window.h"
#include "window_manager.h"
#include <string.h>
@ -29,11 +30,14 @@ typedef struct MovieSubtitleListNode {
static void* movieMallocImpl(size_t size);
static void movieFreeImpl(void* ptr);
static bool movieReadImpl(int fileHandle, void* buf, int count);
static void movieDirectImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
static void movieBufferedImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
static int _movieScaleSubRectAlpha(int a1);
static int _blitAlpha(int win, unsigned char* a2, int a3, int a4, int a5);
static int _blitNormal(int win, int a2, int a3, int a4, int a5);
static void movieDirectImpl(SDL_Surface* surface, int srcWidth, int srcHeight, int srcX, int srcY, int destWidth, int destHeight, int a8, int a9);
static void movieBufferedImpl(SDL_Surface* surface, int srcWidth, int srcHeight, int srcX, int srcY, int destWidth, int destHeight, int a8, int a9);
static int _movieScaleSubRect(int win, unsigned char* data, int width, int height, int pitch);
static int _movieScaleSubRectAlpha(int win, unsigned char* data, int width, int height, int pitch);
static int _movieScaleWindowAlpha(int win, unsigned char* data, int width, int height, int pitch);
static int _blitAlpha(int win, unsigned char* data, int width, int height, int pitch);
static int _movieScaleWindow(int win, unsigned char* data, int width, int height, int pitch);
static int _blitNormal(int win, unsigned char* data, int width, int height, int pitch);
static void movieSetPaletteEntriesImpl(unsigned char* palette, int start, int end);
static int _noop();
static void _cleanupMovie(int a1);
@ -51,6 +55,30 @@ static int gMovieWindow = -1;
// 0x5195BC
static int gMovieSubtitlesFont = -1;
// 0x5195C0
static MovieBlitFunc* gMovieBlitFuncs[2][2][2] = {
{
{
_blitNormal,
_blitNormal,
},
{
_movieScaleWindow,
_movieScaleSubRect,
},
},
{
{
_blitAlpha,
_blitAlpha,
},
{
_movieScaleWindowAlpha,
_movieScaleSubRectAlpha,
},
},
};
// 0x5195E0
static MovieSetPaletteEntriesProc* gMovieSetPaletteEntriesProc = _setSystemPaletteEntries;
@ -72,19 +100,21 @@ static Rect _movieRect;
// 0x638E30
static void (*_movieCallback)();
// 0x638E34
MovieEndFunc* _endMovieFunc;
// 0x638E38
static MovieSetPaletteProc* gMoviePaletteProc;
// NOTE: Some kind of callback which was intended to change movie file path
// in place during opening movie file to find subsitutions. This callback is
// never set.
//
// 0x638E3C
static int (*_failedOpenFunc)(char* filePath);
static MovieFailedOpenFunc* _failedOpenFunc;
// 0x638E40
static MovieBuildSubtitleFilePathProc* gMovieBuildSubtitleFilePathProc;
// 0x638E44
static MovieStartFunc* _startMovieFunc;
// 0x638E48
static int _subtitleW;
@ -103,6 +133,9 @@ static int _lastMovieSY;
// 0x638E5C
static int _movieScaleFlag;
// 0x638E60
static MoviePreDrawFunc* _moviePreDrawFunc;
// 0x638E64
static int _lastMovieH;
@ -134,7 +167,7 @@ static int _movieH;
static int _movieOffset;
// 0x638E8C
static void (*_movieCaptureFrameFunc)(void*, int, int, int, int, int);
static MovieCaptureFrameProc* _movieCaptureFrameFunc;
// 0x638E90
static unsigned char* _lastMovieBuffer;
@ -143,7 +176,7 @@ static unsigned char* _lastMovieBuffer;
static int _movieW;
// 0x638E98
static void (*_movieFrameGrabFunc)();
static MovieFrameGrabProc* _movieFrameGrabFunc;
// 0x638EA0
static int _subtitleH;
@ -172,6 +205,31 @@ static unsigned char* _alphaBuf;
static SDL_Surface* gMovieSdlSurface = NULL;
static int gMovieFileStreamPointerKey = 0;
// NOTE: Unused.
//
// 0x4865E0
void _movieSetPreDrawFunc(MoviePreDrawFunc* preDrawFunc)
{
_moviePreDrawFunc = preDrawFunc;
}
// NOTE: Unused.
//
// 0x4865E8
void _movieSetFailedOpenFunc(MovieFailedOpenFunc* failedOpenFunc)
{
_failedOpenFunc = failedOpenFunc;
}
// NOTE: Unused.
//
// 0x4865F0
void _movieSetFunc(MovieStartFunc* startFunc, MovieEndFunc* endFunc)
{
_startMovieFunc = startFunc;
_endMovieFunc = endFunc;
}
// 0x4865FC
static void* movieMallocImpl(size_t size)
{
@ -249,7 +307,14 @@ static void movieDirectImpl(SDL_Surface* surface, int srcWidth, int srcHeight, i
if (_movieCaptureFrameFunc != NULL) {
if (SDL_LockSurface(surface) == 0) {
_movieCaptureFrameFunc(surface->pixels, srcWidth, destRect.x, destRect.y, destRect.w, destRect.h);
_movieCaptureFrameFunc(static_cast<unsigned char*>(surface->pixels),
srcWidth,
srcHeight,
surface->pitch,
destRect.x,
destRect.y,
destRect.w,
destRect.h);
SDL_UnlockSurface(surface);
}
}
@ -269,8 +334,6 @@ static void movieDirectImpl(SDL_Surface* surface, int srcWidth, int srcHeight, i
// 0x486900
static void movieBufferedImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
{
int v13;
if (gMovieWindow == -1) {
return;
}
@ -290,55 +353,135 @@ static void movieBufferedImpl(SDL_Surface* a1, int a2, int a3, int a4, int a5, i
}
if (_movieCaptureFrameFunc != NULL) {
// TODO: Ignore, _movieCaptureFrameFunc is never set.
// _movieCaptureFrameFunc()
_movieCaptureFrameFunc(static_cast<unsigned char*>(a1->pixels), a2, a3, a1->pitch, _movieRect.left, _movieRect.top, a6, a7);
}
if (_movieFrameGrabFunc != NULL) {
// TODO: Ignore, _movieFrameGrabFunc is never set.
// _movieFrameGrabFunc();
_movieFrameGrabFunc(static_cast<unsigned char*>(a1->pixels), a2, a3, a1->pitch);
} else {
v13 = 4 * _movieSubRectFlag + 8 * _movieScaleFlag + 16 * _movieAlphaFlag;
// TODO: Incomplete.
MovieBlitFunc* func = gMovieBlitFuncs[_movieAlphaFlag][_movieScaleFlag][_movieSubRectFlag];
if (func(gMovieWindow, static_cast<unsigned char*>(a1->pixels), a2, a3, a1->pitch) != 0) {
if (_moviePreDrawFunc != NULL) {
_moviePreDrawFunc(gMovieWindow, &_movieRect);
}
windowRefreshRect(gMovieWindow, &_movieRect);
}
}
SDL_UnlockSurface(a1);
}
// NOTE: Unused.
//
// 0x486A98
void _movieSetFrameGrabFunc(MovieFrameGrabProc* proc)
{
_movieFrameGrabFunc = proc;
}
// NOTE: Unused.
//
// 0x486AA0
void _movieSetCaptureFrameFunc(MovieCaptureFrameProc* func)
{
_movieCaptureFrameFunc = func;
}
// 0x486B68
int _movieScaleSubRect(int win, unsigned char* data, int width, int height, int pitch)
{
int windowWidth = windowGetWidth(win);
unsigned char* windowBuffer = windowGetBuffer(win) + windowWidth * _movieY + _movieX;
if (width * 4 / 3 > _movieW) {
gMovieFlags |= 0x01;
return 0;
}
int v1 = width / 3;
for (int y = 0; y < height; y++) {
int x;
for (x = 0; x < v1; x++) {
unsigned int value = data[0];
value |= data[1] << 8;
value |= data[2] << 16;
value |= data[2] << 24;
*(unsigned int*)windowBuffer = value;
windowBuffer += 4;
data += 3;
}
for (x = x * 3; x < width; x++) {
*windowBuffer++ = *data++;
}
data += pitch - width;
windowBuffer += windowWidth - _movieW;
}
return 1;
}
// 0x486C74
static int _movieScaleSubRectAlpha(int a1)
int _movieScaleSubRectAlpha(int win, unsigned char* data, int width, int height, int pitch)
{
gMovieFlags |= 1;
return 0;
}
// NOTE: Uncollapsed 0x486C74.
int _movieScaleWindowAlpha(int win, unsigned char* data, int width, int height, int pitch)
{
gMovieFlags |= 1;
return 0;
}
// 0x486C80
static int _blitAlpha(int win, unsigned char* a2, int a3, int a4, int a5)
int _blitAlpha(int win, unsigned char* data, int width, int height, int pitch)
{
unsigned char* buf;
int offset;
int windowWidth = windowGetWidth(win);
unsigned char* windowBuffer = windowGetBuffer(win);
_alphaBltBuf(data, width, height, pitch, _alphaWindowBuf, _alphaBuf, windowBuffer + windowWidth * _movieY + _movieX, windowWidth);
return 1;
}
offset = windowGetWidth(win) * _movieY + _movieX;
buf = windowGetBuffer(win);
// 0x486CD4
int _movieScaleWindow(int win, unsigned char* data, int width, int height, int pitch)
{
int windowWidth = windowGetWidth(win);
if (width != 3 * windowWidth / 4) {
gMovieFlags |= 1;
return 0;
}
// TODO: Incomplete.
// _alphaBltBuf(a2, a3, a4, a5, _alphaWindowBuf, _alphaBuf, buf + offset, windowGetWidth(win));
unsigned char* windowBuffer = windowGetBuffer(win);
for (int y = 0; y < height; y++) {
int scaledWidth = width / 3;
for (int x = 0; x < scaledWidth; x++) {
unsigned int value = data[0];
value |= data[1] << 8;
value |= data[2] << 16;
value |= data[3] << 24;
*(unsigned int*)windowBuffer = value;
windowBuffer += 4;
data += 3;
}
data += pitch - width;
}
return 1;
}
// 0x486D84
static int _blitNormal(int win, int a2, int a3, int a4, int a5)
int _blitNormal(int win, unsigned char* data, int width, int height, int pitch)
{
unsigned char* buf;
int offset;
offset = windowGetWidth(win) * _movieY + _movieX;
buf = windowGetBuffer(win);
// TODO: Incomplete.
// _drawScaled(buf + offset, _movieW, _movieH, windowGetWidth(win), a2, a3, a4, a5);
int windowWidth = windowGetWidth(win);
unsigned char* windowBuffer = windowGetBuffer(win);
_drawScaled(windowBuffer + windowWidth * _movieY + _movieX, _movieW, _movieH, windowWidth, data, width, height, pitch);
return 1;
}
@ -373,10 +516,9 @@ static void _cleanupMovie(int a1)
return;
}
// TODO: Probably can be ignored.
// if (_endMovieFunc) {
// _endMovieFunc(_movieW, _movieX, _movieH);
// }
if (_endMovieFunc != NULL) {
_endMovieFunc(gMovieWindow, _movieX, _movieY, _movieW, _movieH);
}
int frame;
int dropped;
@ -579,30 +721,18 @@ static void movieLoadSubtitles(char* filePath)
char* pch;
pch = string;
while (*pch != '\0' && *pch != '\n') {
pch++;
}
if (*pch != '\0') {
pch = strchr(string, '\n');
if (pch != NULL) {
*pch = '\0';
}
pch = string;
while (*pch != '\0' && *pch != '\r') {
pch++;
}
if (*pch != '\0') {
pch = strchr(string, '\r');
if (pch != NULL) {
*pch = '\0';
}
pch = string;
while (*pch != '\0' && *pch != ':') {
pch++;
}
if (*pch != '\0') {
pch = strchr(string, ':');
if (pch != NULL) {
*pch = '\0';
subtitle->num = atoi(string);
subtitle->text = strdup_safe(pch + 1, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1058
@ -737,14 +867,28 @@ static int _movieStart(int win, char* filePath, int (*a3)())
debugPrint("not scaled\n");
}
// TODO: Probably can be ignored, never set.
// if (_startMovieFunc) {
// _startMovieFunc();
// }
if (_startMovieFunc != NULL) {
_startMovieFunc(gMovieWindow);
}
if (_alphaHandle != NULL) {
// TODO: Probably can be ignored, never set.
abort();
int size;
fileReadInt32(_alphaHandle, &size);
short tmp;
fileReadInt16(_alphaHandle, &tmp);
fileReadInt16(_alphaHandle, &tmp);
_alphaBuf = (unsigned char*)internal_malloc_safe(size, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1178
_alphaWindowBuf = (unsigned char*)internal_malloc_safe(_movieH * _movieW, __FILE__, __LINE__); // "..\\int\\MOVIE.C", 1179
unsigned char* windowBuffer = windowGetBuffer(gMovieWindow);
blitBufferToBuffer(windowBuffer + windowGetWidth(gMovieWindow) * _movieY + _movieX,
_movieW,
_movieH,
windowGetWidth(gMovieWindow),
_alphaWindowBuf,
_movieW);
}
_movieRect.left = _movieX;

View File

@ -1,6 +1,8 @@
#ifndef MOVIE_H
#define MOVIE_H
#include "geometry.h"
typedef enum MovieFlags {
MOVIE_FLAG_0x01 = 0x01,
MOVIE_FLAG_0x02 = 0x02,
@ -19,6 +21,13 @@ typedef enum MovieExtendedFlags {
typedef char* MovieBuildSubtitleFilePathProc(char* movieFilePath);
typedef void MovieSetPaletteEntriesProc(unsigned char* palette, int start, int end);
typedef void MovieSetPaletteProc(int frame);
typedef void(MovieFrameGrabProc)(unsigned char* data, int width, int height, int pitch);
typedef void(MovieCaptureFrameProc)(unsigned char* data, int width, int height, int pitch, int movieX, int movieY, int movieWidth, int movieHeight);
typedef int(MovieBlitFunc)(int win, unsigned char* data, int width, int height, int pitch);
typedef void(MoviePreDrawFunc)(int win, Rect* rect);
typedef void(MovieStartFunc)(int win);
typedef void(MovieEndFunc)(int win, int x, int y, int width, int height);
typedef int(MovieFailedOpenFunc)(char* path);
void movieInit();
void movieExit();

View File

@ -715,11 +715,7 @@ static void* _ioRead(int size)
return NULL;
}
if (!gMovieLibReadProc(_io_handle, buf, size)) {
return NULL;
}
return buf;
return gMovieLibReadProc(_io_handle, buf, size) < 1 ? NULL : buf;
}
// 0x4F4D40

View File

@ -89,7 +89,7 @@ static void _nevs_removeprogramreferences(Program* program)
// 0x488418
void _nevs_initonce()
{
_interpretRegisterProgramDeleteCallback(_nevs_removeprogramreferences);
intLibRegisterProgramDeleteCallback(_nevs_removeprogramreferences);
if (gNevs == NULL) {
gNevs = (Nevs*)internal_calloc_safe(sizeof(Nevs), NEVS_COUNT, __FILE__, __LINE__); // "..\\int\\NEVS.C", 131

View File

@ -27,6 +27,10 @@ enum {
OBJ_TYPE_COUNT,
};
#define FID_TYPE(value) ((value) & 0xF000000) >> 24
#define PID_TYPE(value) (value) >> 24
#define SID_TYPE(value) (value) >> 24
typedef enum OutlineType {
OUTLINE_TYPE_HOSTILE = 1,
OUTLINE_TYPE_2 = 2,
@ -66,6 +70,20 @@ typedef enum ObjectFlags {
OBJECT_OPEN_DOOR = OBJECT_SHOOT_THRU | OBJECT_LIGHT_THRU | OBJECT_NO_BLOCK,
} ObjectFlags;
typedef enum CritterFlags {
CRITTER_FLAG_0x2 = 0x2,
CRITTER_FLAG_0x20 = 0x20,
CRITTER_FLAG_0x40 = 0x40,
CRITTER_FLAG_0x80 = 0x80,
CRITTER_FLAG_0x100 = 0x100,
CRITTER_FLAG_0x200 = 0x200,
CRITTER_FLAG_0x400 = 0x400,
CRITTER_FLAG_0x800 = 0x800,
CRITTER_FLAG_0x1000 = 0x1000,
CRITTER_FLAG_0x2000 = 0x2000,
CRITTER_FLAG_0x4000 = 0x4000,
} CritterFlags;
#define OUTLINE_TYPE_MASK 0xFFFFFF
#define OUTLINE_PALETTED 0x40000000
#define OUTLINE_DISABLED 0x80000000
@ -77,9 +95,12 @@ typedef enum ObjectFlags {
#define CONTAINER_FLAG_LOCKED 0x02000000
#define DOOR_FLAG_LOCKED 0x02000000
#define CRITTER_MANEUVER_0x01 0x01
#define CRITTER_MANEUVER_STOP_ATTACKING 0x02
#define CRITTER_MANUEVER_FLEEING 0x04
typedef enum CritterManeuver {
CRITTER_MANEUVER_NONE = 0,
CRITTER_MANEUVER_0x01 = 0x01,
CRITTER_MANEUVER_STOP_ATTACKING = 0x02,
CRITTER_MANUEVER_FLEEING = 0x04,
} CritterManeuver;
typedef enum Dam {
DAM_KNOCKED_OUT = 0x01,
@ -178,18 +199,18 @@ typedef struct DoorSceneryData {
} DoorSceneryData;
typedef struct StairsSceneryData {
int field_0; // obj_pudg.pudstairs.destMap
int field_4; // obj_pudg.pudstairs.destBuiltTile
int destinationMap; // obj_pudg.pudstairs.destMap
int destinationBuiltTile; // obj_pudg.pudstairs.destBuiltTile
} StairsSceneryData;
typedef struct ElevatorSceneryData {
int field_0; // obj_pudg.pudelevator.elevType
int field_4; // obj_pudg.pudelevator.elevLevel
int type;
int level;
} ElevatorSceneryData;
typedef struct LadderSceneryData {
int field_0;
int field_4;
int destinationMap;
int destinationBuiltTile;
} LadderSceneryData;
typedef union SceneryObjectData {
@ -252,4 +273,30 @@ typedef struct ObjectListNode {
struct ObjectListNode* next;
} ObjectListNode;
#define BUILT_TILE_TILE_MASK 0x3FFFFFF
#define BUILT_TILE_ELEVATION_MASK 0xE0000000
#define BUILT_TILE_ELEVATION_SHIFT 29
#define BUILT_TILE_ROTATION_MASK 0x1C000000
#define BUILT_TILE_ROTATION_SHIFT 26
static inline int builtTileGetTile(int builtTile)
{
return builtTile & BUILT_TILE_TILE_MASK;
}
static inline int builtTileGetElevation(int builtTile)
{
return (builtTile & BUILT_TILE_ELEVATION_MASK) >> BUILT_TILE_ELEVATION_SHIFT;
}
static inline int builtTileGetRotation(int builtTile)
{
return (builtTile & BUILT_TILE_ROTATION_MASK) >> BUILT_TILE_ROTATION_SHIFT;
}
static inline int builtTileCreate(int tile, int elevation)
{
return tile | ((elevation << BUILT_TILE_ELEVATION_SHIFT) & BUILT_TILE_ELEVATION_MASK);
}
#endif /* OBJ_TYPES_H */

View File

@ -332,7 +332,7 @@ int objectsInit(unsigned char* buf, int width, int height, int pitch)
gObjectsWindowBufferSize = height * width;
gObjectsWindowPitch = pitch;
dudeFid = buildFid(1, _art_vault_guy_num, 0, 0, 0);
dudeFid = buildFid(OBJ_TYPE_CRITTER, _art_vault_guy_num, 0, 0, 0);
objectCreateWithFidPid(&gDude, dudeFid, 0x1000000);
gDude->flags |= OBJECT_FLAG_0x400;
@ -346,7 +346,7 @@ int objectsInit(unsigned char* buf, int width, int height, int pitch)
exit(1);
}
eggFid = buildFid(6, 2, 0, 0, 0);
eggFid = buildFid(OBJ_TYPE_INTERFACE, 2, 0, 0, 0);
objectCreateWithFidPid(&gEgg, eggFid, -1);
gEgg->flags |= OBJECT_FLAG_0x400;
gEgg->flags |= OBJECT_TEMPORARY;
@ -437,13 +437,13 @@ int objectRead(Object* obj, File* stream)
}
if (obj->pid < 0x5000010 || obj->pid > 0x5000017) {
if ((obj->pid >> 24) == 0 && !(gMapHeader.flags & 0x01)) {
if (PID_TYPE(obj->pid) == 0 && !(gMapHeader.flags & 0x01)) {
_object_fix_weapon_ammo(obj);
}
} else {
if (obj->data.misc.map <= 0) {
if ((obj->fid & 0xFFF) < 33) {
obj->fid = buildFid(5, (obj->fid & 0xFFF) + 16, (obj->fid & 0xFF0000) >> 16, 0, 0);
obj->fid = buildFid(OBJ_TYPE_MISC, (obj->fid & 0xFFF) + 16, FID_ANIM_TYPE(obj->fid), 0, 0);
}
}
}
@ -544,7 +544,7 @@ static int objectLoadAllInternal(File* stream)
_obj_insert(objectListNode);
if ((objectListNode->obj->flags & OBJECT_FLAG_0x400) && (objectListNode->obj->flags >> 24) == OBJ_TYPE_CRITTER && objectListNode->obj->pid != 18000) {
if ((objectListNode->obj->flags & OBJECT_FLAG_0x400) && PID_TYPE(objectListNode->obj->pid) == OBJ_TYPE_CRITTER && objectListNode->obj->pid != 18000) {
objectListNode->obj->flags &= ~OBJECT_FLAG_0x400;
}
@ -619,7 +619,7 @@ static void _obj_fix_combat_cid_for_dude()
// 0x48911C
static void _object_fix_weapon_ammo(Object* obj)
{
if ((obj->pid >> 24) != OBJ_TYPE_ITEM) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_ITEM) {
return;
}
@ -641,7 +641,7 @@ static void _object_fix_weapon_ammo(Object* obj)
obj->data.item.weapon.ammoQuantity = proto->item.data.weapon.ammoCapacity;
}
} else {
if ((obj->pid >> 24) == OBJ_TYPE_MISC) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_MISC) {
// FIXME: looks like this code in unreachable
charges = obj->data.item.misc.charges;
if (charges == 0xCCCCCCCC) {
@ -723,7 +723,7 @@ int objectSaveAll(File* stream)
CritterCombatData* combatData = NULL;
Object* whoHitMe = NULL;
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
combatData = &(object->data.critter.combat);
whoHitMe = combatData->whoHitMe;
if (whoHitMe != 0) {
@ -739,7 +739,7 @@ int objectSaveAll(File* stream)
return -1;
}
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
combatData->whoHitMe = whoHitMe;
}
@ -965,7 +965,7 @@ int objectCreateWithFidPid(Object** objectPtr, int fid, int pid)
objectListNode->obj->pid = pid;
objectListNode->obj->id = scriptsNewObjectId();
if (pid == -1 || (pid >> 24) == OBJ_TYPE_TILE) {
if (pid == -1 || PID_TYPE(pid) == OBJ_TYPE_TILE) {
Inventory* inventory = &(objectListNode->obj->data.inventory);
inventory->length = 0;
inventory->items = NULL;
@ -1451,7 +1451,7 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
}
if (isInCombat()) {
if ((obj->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER) {
if (FID_TYPE(obj->fid) == OBJ_TYPE_CRITTER) {
bool v8 = obj->outline != 0 && (obj->outline & OUTLINE_DISABLED) == 0;
_combat_update_critter_outline_for_los(obj, v8);
}
@ -1471,7 +1471,7 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
}
if (elevation == elev) {
if ((obj->fid & 0xF000000) >> 24 == OBJ_TYPE_MISC) {
if (FID_TYPE(obj->fid) == OBJ_TYPE_MISC) {
if (obj->pid >= 0x5000010 && obj->pid <= 0x5000017) {
ObjectData* data = &(obj->data);
@ -1498,9 +1498,9 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
int v15 = tile / 200 / 2;
if (v14 != _obj_last_roof_x || v15 != _obj_last_roof_y || elevation != _obj_last_elev) {
int v16 = _square[elevation]->field_0[v14 + 100 * v15];
int v31 = buildFid(4, (v16 >> 16) & 0xFFF, 0, 0, 0);
int v31 = buildFid(OBJ_TYPE_TILE, (v16 >> 16) & 0xFFF, 0, 0, 0);
int v32 = _square[elevation]->field_0[_obj_last_roof_x + 100 * _obj_last_roof_y];
int v34 = buildFid(4, 1, 0, 0, 0) == v31;
int v34 = buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0) == v31;
if (v34 != _obj_last_is_empty || (((v16 >> 16) & 0xF000) >> 12) != (((v32 >> 16) & 0xF000) >> 12)) {
if (_obj_last_is_empty == 0) {
@ -1538,7 +1538,7 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
}
}
} else {
if (elevation != _obj_last_elev && (obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (elevation != _obj_last_elev && PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
_combat_delete_critter(obj);
}
}
@ -1549,8 +1549,8 @@ int objectSetLocation(Object* obj, int tile, int elevation, Rect* rect)
// 0x48A9A0
int _obj_reset_roof()
{
int fid = buildFid(4, (_square[gDude->elevation]->field_0[_obj_last_roof_x + 100 * _obj_last_roof_y] >> 16) & 0xFFF, 0, 0, 0);
if (fid != buildFid(4, 1, 0, 0, 0)) {
int fid = buildFid(OBJ_TYPE_TILE, (_square[gDude->elevation]->field_0[_obj_last_roof_x + 100 * _obj_last_roof_y] >> 16) & 0xFFF, 0, 0, 0);
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
_tile_fill_roof(_obj_last_roof_x, _obj_last_roof_y, gDude->elevation, 1);
}
return 0;
@ -2100,13 +2100,13 @@ bool _obj_action_can_use(Object* obj)
// 0x48B278
bool _obj_action_can_talk_to(Object* obj)
{
return _proto_action_can_talk_to(obj->pid) && ((obj->pid >> 24) == OBJ_TYPE_CRITTER) && critterIsActive(obj);
return _proto_action_can_talk_to(obj->pid) && (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) && critterIsActive(obj);
}
// 0x48B2A8
bool _obj_portal_is_walk_thru(Object* obj)
{
if ((obj->pid >> 24) != OBJ_TYPE_SCENERY) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_SCENERY) {
return false;
}
@ -2207,7 +2207,7 @@ Object* objectFindFirst()
}
while (objectListNode != NULL) {
if (artIsObjectTypeHidden((objectListNode->obj->fid & 0xF000000) >> 24) == 0) {
if (artIsObjectTypeHidden(FID_TYPE(objectListNode->obj->fid)) == 0) {
gObjectFindLastObjectListNode = objectListNode;
return objectListNode->obj;
}
@ -2234,7 +2234,7 @@ Object* objectFindNext()
while (objectListNode != NULL) {
Object* object = objectListNode->obj;
if (!artIsObjectTypeHidden((object->fid & 0xF000000) >> 24)) {
if (!artIsObjectTypeHidden(FID_TYPE(object->fid))) {
gObjectFindLastObjectListNode = objectListNode;
return object;
}
@ -2257,7 +2257,7 @@ Object* objectFindFirstAtElevation(int elevation)
while (objectListNode != NULL) {
Object* object = objectListNode->obj;
if (object->elevation == elevation) {
if (!artIsObjectTypeHidden((object->fid & 0xF000000) >> 24)) {
if (!artIsObjectTypeHidden(FID_TYPE(object->fid))) {
gObjectFindLastObjectListNode = objectListNode;
return object;
}
@ -2287,7 +2287,7 @@ Object* objectFindNextAtElevation()
while (objectListNode != NULL) {
Object* object = objectListNode->obj;
if (object->elevation == gObjectFindElevation) {
if (!artIsObjectTypeHidden((object->fid & 0xF000000) >> 24)) {
if (!artIsObjectTypeHidden(FID_TYPE(object->fid))) {
gObjectFindLastObjectListNode = objectListNode;
return object;
}
@ -2310,7 +2310,7 @@ Object* objectFindFirstAtLocation(int elevation, int tile)
while (objectListNode != NULL) {
Object* object = objectListNode->obj;
if (object->elevation == elevation) {
if (!artIsObjectTypeHidden((object->fid & 0xF000000) >> 24)) {
if (!artIsObjectTypeHidden(FID_TYPE(object->fid))) {
gObjectFindLastObjectListNode = objectListNode;
return object;
}
@ -2334,7 +2334,7 @@ Object* objectFindNextAtLocation()
while (objectListNode != NULL) {
Object* object = objectListNode->obj;
if (object->elevation == gObjectFindElevation) {
if (!artIsObjectTypeHidden((object->fid & 0xF000000) >> 24)) {
if (!artIsObjectTypeHidden(FID_TYPE(object->fid))) {
gObjectFindLastObjectListNode = objectListNode;
return object;
}
@ -2449,7 +2449,7 @@ Object* _obj_blocking_at(Object* a1, int tile, int elev)
v7 = objectListNode->obj;
if (v7->elevation == elev) {
if ((v7->flags & OBJECT_HIDDEN) == 0 && (v7->flags & OBJECT_NO_BLOCK) == 0 && v7 != a1) {
type = (v7->fid & 0xF000000) >> 24;
type = FID_TYPE(v7->fid);
if (type == OBJ_TYPE_CRITTER
|| type == OBJ_TYPE_SCENERY
|| type == OBJ_TYPE_WALL) {
@ -2469,7 +2469,7 @@ Object* _obj_blocking_at(Object* a1, int tile, int elev)
if ((v7->flags & OBJECT_MULTIHEX) != 0) {
if (v7->elevation == elev) {
if ((v7->flags & OBJECT_HIDDEN) == 0 && (v7->flags & OBJECT_NO_BLOCK) == 0 && v7 != a1) {
type = (v7->fid & 0xF000000) >> 24;
type = FID_TYPE(v7->fid);
if (type == OBJ_TYPE_CRITTER
|| type == OBJ_TYPE_SCENERY
|| type == OBJ_TYPE_WALL) {
@ -2499,7 +2499,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
if (candidate->elevation == elev) {
unsigned int flags = candidate->flags;
if ((flags & OBJECT_HIDDEN) == 0 && ((flags & OBJECT_NO_BLOCK) == 0 || (flags & OBJECT_SHOOT_THRU) == 0) && candidate != obj) {
int type = (candidate->fid & 0xF000000) >> 24;
int type = FID_TYPE(candidate->fid);
// SFALL: Fix to prevent corpses from blocking line of fire.
if ((type == OBJ_TYPE_CRITTER && !critterIsDead(candidate))
|| type == OBJ_TYPE_SCENERY
@ -2524,7 +2524,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
if ((flags & OBJECT_MULTIHEX) != 0) {
if (candidate->elevation == elev) {
if ((flags & OBJECT_HIDDEN) == 0 && (flags & OBJECT_NO_BLOCK) == 0 && candidate != obj) {
int type = (candidate->fid & 0xF000000) >> 24;
int type = FID_TYPE(candidate->fid);
// SFALL: Fix to prevent corpses from blocking line of
// fire.
if ((type == OBJ_TYPE_CRITTER && !critterIsDead(candidate))
@ -2556,7 +2556,7 @@ Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation)
if ((object->flags & OBJECT_HIDDEN) == 0
&& (object->flags & OBJECT_NO_BLOCK) == 0
&& object != a1) {
int objectType = (object->fid & 0xF000000) >> 24;
int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_CRITTER
|| objectType == OBJ_TYPE_SCENERY
|| objectType == OBJ_TYPE_WALL) {
@ -2585,7 +2585,7 @@ Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation)
if ((object->flags & OBJECT_HIDDEN) == 0
&& (object->flags & OBJECT_NO_BLOCK) == 0
&& object != a1) {
int objectType = (object->fid & 0xF000000) >> 24;
int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_CRITTER
|| objectType == OBJ_TYPE_SCENERY
|| objectType == OBJ_TYPE_WALL) {
@ -2639,7 +2639,7 @@ Object* _obj_sight_blocking_at(Object* a1, int tile, int elevation)
&& (object->flags & OBJECT_HIDDEN) == 0
&& (object->flags & OBJECT_LIGHT_THRU) == 0
&& object != a1) {
int objectType = (object->fid & 0xF000000) >> 24;
int objectType = FID_TYPE(object->fid);
if (objectType == OBJ_TYPE_SCENERY || objectType == OBJ_TYPE_WALL) {
return object;
}
@ -2713,7 +2713,7 @@ int objectListCreate(int tile, int elevation, int objectType, Object*** objectLi
Object* obj = objectListNode->obj;
if ((obj->flags & OBJECT_HIDDEN) == 0
&& obj->elevation == elevation
&& ((obj->fid & 0xF000000) >> 24) == objectType) {
&& FID_TYPE(obj->fid) == objectType) {
count++;
}
objectListNode = objectListNode->next;
@ -2725,7 +2725,7 @@ int objectListCreate(int tile, int elevation, int objectType, Object*** objectLi
Object* obj = objectListNode->obj;
if ((obj->flags & OBJECT_HIDDEN) == 0
&& obj->elevation == elevation
&& ((objectListNode->obj->fid & 0xF000000) >> 24) == objectType) {
&& FID_TYPE(objectListNode->obj->fid) == objectType) {
count++;
}
objectListNode = objectListNode->next;
@ -2748,7 +2748,7 @@ int objectListCreate(int tile, int elevation, int objectType, Object*** objectLi
Object* obj = objectListNode->obj;
if ((obj->flags & OBJECT_HIDDEN) == 0
&& obj->elevation == elevation
&& ((obj->fid & 0xF000000) >> 24) == objectType) {
&& FID_TYPE(obj->fid) == objectType) {
*objects++ = obj;
}
objectListNode = objectListNode->next;
@ -2760,7 +2760,7 @@ int objectListCreate(int tile, int elevation, int objectType, Object*** objectLi
Object* obj = objectListNode->obj;
if ((obj->flags & OBJECT_HIDDEN) == 0
&& obj->elevation == elevation
&& ((obj->fid & 0xF000000) >> 24) == objectType) {
&& FID_TYPE(obj->fid) == objectType) {
*objects++ = obj;
}
objectListNode = objectListNode->next;
@ -3003,7 +3003,7 @@ int _obj_intersects_with(Object* object, int x, int y)
flags |= 0x02;
}
} else {
int type = (object->fid & 0xF000000) >> 24;
int type = FID_TYPE(object->fid);
if (type == OBJ_TYPE_SCENERY || type == OBJ_TYPE_WALL) {
Proto* proto;
protoGetProto(object->pid, &proto);
@ -3064,7 +3064,7 @@ int _obj_create_intersect_list(int x, int y, int elevation, int objectType, Obje
}
if (object->elevation == elevation
&& (objectType == -1 || (object->fid & 0xF000000) >> 24 == objectType)
&& (objectType == -1 || FID_TYPE(object->fid) == objectType)
&& object != gEgg) {
int flags = _obj_intersects_with(object, x, y);
if (flags != 0) {
@ -3164,7 +3164,7 @@ void _obj_process_seen()
// 0x48C8E4
char* objectGetName(Object* obj)
{
int objectType = (obj->fid & 0xF000000) >> 24;
int objectType = FID_TYPE(obj->fid);
switch (objectType) {
case OBJ_TYPE_ITEM:
return itemGetName(obj);
@ -3178,7 +3178,7 @@ char* objectGetName(Object* obj)
// 0x48C914
char* objectGetDescription(Object* obj)
{
if (((obj->fid & 0xF000000) >> 24) == OBJ_TYPE_ITEM) {
if (FID_TYPE(obj->fid) == OBJ_TYPE_ITEM) {
return itemGetDescription(obj);
}
@ -3226,13 +3226,13 @@ void _obj_preload_art_cache(int flags)
int v11 = gObjectFidsLength;
int v12 = gObjectFidsLength;
if ((gObjectFids[v12 - 1] & 0xF000000) >> 24 == 3) {
int v13 = 0;
if (FID_TYPE(gObjectFids[v12 - 1]) == OBJ_TYPE_WALL) {
int objectType = OBJ_TYPE_ITEM;
do {
v11--;
v13 = (gObjectFids[v12 - 1] & 0xF000000) >> 24;
objectType = FID_TYPE(gObjectFids[v12 - 1]);
v12--;
} while (v13 == 3);
} while (objectType == OBJ_TYPE_WALL);
v11++;
}
@ -3251,7 +3251,7 @@ void _obj_preload_art_cache(int flags)
for (int i = 0; i < 4096; i++) {
if (arr[i] != 0) {
int fid = buildFid(4, i, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_TILE, i, 0, 0, 0);
if (artLock(fid, &cache_handle) != NULL) {
artUnlock(cache_handle);
}
@ -3543,7 +3543,7 @@ static int _obj_save_obj(File* stream, Object* object)
CritterCombatData* combatData = NULL;
Object* whoHitMe = NULL;
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
combatData = &(object->data.critter.combat);
whoHitMe = combatData->whoHitMe;
if (whoHitMe != 0) {
@ -3559,7 +3559,7 @@ static int _obj_save_obj(File* stream, Object* object)
return -1;
}
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
combatData->whoHitMe = whoHitMe;
}
@ -4602,7 +4602,7 @@ static int _obj_adjust_light(Object* obj, int a2, Rect* rect)
v14 = (objectListNode->obj->flags & OBJECT_LIGHT_THRU) == 0;
if ((objectListNode->obj->fid & 0xF000000) >> 24 == OBJ_TYPE_WALL) {
if (FID_TYPE(objectListNode->obj->fid) == OBJ_TYPE_WALL) {
if ((objectListNode->obj->flags & OBJECT_FLAT) == 0) {
Proto* proto;
protoGetProto(objectListNode->obj->pid, &proto);
@ -4933,7 +4933,7 @@ static void objectDrawOutline(Object* object, Rect* rect)
// 0x48F1B0
static void _obj_render_object(Object* object, Rect* rect, int light)
{
int type = (object->fid & 0xF000000) >> 24;
int type = FID_TYPE(object->fid);
if (artIsObjectTypeHidden(type)) {
return;
}
@ -5146,7 +5146,7 @@ static void _obj_render_object(Object* object, Rect* rect, int light)
// 0x48FA14
void _obj_fix_violence_settings(int* fid)
{
if ((*fid >> 24) != OBJ_TYPE_CRITTER) {
if (FID_TYPE(*fid) != OBJ_TYPE_CRITTER) {
return;
}
@ -5181,12 +5181,12 @@ void _obj_fix_violence_settings(int* fid)
break;
}
int anim = (*fid & 0xFF0000) >> 16;
int anim = FID_ANIM_TYPE(*fid);
if (anim >= start && anim <= end) {
anim = (anim == ANIM_FALL_BACK_BLOOD_SF)
? ANIM_FALL_BACK_SF
: ANIM_FALL_FRONT_SF;
*fid = buildFid(1, *fid & 0xFFF, anim, (*fid & 0xF000) >> 12, (*fid & 0x70000000) >> 28);
*fid = buildFid(OBJ_TYPE_CRITTER, *fid & 0xFFF, anim, (*fid & 0xF000) >> 12, (*fid & 0x70000000) >> 28);
}
if (shouldResetViolenceLevel) {
@ -5200,8 +5200,8 @@ static int _obj_preload_sort(const void* a1, const void* a2)
int v1 = *(int*)a1;
int v2 = *(int*)a2;
int v3 = _cd_order[(v1 & 0xF000000) >> 24];
int v4 = _cd_order[(v2 & 0xF000000) >> 24];
int v3 = _cd_order[FID_TYPE(v1)];
int v4 = _cd_order[FID_TYPE(v2)];
int cmp = v3 - v4;
if (cmp != 0) {

View File

@ -574,7 +574,7 @@ static int optionsWindowInit()
}
for (int index = 0; index < OPTIONS_WINDOW_FRM_COUNT; index++) {
int fid = buildFid(6, gOptionsWindowFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gOptionsWindowFrmIds[index], 0, 0, 0);
gOptionsWindowFrmData[index] = artLockFrameDataReturningSize(fid, &(gOptionsWindowFrmHandles[index]), &(gOptionsWindowFrmSizes[index].width), &(gOptionsWindowFrmSizes[index].height));
if (gOptionsWindowFrmData[index] == NULL) {
@ -730,7 +730,7 @@ int showPause(bool a1)
_ShadeScreen(a1);
for (int index = 0; index < PAUSE_WINDOW_FRM_COUNT; index++) {
int fid = buildFid(6, graphicIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, graphicIds[index], 0, 0, 0);
frmData[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
if (frmData[index] == NULL) {
while (--index >= 0) {
@ -1498,7 +1498,7 @@ static int preferencesWindowInit()
_SaveSettings();
for (i = 0; i < PREFERENCES_WINDOW_FRM_COUNT; i++) {
fid = buildFid(6, gPreferencesWindowFrmIds[i], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, gPreferencesWindowFrmIds[i], 0, 0, 0);
gPreferencesWindowFrmData[i] = artLockFrameDataReturningSize(fid, &(gPreferencesWindowFrmHandles[i]), &(gPreferencesWindowFrmSizes[i].width), &(gPreferencesWindowFrmSizes[i].height));
if (gPreferencesWindowFrmData[i] == NULL) {
for (; i != 0; i--) {
@ -2064,3 +2064,9 @@ static void _DoThing(int eventCode)
_changed = true;
}
// 0x48FC48
int _do_options()
{
return showOptionsWithInitialKeyCode(-1);
}

View File

@ -29,5 +29,6 @@ int preferencesSave(File* stream);
int preferencesLoad(File* stream);
void brightnessIncrease();
void brightnessDecrease();
int _do_options();
#endif /* OPTIONS_H */

View File

@ -1,9 +1,9 @@
#include "party_member.h"
#include "combat_ai.h"
#include "combat_ai_defs.h"
#include "animation.h"
#include "color.h"
#include "combat_ai.h"
#include "combat_ai_defs.h"
#include "config.h"
#include "critter.h"
#include "debug.h"
@ -558,7 +558,7 @@ static int _partyMemberPrepLoadInstance(STRUCT_519DA8* a1)
return 0;
}
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
obj->data.critter.combat.whoHitMe = NULL;
}
@ -605,7 +605,7 @@ static int _partyMemberPrepLoadInstance(STRUCT_519DA8* a1)
scriptRemove(script->sid);
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
_dude_stand(obj, obj->rotation, -1);
}
@ -660,7 +660,7 @@ static int _partyMemberRecoverLoadInstance(STRUCT_519DA8* a1)
}
int scriptType = SCRIPT_TYPE_CRITTER;
if ((a1->object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(a1->object->pid) != OBJ_TYPE_CRITTER) {
scriptType = SCRIPT_TYPE_ITEM;
}
@ -791,7 +791,7 @@ int _partyMemberSyncPosition()
for (int index = 1; index < gPartyMembersLength; index++) {
STRUCT_519DA8* partyMember = &(gPartyMembers[index]);
Object* partyMemberObj = partyMember->object;
if ((partyMemberObj->flags & OBJECT_HIDDEN) == 0 && (partyMemberObj->pid >> 24) == OBJ_TYPE_CRITTER) {
if ((partyMemberObj->flags & OBJECT_HIDDEN) == 0 && PID_TYPE(partyMemberObj->pid) == OBJ_TYPE_CRITTER) {
int rotation;
if ((n % 2) != 0) {
rotation = clockwiseRotation;
@ -822,7 +822,7 @@ int _partyMemberRestingHeal(int a1)
for (int index = 0; index < gPartyMembersLength; index++) {
STRUCT_519DA8* partyMember = &(gPartyMembers[index]);
if ((partyMember->object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(partyMember->object->pid) == OBJ_TYPE_CRITTER) {
int healingRate = critterGetStat(partyMember->object, STAT_HEALING_RATE);
critterAdjustHitPoints(partyMember->object, v1 * healingRate);
}
@ -892,7 +892,7 @@ int _getPartyMemberCount()
for (int index = 1; index < gPartyMembersLength; index++) {
Object* object = gPartyMembers[index].object;
if ((object->pid >> 24) != OBJ_TYPE_CRITTER || critterIsDead(object) || (object->flags & OBJECT_HIDDEN) != 0) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER || critterIsDead(object) || (object->flags & OBJECT_HIDDEN) != 0) {
count--;
}
}
@ -1126,7 +1126,7 @@ int partyMemberGetBestSkill(Object* object)
return bestSkill;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return bestSkill;
}
@ -1152,7 +1152,7 @@ Object* partyMemberGetBestInSkill(int skill)
for (int index = 0; index < gPartyMembersLength; index++) {
Object* object = gPartyMembers[index].object;
if ((object->flags & OBJECT_HIDDEN) == 0 && (object->pid >> 24) == OBJ_TYPE_CRITTER) {
if ((object->flags & OBJECT_HIDDEN) == 0 && PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
int value = skillGetValue(object, skill);
if (value > bestValue) {
bestValue = value;
@ -1173,7 +1173,7 @@ int partyGetBestSkillValue(int skill)
for (int index = 0; index < gPartyMembersLength; index++) {
Object* object = gPartyMembers[index].object;
if ((object->flags & OBJECT_HIDDEN) == 0 && (object->pid >> 24) == OBJ_TYPE_CRITTER) {
if ((object->flags & OBJECT_HIDDEN) == 0 && PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
int value = skillGetValue(object, skill);
if (value > bestValue) {
bestValue = value;
@ -1191,7 +1191,7 @@ static int _partyFixMultipleMembers()
int critterCount = 0;
for (Object* obj = objectFindFirst(); obj != NULL; obj = objectFindNext()) {
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
critterCount++;
}
@ -1294,7 +1294,7 @@ bool partyMemberSupportsDisposition(Object* critter, int disposition)
return false;
}
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1317,7 +1317,7 @@ bool partyMemberSupportsAreaAttackMode(Object* object, int areaAttackMode)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1340,7 +1340,7 @@ bool partyMemberSupportsRunAwayMode(Object* object, int runAwayMode)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1363,7 +1363,7 @@ bool partyMemberSupportsBestWeapon(Object* object, int bestWeapon)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1386,7 +1386,7 @@ bool partyMemberSupportsDistance(Object* object, int distanceMode)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1409,7 +1409,7 @@ bool partyMemberSupportsAttackWho(Object* object, int attackWho)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1432,7 +1432,7 @@ bool partyMemberSupportsChemUse(Object* object, int chemUse)
return false;
}
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) {
return false;
}
@ -1475,7 +1475,7 @@ int _partyMemberIncLevels()
break;
}
if ((obj->pid >> 24) != 1) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
continue;
}
@ -1623,7 +1623,7 @@ bool partyIsAnyoneCanBeHealedByRest()
STRUCT_519DA8* ptr = &(gPartyMembers[index]);
Object* object = ptr->object;
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) continue;
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) continue;
if (critterIsDead(object)) continue;
if ((object->flags & OBJECT_HIDDEN) != 0) continue;
if (critterGetKillType(object) == KILL_TYPE_ROBOT) continue;
@ -1650,7 +1650,7 @@ int partyGetMaxWoundToHealByRest()
STRUCT_519DA8* ptr = &(gPartyMembers[index]);
Object* object = ptr->object;
if ((object->pid >> 24) != OBJ_TYPE_CRITTER) continue;
if (PID_TYPE(object->pid) != OBJ_TYPE_CRITTER) continue;
if (critterIsDead(object)) continue;
if ((object->flags & OBJECT_HIDDEN) != 0) continue;
if (critterGetKillType(object) == KILL_TYPE_ROBOT) continue;

178
src/pcx.cc Normal file
View File

@ -0,0 +1,178 @@
#include "pcx.h"
#include "memory_manager.h"
// 0x519DC8
unsigned char gPcxLastRunLength = 0;
// 0x519DC9
unsigned char gPcxLastValue = 0;
// NOTE: The reading method in this function is a little bit odd. It does not
// use high level reading functions, which can read right into struct. Instead
// they read everything into temporary variables. There are no error checks.
//
// 0x4961D4
void pcxReadHeader(PcxHeader* pcxHeader, File* stream)
{
pcxHeader->identifier = fileReadChar(stream);
pcxHeader->version = fileReadChar(stream);
pcxHeader->encoding = fileReadChar(stream);
pcxHeader->bitsPerPixel = fileReadChar(stream);
short minX;
fileRead(&minX, 2, 1, stream);
pcxHeader->minX = minX;
short minY;
fileRead(&minY, 2, 1, stream);
pcxHeader->minY = minY;
short maxX;
fileRead(&maxX, 2, 1, stream);
pcxHeader->maxX = maxX;
short maxY;
fileRead(&maxY, 2, 1, stream);
pcxHeader->maxY = maxY;
short horizontalResolution;
fileRead(&horizontalResolution, 2, 1, stream);
pcxHeader->horizontalResolution = horizontalResolution;
short verticalResolution;
fileRead(&verticalResolution, 2, 1, stream);
pcxHeader->verticalResolution = verticalResolution;
for (int index = 0; index < 48; index++) {
pcxHeader->palette[index] = fileReadChar(stream);
}
pcxHeader->reserved1 = fileReadChar(stream);
pcxHeader->planeCount = fileReadChar(stream);
short bytesPerLine;
fileRead(&bytesPerLine, 2, 1, stream);
pcxHeader->bytesPerLine = bytesPerLine;
short paletteType;
fileRead(&paletteType, 2, 1, stream);
pcxHeader->paletteType = paletteType;
short horizontalScreenSize;
fileRead(&horizontalScreenSize, 2, 1, stream);
pcxHeader->horizontalScreenSize = horizontalScreenSize;
short verticalScreenSize;
fileRead(&verticalScreenSize, 2, 1, stream);
pcxHeader->verticalScreenSize = verticalScreenSize;
for (int index = 0; index < 54; index++) {
pcxHeader->reserved2[index] = fileReadChar(stream);
}
}
// 0x49636C
int pcxReadLine(unsigned char* data, int size, File* stream)
{
unsigned char runLength = gPcxLastRunLength;
unsigned char value = gPcxLastValue;
int uncompressedSize = 0;
int index = 0;
do {
uncompressedSize += runLength;
while (runLength > 0 && index < size) {
data[index] = value;
runLength--;
index++;
}
gPcxLastRunLength = runLength;
gPcxLastValue = value;
if (runLength != 0) {
uncompressedSize -= runLength;
break;
}
value = fileReadChar(stream);
if ((value & 0xC0) == 0xC0) {
gPcxLastRunLength = value & 0x3F;
value = fileReadChar(stream);
runLength = gPcxLastRunLength;
} else {
runLength = 1;
}
} while (index < size);
gPcxLastRunLength = runLength;
gPcxLastValue = value;
return uncompressedSize;
}
// 0x49641C
int pcxReadPalette(PcxHeader* pcxHeader, unsigned char* palette, File* stream)
{
if (pcxHeader->version != 5) {
return 0;
}
long pos = fileTell(stream);
long size = fileGetSize(stream);
fileSeek(stream, size - 769, SEEK_SET);
if (fileReadChar(stream) != 12) {
fileSeek(stream, pos, SEEK_SET);
return 0;
}
for (int index = 0; index < 768; index++) {
palette[index] = fileReadChar(stream);
}
fileSeek(stream, pos, SEEK_SET);
return 1;
}
// 0x496494
unsigned char* pcxRead(const char* path, int* widthPtr, int* heightPtr, unsigned char* palette)
{
File* stream = fileOpen(path, "rb");
if (stream == NULL) {
return NULL;
}
PcxHeader pcxHeader;
pcxReadHeader(&pcxHeader, stream);
int width = pcxHeader.maxX - pcxHeader.minX + 1;
int height = pcxHeader.maxY - pcxHeader.minY + 1;
*widthPtr = width;
*heightPtr = height;
int bytesPerLine = pcxHeader.planeCount * pcxHeader.bytesPerLine;
unsigned char* data = (unsigned char*)internal_malloc_safe(bytesPerLine * height, __FILE__, __LINE__); // "..\\int\\PCX.C", 195
if (data == NULL) {
// NOTE: This code is unreachable, internal_malloc_safe never fails.
fileClose(stream);
return NULL;
}
gPcxLastRunLength = 0;
gPcxLastValue = 0;
unsigned char* ptr = data;
for (int y = 0; y < height; y++) {
pcxReadLine(ptr, bytesPerLine, stream);
ptr += width;
}
pcxReadPalette(&pcxHeader, palette, stream);
fileClose(stream);
return data;
}

35
src/pcx.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef PCX_H
#define PCX_H
#include "db.h"
typedef struct PcxHeader {
unsigned char identifier;
unsigned char version;
unsigned char encoding;
unsigned char bitsPerPixel;
short minX;
short minY;
short maxX;
short maxY;
short horizontalResolution;
short verticalResolution;
unsigned char palette[48];
unsigned char reserved1;
unsigned char planeCount;
short bytesPerLine;
short paletteType;
short horizontalScreenSize;
short verticalScreenSize;
unsigned char reserved2[54];
} PcxHeader;
extern unsigned char gPcxLastRunLength;
extern unsigned char gPcxLastValue;
void pcxReadHeader(PcxHeader* pcxHeader, File* stream);
int pcxReadLine(unsigned char* data, int size, File* stream);
int pcxReadPalette(PcxHeader* pcxHeader, unsigned char* palette, File* stream);
unsigned char* pcxRead(const char* path, int* widthPtr, int* heightPtr, unsigned char* palette);
#endif /* PCX_H */

View File

@ -535,7 +535,7 @@ int perkGetFrmId(int perk)
// 0x496BFC
void perkAddEffect(Object* critter, int perk)
{
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
debugPrint("\nERROR: perk_add_effect: Was called on non-critter!");
return;
}
@ -575,7 +575,7 @@ void perkAddEffect(Object* critter, int perk)
// 0x496CE0
void perkRemoveEffect(Object* critter, int perk)
{
if ((critter->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(critter->pid) != OBJ_TYPE_CRITTER) {
debugPrint("\nERROR: perk_remove_effect: Was called on non-critter!");
return;
}

View File

@ -512,7 +512,7 @@ static int pipboyWindowInit(bool forceRest)
int index;
for (index = 0; index < PIPBOY_FRM_COUNT; index++) {
int fid = buildFid(6, gPipboyFrmIds[index], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gPipboyFrmIds[index], 0, 0, 0);
gPipboyFrmData[index] = artLockFrameDataReturningSize(fid, &(gPipboyFrmHandles[index]), &(gPipboyFrmSizes[index].width), &(gPipboyFrmSizes[index].height));
if (gPipboyFrmData[index] == NULL) {
break;
@ -1087,7 +1087,7 @@ static void pipboyWindowHandleStatus(int a1)
// Skip quests in the same location.
//
// FIXME: This code should be identical to the one in the
// FIXME: This code should be identical to the one in the
// `pipboyWindowRenderQuestLocationList`. See buffer overread
// bug involved.
for (; index < gQuestsCount; index++) {
@ -2013,7 +2013,7 @@ static bool pipboyRest(int hours, int minutes, int duration)
rc = true;
}
unsigned int v8 = (unsigned int)((double)hour / v7 * (hours * 36000.0) + gameTime);
unsigned int v8 = (unsigned int)((double)hour / v7 * (hours * GAME_TIME_TICKS_PER_HOUR) + gameTime);
unsigned int nextEventTime = queueGetNextEventTime();
if (!rc && v8 >= nextEventTime) {
gameTimeSetTime(nextEventTime + 1);
@ -2050,7 +2050,7 @@ static bool pipboyRest(int hours, int minutes, int duration)
}
if (!rc) {
gameTimeSetTime(gameTime + 36000 * hours);
gameTimeSetTime(gameTime + GAME_TIME_TICKS_PER_HOUR * hours);
}
pipboyDrawNumber(gameTimeGetHour(), 4, PIPBOY_WINDOW_TIME_X, PIPBOY_WINDOW_TIME_Y);

View File

@ -55,7 +55,7 @@ void compat_splitpath(const char* path, char* drive, char* dir, char* fname, cha
#ifdef _WIN32
_splitpath(path, drive, dir, fname, ext);
#else
const char *driveStart = path;
const char* driveStart = path;
if (path[0] == '/' && path[1] == '/') {
path += 2;
while (*path != '\0' && *path != '/' && *path != '.') {
@ -130,7 +130,7 @@ void compat_makepath(char* path, const char* drive, const char* dir, const char*
if (*drive != '\0') {
strcpy(path, drive);
path = strchr(path, '\0');
if (path[-1] == '/') {
path--;
} else {

View File

@ -185,17 +185,21 @@ static char** _perk_code_strs;
// 0x6648BC
static char** _critter_stats_list;
// NOTE: Inlined.
void _proto_make_path(char* path, int pid)
{
strcpy(path, _cd_path_base);
strcat(path, _proto_path_base);
if (pid != -1) {
strcat(path, artGetObjectTypeName(PID_TYPE(pid)));
}
}
// Append proto file name to proto_path from proto.lst.
//
// 0x49E758
int _proto_list_str(int pid, char* proto_path)
{
char path[COMPAT_MAX_PATH];
char str[COMPAT_MAX_PATH];
char* pch;
File* stream;
int i;
if (pid == -1) {
return -1;
}
@ -204,17 +208,17 @@ int _proto_list_str(int pid, char* proto_path)
return -1;
}
strcpy(path, _cd_path_base);
strcat(path, "proto\\");
strcat(path, artGetObjectTypeName(pid >> 24));
char path[COMPAT_MAX_PATH];
_proto_make_path(path, pid);
strcat(path, "\\");
strcat(path, artGetObjectTypeName(pid >> 24));
strcat(path, artGetObjectTypeName(PID_TYPE(pid)));
strcat(path, ".lst");
stream = fileOpen(path, "rt");
File* stream = fileOpen(path, "rt");
i = 1;
while (fileReadString(str, sizeof(str), stream)) {
int i = 1;
char string[256];
while (fileReadString(string, sizeof(string), stream)) {
if (i == (pid & 0xFFFFFF)) {
break;
}
@ -228,14 +232,17 @@ int _proto_list_str(int pid, char* proto_path)
return -1;
}
pch = str;
while (*pch != '\0' && *pch != '\n') {
*proto_path = *pch;
proto_path++;
pch++;
char* pch = strchr(string, ' ');
if (pch != NULL) {
*pch = '\0';
}
*proto_path = '\0';
pch = strchr(string, '\n');
if (pch != NULL) {
*pch = '\0';
}
strcpy(proto_path, string);
return 0;
}
@ -252,7 +259,7 @@ bool _proto_action_can_use(int pid)
return true;
}
if ((pid >> 24) == OBJ_TYPE_ITEM && proto->item.type == ITEM_TYPE_CONTAINER) {
if (PID_TYPE(pid) == OBJ_TYPE_ITEM && proto->item.type == ITEM_TYPE_CONTAINER) {
return true;
}
@ -271,7 +278,7 @@ bool _proto_action_can_use_on(int pid)
return true;
}
if ((pid >> 24) == OBJ_TYPE_ITEM && proto->item.type == ITEM_TYPE_DRUG) {
if (PID_TYPE(pid) == OBJ_TYPE_ITEM && proto->item.type == ITEM_TYPE_DRUG) {
return true;
}
@ -286,7 +293,7 @@ bool _proto_action_can_talk_to(int pid)
return false;
}
if ((pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(pid) == OBJ_TYPE_CRITTER) {
return true;
}
@ -302,7 +309,7 @@ bool _proto_action_can_talk_to(int pid)
// 0x49EA5C
int _proto_action_can_pickup(int pid)
{
if ((pid >> 24) != OBJ_TYPE_ITEM) {
if (PID_TYPE(pid) != OBJ_TYPE_ITEM) {
return false;
}
@ -326,7 +333,7 @@ char* protoGetMessage(int pid, int message)
Proto* proto;
if (protoGetProto(pid, &proto) != -1) {
if (proto->messageId != -1) {
MessageList* messageList = &(_proto_msg_files[pid >> 24]);
MessageList* messageList = &(_proto_msg_files[PID_TYPE(pid)]);
MessageListItem messageListItem;
messageListItem.num = proto->messageId + message;
@ -366,7 +373,7 @@ static int _proto_critter_init(Proto* a1, int a2)
a1->pid = -1;
a1->messageId = 100 * v1;
a1->fid = buildFid(1, v1 - 1, 0, 0, 0);
a1->fid = buildFid(OBJ_TYPE_CRITTER, v1 - 1, 0, 0, 0);
a1->critter.lightDistance = 0;
a1->critter.lightIntensity = 0;
a1->critter.flags = 0x20000000;
@ -377,7 +384,7 @@ static int _proto_critter_init(Proto* a1, int a2)
a1->critter.headFid = -1;
a1->critter.aiPacket = 1;
if (!artExists(a1->fid)) {
a1->fid = buildFid(1, 0, 0, 0, 0);
a1->fid = buildFid(OBJ_TYPE_CRITTER, 0, 0, 0, 0);
}
CritterProtoData* data = &(a1->critter.data);
@ -437,7 +444,7 @@ int objectDataRead(Object* obj, File* stream)
// TODO: See below.
if (fileReadInt32(stream, (int*)&(inventory->items)) == -1) return -1;
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
if (fileReadInt32(stream, &(obj->data.critter.field_0)) == -1) return -1;
if (objectCritterCombatDataRead(&(obj->data.critter.combat), stream) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.critter.hp)) == -1) return -1;
@ -451,7 +458,7 @@ int objectDataRead(Object* obj, File* stream)
obj->data.flags = 0;
}
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
if (protoGetProto(obj->pid, &proto) == -1) return -1;
@ -482,27 +489,27 @@ int objectDataRead(Object* obj, File* stream)
if (fileReadInt32(stream, &(obj->data.scenery.door.openFlags)) == -1) return -1;
break;
case SCENERY_TYPE_STAIRS:
if (fileReadInt32(stream, &(obj->data.scenery.stairs.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.stairs.field_0)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.stairs.destinationBuiltTile)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.stairs.destinationMap)) == -1) return -1;
break;
case SCENERY_TYPE_ELEVATOR:
if (fileReadInt32(stream, &(obj->data.scenery.elevator.field_0)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.elevator.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.elevator.type)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.elevator.level)) == -1) return -1;
break;
case SCENERY_TYPE_LADDER_UP:
if (gMapHeader.version == 19) {
if (fileReadInt32(stream, &(obj->data.scenery.ladder.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.destinationBuiltTile)) == -1) return -1;
} else {
if (fileReadInt32(stream, &(obj->data.scenery.ladder.field_0)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.destinationMap)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.destinationBuiltTile)) == -1) return -1;
}
break;
case SCENERY_TYPE_LADDER_DOWN:
if (gMapHeader.version == 19) {
if (fileReadInt32(stream, &(obj->data.scenery.ladder.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.destinationBuiltTile)) == -1) return -1;
} else {
if (fileReadInt32(stream, &(obj->data.scenery.ladder.field_0)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.destinationMap)) == -1) return -1;
if (fileReadInt32(stream, &(obj->data.scenery.ladder.destinationBuiltTile)) == -1) return -1;
}
break;
}
@ -534,7 +541,7 @@ int objectDataWrite(Object* obj, File* stream)
// this field is shared with something else.
if (fileWriteInt32(stream, (intptr_t)data->inventory.items) == -1) return -1;
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
if (fileWriteInt32(stream, data->flags) == -1) return -1;
if (objectCritterCombatDataWrite(&(obj->data.critter.combat), stream) == -1) return -1;
if (fileWriteInt32(stream, data->critter.hp) == -1) return -1;
@ -543,7 +550,7 @@ int objectDataWrite(Object* obj, File* stream)
} else {
if (fileWriteInt32(stream, data->flags) == -1) return -1;
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
if (protoGetProto(obj->pid, &proto) == -1) return -1;
@ -571,20 +578,20 @@ int objectDataWrite(Object* obj, File* stream)
if (fileWriteInt32(stream, data->scenery.door.openFlags) == -1) return -1;
break;
case SCENERY_TYPE_STAIRS:
if (fileWriteInt32(stream, data->scenery.stairs.field_4) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.stairs.field_0) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.stairs.destinationBuiltTile) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.stairs.destinationMap) == -1) return -1;
break;
case SCENERY_TYPE_ELEVATOR:
if (fileWriteInt32(stream, data->scenery.elevator.field_0) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.elevator.field_4) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.elevator.type) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.elevator.level) == -1) return -1;
break;
case SCENERY_TYPE_LADDER_UP:
if (fileWriteInt32(stream, data->scenery.ladder.field_0) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.elevator.field_4) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.ladder.destinationMap) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.ladder.destinationBuiltTile) == -1) return -1;
break;
case SCENERY_TYPE_LADDER_DOWN:
if (fileWriteInt32(stream, data->scenery.ladder.field_0) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.elevator.field_4) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.ladder.destinationMap) == -1) return -1;
if (fileWriteInt32(stream, data->scenery.ladder.destinationBuiltTile) == -1) return -1;
break;
default:
break;
@ -624,7 +631,7 @@ static int _proto_update_gen(Object* obj)
return -1;
}
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
switch (proto->item.type) {
case ITEM_TYPE_CONTAINER:
@ -651,16 +658,16 @@ static int _proto_update_gen(Object* obj)
data->scenery.door.openFlags = proto->scenery.data.door.openFlags;
break;
case SCENERY_TYPE_STAIRS:
data->scenery.stairs.field_4 = proto->scenery.data.stairs.field_0;
data->scenery.stairs.field_0 = proto->scenery.data.stairs.field_4;
data->scenery.stairs.destinationBuiltTile = proto->scenery.data.stairs.field_0;
data->scenery.stairs.destinationMap = proto->scenery.data.stairs.field_4;
break;
case SCENERY_TYPE_ELEVATOR:
data->scenery.elevator.field_0 = proto->scenery.data.elevator.field_0;
data->scenery.elevator.field_4 = proto->scenery.data.elevator.field_4;
data->scenery.elevator.type = proto->scenery.data.elevator.type;
data->scenery.elevator.level = proto->scenery.data.elevator.level;
break;
case SCENERY_TYPE_LADDER_UP:
case SCENERY_TYPE_LADDER_DOWN:
data->scenery.ladder.field_0 = proto->scenery.data.ladder.field_0;
data->scenery.ladder.destinationMap = proto->scenery.data.ladder.field_0;
break;
}
break;
@ -698,7 +705,7 @@ int _proto_update_init(Object* obj)
obj->field_2C_array[i] = 0;
}
if ((obj->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) != OBJ_TYPE_CRITTER) {
return _proto_update_gen(obj);
}
@ -749,11 +756,11 @@ int _proto_dude_update_gender()
v1 = (gDude->fid & 0xF000) >> 12;
}
int fid = buildFid(1, _art_vault_guy_num, 0, v1, 0);
int fid = buildFid(OBJ_TYPE_CRITTER, _art_vault_guy_num, 0, v1, 0);
objectSetFid(gDude, fid, NULL);
}
proto->fid = buildFid(1, _art_vault_guy_num, 0, 0, 0);
proto->fid = buildFid(OBJ_TYPE_CRITTER, _art_vault_guy_num, 0, 0, 0);
return 0;
}
@ -762,7 +769,7 @@ int _proto_dude_update_gender()
// 0x49FA64
int _proto_dude_init(const char* path)
{
gDudeProto.fid = buildFid(1, _art_vault_guy_num, 0, 0, 0);
gDudeProto.fid = buildFid(OBJ_TYPE_CRITTER, _art_vault_guy_num, 0, 0, 0);
if (_init_true) {
_obj_inven_free(&(gDude->data.inventory));
@ -822,7 +829,7 @@ int protoGetDataMember(int pid, int member, ProtoDataMemberValue* value)
return -1;
}
switch (pid >> 24) {
switch (PID_TYPE(pid)) {
case OBJ_TYPE_ITEM:
switch (member) {
case ITEM_DATA_MEMBER_PID:
@ -1076,7 +1083,7 @@ int protoInit()
_proto_critter_init((Proto*)&gDudeProto, 0x1000000);
gDudeProto.pid = 0x1000000;
gDudeProto.fid = buildFid(1, 1, 0, 0, 0);
gDudeProto.fid = buildFid(OBJ_TYPE_CRITTER, 1, 0, 0, 0);
gDude->pid = 0x1000000;
gDude->sid = 1;
@ -1188,7 +1195,7 @@ void protoReset()
// TODO: Get rid of cast.
_proto_critter_init((Proto*)&gDudeProto, 0x1000000);
gDudeProto.pid = 0x1000000;
gDudeProto.fid = buildFid(1, 1, 0, 0, 0);
gDudeProto.fid = buildFid(OBJ_TYPE_CRITTER, 1, 0, 0, 0);
gDude->pid = 0x1000000;
gDude->sid = -1;
@ -1233,9 +1240,7 @@ static int _proto_header_load()
ptr->max_entries_num = 1;
char path[COMPAT_MAX_PATH];
strcpy(path, _cd_path_base);
strcat(path, _proto_path_base);
strcat(path, artGetObjectTypeName(index));
_proto_make_path(path, index << 24);
strcat(path, "\\");
strcat(path, artGetObjectTypeName(index));
strcat(path, ".lst");
@ -1358,8 +1363,8 @@ static int protoSceneryDataRead(SceneryProtoData* scenery_data, int type, File*
return 0;
case SCENERY_TYPE_ELEVATOR:
if (fileReadInt32(stream, &(scenery_data->elevator.field_0)) == -1) return -1;
if (fileReadInt32(stream, &(scenery_data->elevator.field_4)) == -1) return -1;
if (fileReadInt32(stream, &(scenery_data->elevator.type)) == -1) return -1;
if (fileReadInt32(stream, &(scenery_data->elevator.level)) == -1) return -1;
return 0;
case SCENERY_TYPE_LADDER_UP:
@ -1384,7 +1389,7 @@ static int protoRead(Proto* proto, File* stream)
if (fileReadInt32(stream, &(proto->messageId)) == -1) return -1;
if (fileReadInt32(stream, &(proto->fid)) == -1) return -1;
switch (proto->pid >> 24) {
switch (PID_TYPE(proto->pid)) {
case OBJ_TYPE_ITEM:
if (fileReadInt32(stream, &(proto->item.lightDistance)) == -1) return -1;
if (_db_freadInt(stream, &(proto->item.lightIntensity)) == -1) return -1;
@ -1544,8 +1549,8 @@ static int protoSceneryDataWrite(SceneryProtoData* scenery_data, int type, File*
return 0;
case SCENERY_TYPE_ELEVATOR:
if (fileWriteInt32(stream, scenery_data->elevator.field_0) == -1) return -1;
if (fileWriteInt32(stream, scenery_data->elevator.field_4) == -1) return -1;
if (fileWriteInt32(stream, scenery_data->elevator.type) == -1) return -1;
if (fileWriteInt32(stream, scenery_data->elevator.level) == -1) return -1;
return 0;
case SCENERY_TYPE_LADDER_UP:
@ -1569,7 +1574,7 @@ static int protoWrite(Proto* proto, File* stream)
if (fileWriteInt32(stream, proto->messageId) == -1) return -1;
if (fileWriteInt32(stream, proto->fid) == -1) return -1;
switch (proto->pid >> 24) {
switch (PID_TYPE(proto->pid)) {
case OBJ_TYPE_ITEM:
if (fileWriteInt32(stream, proto->item.lightDistance) == -1) return -1;
if (_db_fwriteLong(stream, proto->item.lightIntensity) == -1) return -1;
@ -1645,13 +1650,7 @@ int _proto_save_pid(int pid)
}
char path[260];
strcpy(path, _cd_path_base);
strcat(path, _proto_path_base);
if (pid != -1) {
strcat(path, artGetObjectTypeName(pid >> 24));
}
_proto_make_path(path, pid);
strcat(path, "\\");
_proto_list_str(pid, path + strlen(path));
@ -1672,14 +1671,7 @@ int _proto_save_pid(int pid)
static int _proto_load_pid(int pid, Proto** protoPtr)
{
char path[COMPAT_MAX_PATH];
strcpy(path, _cd_path_base);
strcat(path, "proto\\");
if (pid != -1) {
strcat(path, artGetObjectTypeName(pid >> 24));
}
_proto_make_path(path, pid);
strcat(path, "\\");
if (_proto_list_str(pid, path + strlen(path)) == -1) {
@ -1693,7 +1685,7 @@ static int _proto_load_pid(int pid, Proto** protoPtr)
return -1;
}
if (_proto_find_free_subnode(pid >> 24, protoPtr) == -1) {
if (_proto_find_free_subnode(PID_TYPE(pid), protoPtr) == -1) {
fileClose(stream);
return -1;
}
@ -1826,7 +1818,7 @@ int protoGetProto(int pid, Proto** protoPtr)
return 0;
}
ProtoList* protoList = &(_protoLists[pid >> 24]);
ProtoList* protoList = &(_protoLists[PID_TYPE(pid)]);
ProtoListExtent* protoListExtent = protoList->head;
while (protoListExtent != NULL) {
for (int index = 0; index < protoListExtent->length; index++) {
@ -1841,7 +1833,7 @@ int protoGetProto(int pid, Proto** protoPtr)
if (protoList->head != NULL && protoList->tail != NULL) {
if (PROTO_LIST_EXTENT_SIZE * protoList->length - (PROTO_LIST_EXTENT_SIZE - protoList->tail->length) > PROTO_LIST_MAX_ENTRIES) {
_proto_remove_some_list(pid >> 24);
_proto_remove_some_list(PID_TYPE(pid));
}
}

View File

@ -100,6 +100,7 @@ extern char _cd_path_base[COMPAT_MAX_PATH];
extern MessageList gProtoMessageList;
extern char* _proto_none_str;
void _proto_make_path(char* path, int pid);
int _proto_list_str(int pid, char* proto_path);
bool _proto_action_can_use(int pid);
bool _proto_action_can_use_on(int pid);

View File

@ -76,7 +76,7 @@ int _obj_new_sid(Object* object, int* sidPtr)
}
int sid;
int objectType = object->pid >> 24;
int objectType = PID_TYPE(object->pid);
if (objectType < OBJ_TYPE_TILE) {
sid = proto->sid;
} else if (objectType == OBJ_TYPE_TILE) {
@ -91,7 +91,7 @@ int _obj_new_sid(Object* object, int* sidPtr)
return -1;
}
int scriptType = sid >> 24;
int scriptType = SID_TYPE(sid);
if (scriptAdd(sidPtr, scriptType) == -1) {
return -1;
}
@ -108,7 +108,7 @@ int _obj_new_sid(Object* object, int* sidPtr)
}
if (scriptType == SCRIPT_TYPE_SPATIAL) {
script->sp.built_tile = object->tile | ((object->elevation << 29) & 0xE0000000);
script->sp.built_tile = builtTileCreate(object->tile, object->elevation);
script->sp.radius = 3;
}
@ -143,7 +143,7 @@ int _obj_new_sid_inst(Object* obj, int scriptType, int a3)
script->field_14 = a3;
if (scriptType == SCRIPT_TYPE_SPATIAL) {
script->sp.built_tile = ((obj->elevation << 29) & 0xE0000000) | obj->tile;
script->sp.built_tile = builtTileCreate(obj->tile, obj->elevation);
script->sp.radius = 3;
}
@ -156,7 +156,7 @@ int _obj_new_sid_inst(Object* obj, int scriptType, int a3)
_scr_find_str_run_info(a3 & 0xFFFFFF, &(script->field_50), sid);
if ((obj->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_CRITTER) {
obj->field_80 = script->field_14;
}
@ -176,7 +176,7 @@ int _obj_look_at_func(Object* a1, Object* a2, void (*a3)(char* string))
return -1;
}
if (((a2->fid & 0xF000000) >> 24) == OBJ_TYPE_TILE) {
if (FID_TYPE(a2->fid) == OBJ_TYPE_TILE) {
return -1;
}
@ -202,7 +202,7 @@ int _obj_look_at_func(Object* a1, Object* a2, void (*a3)(char* string))
if (!scriptOverrides) {
MessageListItem messageListItem;
if ((a2->pid >> 24) == OBJ_TYPE_CRITTER && critterIsDead(a2)) {
if (PID_TYPE(a2->pid) == OBJ_TYPE_CRITTER && critterIsDead(a2)) {
messageListItem.num = 491 + randomBetween(0, 1);
} else {
messageListItem.num = 490;
@ -240,7 +240,7 @@ int _obj_examine_func(Object* critter, Object* target, void (*fn)(char* string))
return -1;
}
if ((target->fid & 0xF000000) >> 24 == OBJ_TYPE_TILE) {
if (FID_TYPE(target->fid) == OBJ_TYPE_TILE) {
return -1;
}
@ -271,7 +271,7 @@ int _obj_examine_func(Object* critter, Object* target, void (*fn)(char* string))
}
fn(messageListItem.text);
} else {
if ((target->pid >> 24) != OBJ_TYPE_CRITTER || !critterIsDead(target)) {
if (PID_TYPE(target->pid) != OBJ_TYPE_CRITTER || !critterIsDead(target)) {
fn(description);
}
}
@ -283,7 +283,7 @@ int _obj_examine_func(Object* critter, Object* target, void (*fn)(char* string))
char formattedText[260];
int type = target->pid >> 24;
int type = PID_TYPE(target->pid);
if (type == OBJ_TYPE_CRITTER) {
if (target != gDude && perkGetRank(gDude, PERK_AWARENESS) && !critterIsDead(target)) {
MessageListItem hpMessageListItem;
@ -597,7 +597,7 @@ static int _obj_remove_from_inven(Object* critter, Object* item)
int v11 = 0;
if (critterGetItem2(critter) == item) {
if (critter != gDude || interfaceGetCurrentHand()) {
fid = buildFid(1, critter->fid & 0xFFF, (critter->fid & 0xFF0000) >> 16, 0, critter->rotation);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, FID_ANIM_TYPE(critter->fid), 0, critter->rotation);
objectSetFid(critter, fid, &updatedRect);
v11 = 2;
} else {
@ -605,7 +605,7 @@ static int _obj_remove_from_inven(Object* critter, Object* item)
}
} else if (critterGetItem1(critter) == item) {
if (critter == gDude && !interfaceGetCurrentHand()) {
fid = buildFid(1, critter->fid & 0xFFF, (critter->fid & 0xFF0000) >> 16, 0, critter->rotation);
fid = buildFid(OBJ_TYPE_CRITTER, critter->fid & 0xFFF, FID_ANIM_TYPE(critter->fid), 0, critter->rotation);
objectSetFid(critter, fid, &updatedRect);
v11 = 2;
} else {
@ -620,7 +620,7 @@ static int _obj_remove_from_inven(Object* critter, Object* item)
v5 = proto->fid;
}
fid = buildFid(1, v5, (critter->fid & 0xFF0000) >> 16, (critter->fid & 0xF000) >> 12, critter->rotation);
fid = buildFid(OBJ_TYPE_CRITTER, v5, FID_ANIM_TYPE(critter->fid), (critter->fid & 0xF000) >> 12, critter->rotation);
objectSetFid(critter, fid, &updatedRect);
v11 = 3;
}
@ -1165,7 +1165,7 @@ static int _protinst_default_use_item(Object* a1, Object* a2, Object* item)
int rc;
switch (itemGetType(item)) {
case ITEM_TYPE_DRUG:
if ((a2->pid >> 24) != OBJ_TYPE_CRITTER) {
if (PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) {
if (a1 == gDude) {
// That does nothing
messageListItem.num = 582;
@ -1422,7 +1422,7 @@ int _check_scenery_ap_cost(Object* obj, Object* a2)
// 0x49C740
int _obj_use(Object* a1, Object* a2)
{
int type = (a2->fid & 0xF000000) >> 24;
int type = FID_TYPE(a2->fid);
if (a1 == gDude) {
if (type != OBJ_TYPE_SCENERY) {
return -1;
@ -1438,7 +1438,7 @@ int _obj_use(Object* a1, Object* a2)
return -1;
}
if ((a2->pid >> 24) == OBJ_TYPE_SCENERY && sceneryProto->scenery.type == SCENERY_TYPE_DOOR) {
if (PID_TYPE(a2->pid) == OBJ_TYPE_SCENERY && sceneryProto->scenery.type == SCENERY_TYPE_DOOR) {
return _obj_use_door(a1, a2, 0);
}
@ -1457,7 +1457,7 @@ int _obj_use(Object* a1, Object* a2)
}
if (!scriptOverrides) {
if ((a2->pid >> 24) == OBJ_TYPE_SCENERY) {
if (PID_TYPE(a2->pid) == OBJ_TYPE_SCENERY) {
if (sceneryProto->scenery.type == SCENERY_TYPE_LADDER_DOWN) {
if (useLadderDown(a1, a2, 0) == 0) {
scriptOverrides = true;
@ -1498,21 +1498,21 @@ int _obj_use(Object* a1, Object* a2)
// 0x49C900
static int useLadderDown(Object* a1, Object* ladder, int a3)
{
int builtTile = ladder->data.scenery.ladder.field_4;
int builtTile = ladder->data.scenery.ladder.destinationBuiltTile;
if (builtTile == -1) {
return -1;
}
int tile = builtTile & 0x3FFFFFF;
int elevation = (builtTile & 0xE0000000) >> 29;
if (ladder->data.scenery.ladder.field_0 != 0) {
int tile = builtTileGetTile(builtTile);
int elevation = builtTileGetElevation(builtTile);
if (ladder->data.scenery.ladder.destinationMap != 0) {
MapTransition transition;
memset(&transition, 0, sizeof(transition));
transition.map = ladder->data.scenery.ladder.field_0;
transition.map = ladder->data.scenery.ladder.destinationMap;
transition.elevation = elevation;
transition.tile = tile;
transition.rotation = (builtTile & 0x1C000000) >> 26;
transition.rotation = builtTileGetRotation(builtTile);
mapSetTransition(&transition);
@ -1532,21 +1532,21 @@ static int useLadderDown(Object* a1, Object* ladder, int a3)
// 0x49C9A4
static int useLadderUp(Object* a1, Object* ladder, int a3)
{
int builtTile = ladder->data.scenery.ladder.field_4;
int builtTile = ladder->data.scenery.ladder.destinationBuiltTile;
if (builtTile == -1) {
return -1;
}
int tile = builtTile & 0x3FFFFFF;
int elevation = (builtTile & 0xE0000000) >> 29;
if (ladder->data.scenery.ladder.field_0 != 0) {
int tile = builtTileGetTile(builtTile);
int elevation = builtTileGetElevation(builtTile);
if (ladder->data.scenery.ladder.destinationMap != 0) {
MapTransition transition;
memset(&transition, 0, sizeof(transition));
transition.map = ladder->data.scenery.ladder.field_0;
transition.map = ladder->data.scenery.ladder.destinationMap;
transition.elevation = elevation;
transition.tile = tile;
transition.rotation = (builtTile & 0x1C000000) >> 26;
transition.rotation = builtTileGetRotation(builtTile);
mapSetTransition(&transition);
@ -1566,21 +1566,21 @@ static int useLadderUp(Object* a1, Object* ladder, int a3)
// 0x49CA48
static int useStairs(Object* a1, Object* stairs, int a3)
{
int builtTile = stairs->data.scenery.stairs.field_4;
int builtTile = stairs->data.scenery.stairs.destinationBuiltTile;
if (builtTile == -1) {
return -1;
}
int tile = builtTile & 0x3FFFFFF;
int elevation = (builtTile & 0xE0000000) >> 29;
if (stairs->data.scenery.stairs.field_0 > 0) {
int tile = builtTileGetTile(builtTile);
int elevation = builtTileGetElevation(builtTile);
if (stairs->data.scenery.stairs.destinationMap > 0) {
MapTransition transition;
memset(&transition, 0, sizeof(transition));
transition.map = stairs->data.scenery.stairs.field_0;
transition.map = stairs->data.scenery.stairs.destinationMap;
transition.elevation = elevation;
transition.tile = tile;
transition.rotation = (builtTile & 0x1C000000) >> 26;
transition.rotation = builtTileGetRotation(builtTile);
mapSetTransition(&transition);
@ -1734,31 +1734,31 @@ int _obj_use_door(Object* a1, Object* a2, int a3)
step = 1;
}
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
for (int i = start; i != end; i += step) {
if (i != 0) {
if (a3 == 0) {
reg_anim_11_0(a2, a2, _set_door_state_closed, -1);
animationRegisterCallback(a2, a2, (AnimationCallback*)_set_door_state_closed, -1);
}
const char* sfx = sfxBuildOpenName(a2, SCENERY_SOUND_EFFECT_CLOSED);
reg_anim_play_sfx(a2, sfx, -1);
animationRegisterPlaySoundEffect(a2, sfx, -1);
reg_anim_animate_reverse(a2, 0, 0);
animationRegisterAnimateReversed(a2, ANIM_STAND, 0);
} else {
if (a3 == 0) {
reg_anim_11_0(a2, a2, _set_door_state_open, -1);
animationRegisterCallback(a2, a2, (AnimationCallback*)_set_door_state_open, -1);
}
const char* sfx = sfxBuildOpenName(a2, SCENERY_SOUND_EFFECT_CLOSED);
reg_anim_play_sfx(a2, sfx, -1);
animationRegisterPlaySoundEffect(a2, sfx, -1);
reg_anim_animate(a2, 0, 0);
animationRegisterAnimate(a2, ANIM_STAND, 0);
}
}
reg_anim_11_1(a2, a2, _check_door_state, -1);
animationRegisterCallbackForced(a2, a2, (AnimationCallback*)_check_door_state, -1);
reg_anim_end();
}
@ -1769,7 +1769,7 @@ int _obj_use_door(Object* a1, Object* a2, int a3)
// 0x49CE7C
int _obj_use_container(Object* critter, Object* item)
{
if (((item->fid & 0xF000000) >> 24) != OBJ_TYPE_ITEM) {
if (FID_TYPE(item->fid) != OBJ_TYPE_ITEM) {
return -1;
}
@ -1817,16 +1817,16 @@ int _obj_use_container(Object* critter, Object* item)
return -1;
}
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
if (item->frame == 0) {
const char* sfx = sfxBuildOpenName(item, SCENERY_SOUND_EFFECT_OPEN);
reg_anim_play_sfx(item, sfx, 0);
reg_anim_animate(item, 0, 0);
animationRegisterPlaySoundEffect(item, sfx, 0);
animationRegisterAnimate(item, ANIM_STAND, 0);
} else {
const char* sfx = sfxBuildOpenName(item, SCENERY_SOUND_EFFECT_CLOSED);
reg_anim_play_sfx(item, sfx, 0);
reg_anim_animate_reverse(item, 0, 0);
animationRegisterPlaySoundEffect(item, sfx, 0);
animationRegisterAnimateReversed(item, ANIM_STAND, 0);
}
reg_anim_end();
@ -1902,7 +1902,7 @@ static bool _obj_is_lockable(Object* obj)
return false;
}
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
if (proto->item.type == ITEM_TYPE_CONTAINER) {
return true;
@ -1926,7 +1926,7 @@ bool objectIsLocked(Object* obj)
}
ObjectData* data = &(obj->data);
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
return data->flags & CONTAINER_FLAG_LOCKED;
case OBJ_TYPE_SCENERY:
@ -1943,7 +1943,7 @@ int objectLock(Object* object)
return -1;
}
switch (object->pid >> 24) {
switch (PID_TYPE(object->pid)) {
case OBJ_TYPE_ITEM:
object->data.flags |= OBJ_LOCKED;
break;
@ -1964,7 +1964,7 @@ int objectUnlock(Object* object)
return -1;
}
switch (object->pid >> 24) {
switch (PID_TYPE(object->pid)) {
case OBJ_TYPE_ITEM:
object->data.flags &= ~OBJ_LOCKED;
return 0;
@ -1989,7 +1989,7 @@ static bool _obj_is_openable(Object* obj)
return false;
}
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
if (proto->item.type == ITEM_TYPE_CONTAINER) {
return true;
@ -2028,24 +2028,24 @@ static int objectOpenClose(Object* obj)
objectUnjamLock(obj);
reg_anim_begin(2);
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
if (obj->frame != 0) {
reg_anim_11_1(obj, obj, _set_door_state_closed, -1);
animationRegisterCallbackForced(obj, obj, (AnimationCallback*)_set_door_state_closed, -1);
const char* sfx = sfxBuildOpenName(obj, SCENERY_SOUND_EFFECT_CLOSED);
reg_anim_play_sfx(obj, sfx, -1);
animationRegisterPlaySoundEffect(obj, sfx, -1);
reg_anim_animate_reverse(obj, 0, 0);
animationRegisterAnimateReversed(obj, ANIM_STAND, 0);
} else {
reg_anim_11_1(obj, obj, _set_door_state_open, -1);
animationRegisterCallbackForced(obj, obj, (AnimationCallback*)_set_door_state_open, -1);
const char* sfx = sfxBuildOpenName(obj, SCENERY_SOUND_EFFECT_OPEN);
reg_anim_play_sfx(obj, sfx, -1);
reg_anim_animate(obj, 0, 0);
animationRegisterPlaySoundEffect(obj, sfx, -1);
animationRegisterAnimate(obj, ANIM_STAND, 0);
}
reg_anim_11_1(obj, obj, _check_door_state, -1);
animationRegisterCallbackForced(obj, obj, (AnimationCallback*)_check_door_state, -1);
reg_anim_end();
@ -2079,7 +2079,7 @@ static bool objectIsJammed(Object* obj)
return false;
}
if ((obj->pid >> 24) == OBJ_TYPE_SCENERY) {
if (PID_TYPE(obj->pid) == OBJ_TYPE_SCENERY) {
if ((obj->data.scenery.door.openFlags & OBJ_JAMMED) != 0) {
return true;
}
@ -2101,7 +2101,7 @@ int objectJamLock(Object* obj)
}
ObjectData* data = &(obj->data);
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
data->flags |= CONTAINER_FLAG_JAMMED;
break;
@ -2121,7 +2121,7 @@ int objectUnjamLock(Object* obj)
}
ObjectData* data = &(obj->data);
switch (obj->pid >> 24) {
switch (PID_TYPE(obj->pid)) {
case OBJ_TYPE_ITEM:
data->flags &= ~CONTAINER_FLAG_JAMMED;
break;

View File

@ -362,8 +362,8 @@ typedef struct {
} SceneryProtoStairsData;
typedef struct {
int field_0; // d.lower_tile
int field_4; // d.upper_tile
int type;
int level;
} SceneryProtoElevatorData;
typedef struct {

View File

@ -36,7 +36,7 @@ typedef struct WithdrawalEvent {
typedef struct ScriptEvent {
int sid;
int field_4;
int fixedParam;
} ScriptEvent;
typedef struct RadiationEvent {

View File

@ -44,6 +44,82 @@ void _regionSetBound(Region* region)
}
}
// 0x4A2C14
bool regionContainsPoint(Region* region, int x, int y)
{
if (region == NULL) {
return false;
}
if (x < region->field_24 || x > region->field_2C || y < region->field_28 || y > region->field_30) {
return false;
}
int v1;
Point* prev = &(region->points[0]);
if (x >= prev->x) {
if (y >= prev->y) {
v1 = 2;
} else {
v1 = 1;
}
} else {
if (y >= prev->y) {
v1 = 3;
} else {
v1 = 0;
}
}
int v4 = 0;
for (int index = 0; index < region->pointsLength; index++) {
int v2;
Point* point = &(region->points[index + 1]);
if (x >= point->x) {
if (y >= point->y) {
v2 = 2;
} else {
v2 = 1;
}
} else {
if (y >= point->y) {
v2 = 3;
} else {
v2 = 0;
}
}
int v3 = v2 - v1;
switch (v3) {
case -3:
v3 = 1;
break;
case -2:
case 2:
if ((double)x < ((double)point->x - (double)(prev->x - point->x) / (double)(prev->y - point->y) * (double)(point->y - y))) {
v3 = -v3;
}
break;
case 3:
v3 = -1;
break;
}
prev = point;
v1 = v2;
v4 += v3;
}
if (v4 == 4 || v4 == -4) {
return true;
}
return false;
}
// 0x4A2D78
Region* regionCreate(int initialCapacity)
{
@ -62,24 +138,24 @@ Region* regionCreate(int initialCapacity)
region->field_74 = 0;
region->field_28 = INT_MIN;
region->field_30 = INT_MAX;
region->field_54 = 0;
region->field_5C = 0;
region->field_64 = 0;
region->procs[3] = 0;
region->rightProcs[1] = 0;
region->rightProcs[3] = 0;
region->field_68 = 0;
region->field_6C = 0;
region->rightProcs[0] = 0;
region->field_70 = 0;
region->field_60 = 0;
region->field_78 = 0;
region->field_7C = 0;
region->field_80 = 0;
region->field_84 = 0;
region->rightProcs[2] = 0;
region->mouseEventCallback = NULL;
region->rightMouseEventCallback = NULL;
region->mouseEventCallbackUserData = 0;
region->rightMouseEventCallbackUserData = 0;
region->pointsLength = 0;
region->field_24 = 0;
region->field_2C = 0;
region->field_50 = 0;
region->field_4C = 0;
region->field_48 = 0;
region->field_58 = 0;
region->field_24 = region->field_28;
region->field_2C = region->field_30;
region->procs[2] = 0;
region->procs[1] = 0;
region->procs[0] = 0;
region->rightProcs[0] = 0;
return region;
}

View File

@ -6,6 +6,10 @@
#define REGION_NAME_LENGTH (32)
typedef struct Region Region;
typedef void RegionMouseEventCallback(Region* region, void* userData, int event);
typedef struct Region {
char name[REGION_NAME_LENGTH];
Point* points;
@ -18,22 +22,16 @@ typedef struct Region {
int pointsLength;
int pointsCapacity;
Program* program;
int field_48;
int field_4C;
int field_50;
int field_54;
int field_58;
int field_5C;
int field_60;
int field_64;
int procs[4];
int rightProcs[4];
int field_68;
int field_6C;
int field_70;
int field_74;
int field_78;
int field_7C;
int field_80;
int field_84;
RegionMouseEventCallback* mouseEventCallback;
RegionMouseEventCallback* rightMouseEventCallback;
void* mouseEventCallbackUserData;
void* rightMouseEventCallbackUserData;
void* userData;
} Region;

View File

@ -29,8 +29,8 @@
#include "window_manager_private.h"
#include "world_map.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@ -567,12 +567,12 @@ Object* scriptGetSelf(Program* program)
return script->owner;
}
if ((sid >> 24) != SCRIPT_TYPE_SPATIAL) {
if (SID_TYPE(sid) != SCRIPT_TYPE_SPATIAL) {
return NULL;
}
Object* object;
int fid = buildFid(6, 3, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, 3, 0, 0, 0);
objectCreateWithFidPid(&object, fid, -1);
objectHide(object, NULL);
_obj_toggle_flat(object, NULL);
@ -595,7 +595,7 @@ Object* scriptGetSelf(Program* program)
Script* spatialScript = scriptGetFirstSpatialScript(elevation);
while (spatialScript != NULL) {
if (spatialScript == script) {
objectSetLocation(object, script->sp.built_tile & 0x3FFFFFF, elevation, NULL);
objectSetLocation(object, builtTileGetTile(script->sp.built_tile), elevation, NULL);
return object;
}
spatialScript = scriptGetNextSpatialScript();
@ -780,7 +780,7 @@ void _scrSetQueueTestVals(Object* a1, int a2)
int _scrQueueRemoveFixed(Object* obj, void* data)
{
ScriptEvent* scriptEvent = (ScriptEvent*)data;
return obj == _scrQueueTestObj && scriptEvent->field_4 == _scrQueueTestValue;
return obj == _scrQueueTestObj && scriptEvent->fixedParam == _scrQueueTestValue;
}
// 0x4A3E60
@ -792,7 +792,7 @@ int scriptAddTimerEvent(int sid, int delay, int param)
}
scriptEvent->sid = sid;
scriptEvent->field_4 = param;
scriptEvent->fixedParam = param;
Script* script;
if (scriptGetScript(sid, &script) == -1) {
@ -814,7 +814,7 @@ int scriptEventWrite(File* stream, void* data)
ScriptEvent* scriptEvent = (ScriptEvent*)data;
if (fileWriteInt32(stream, scriptEvent->sid) == -1) return -1;
if (fileWriteInt32(stream, scriptEvent->field_4) == -1) return -1;
if (fileWriteInt32(stream, scriptEvent->fixedParam) == -1) return -1;
return 0;
}
@ -828,7 +828,7 @@ int scriptEventRead(File* stream, void** dataPtr)
}
if (fileReadInt32(stream, &(scriptEvent->sid)) == -1) goto err;
if (fileReadInt32(stream, &(scriptEvent->field_4)) == -1) goto err;
if (fileReadInt32(stream, &(scriptEvent->fixedParam)) == -1) goto err;
*dataPtr = scriptEvent;
@ -852,7 +852,7 @@ int scriptEventProcess(Object* obj, void* data)
return 0;
}
script->fixedParam = scriptEvent->field_4;
script->fixedParam = scriptEvent->fixedParam;
scriptExecProc(scriptEvent->sid, SCRIPT_PROC_TIMED);
@ -929,7 +929,7 @@ int scriptsHandleRequests()
Object* elevatorDoors = objectFindFirstAtElevation(gDude->elevation);
while (elevatorDoors != NULL) {
int pid = elevatorDoors->pid;
if ((pid >> 24) == OBJ_TYPE_SCENERY
if (PID_TYPE(pid) == OBJ_TYPE_SCENERY
&& (pid == PROTO_ID_0x2000099 || pid == PROTO_ID_0x20001A5 || pid == PROTO_ID_0x20001D6)
&& tileDistanceBetween(elevatorDoors->tile, gDude->tile) <= 4) {
break;
@ -955,7 +955,7 @@ int scriptsHandleRequests()
Object* elevatorDoors = objectFindFirstAtElevation(gDude->elevation);
while (elevatorDoors != NULL) {
int pid = elevatorDoors->pid;
if ((pid >> 24) == OBJ_TYPE_SCENERY
if (PID_TYPE(pid) == OBJ_TYPE_SCENERY
&& (pid == PROTO_ID_0x2000099 || pid == PROTO_ID_0x20001A5 || pid == PROTO_ID_0x20001D6)
&& tileDistanceBetween(elevatorDoors->tile, gDude->tile) <= 4) {
break;
@ -1035,7 +1035,7 @@ int _scripts_check_state_in_combat()
Object* elevatorDoors = objectFindFirstAtElevation(gDude->elevation);
while (elevatorDoors != NULL) {
int pid = elevatorDoors->pid;
if ((pid >> 24) == OBJ_TYPE_SCENERY
if (PID_TYPE(pid) == OBJ_TYPE_SCENERY
&& (pid == PROTO_ID_0x2000099 || pid == PROTO_ID_0x20001A5 || pid == PROTO_ID_0x20001D6)
&& tileDistanceBetween(elevatorDoors->tile, gDude->tile) <= 4) {
break;
@ -1137,8 +1137,8 @@ int scriptsRequestElevator(Object* a1, int a2)
return -1;
}
// TODO: What the hell is this?
tile -= 1005;
// In the following code we are looking for an elevator. 5 tiles in each direction
tile = tile - (HEX_GRID_WIDTH * 5) - 5; // left upper corner
Object* obj;
for (int y = -5; y < 5; y++) {
@ -1163,12 +1163,12 @@ int scriptsRequestElevator(Object* a1, int a2)
break;
}
tile += 190;
tile += HEX_GRID_WIDTH - 10;
}
if (obj != NULL) {
elevatorType = obj->data.scenery.elevator.field_0;
elevatorLevel = obj->data.scenery.elevator.field_4;
elevatorType = obj->data.scenery.elevator.type;
elevatorLevel = obj->data.scenery.elevator.level;
}
if (elevatorType == -1) {
@ -1224,6 +1224,13 @@ int scriptsRequestStealing(Object* a1, Object* a2)
return 0;
}
// NOTE: Inlined.
void _script_make_path(char* path)
{
strcpy(path, _cd_path_base);
strcat(path, gScriptsBasePath);
}
// exec_script_proc
// 0x4A4810
int scriptExecProc(int sid, int proc)
@ -1341,7 +1348,8 @@ bool scriptHasProc(int sid, int proc)
static int scriptsLoadScriptsList()
{
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s", "scripts\\", "scripts.lst");
_script_make_path(path);
strcat(path, "scripts.lst");
File* stream = fileOpen(path, "rt");
if (stream == NULL) {
@ -1716,8 +1724,7 @@ static int _scr_header_load()
_num_script_indexes = 0;
char path[COMPAT_MAX_PATH];
strcpy(path, _cd_path_base);
strcat(path, gScriptsBasePath);
_script_make_path(path);
strcat(path, "scripts.lst");
File* stream = fileOpen(path, "rt");
@ -1757,7 +1764,7 @@ static int scriptWrite(Script* scr, File* stream)
if (fileWriteInt32(stream, scr->sid) == -1) return -1;
if (fileWriteInt32(stream, scr->field_4) == -1) return -1;
switch (scr->sid >> 24) {
switch (SID_TYPE(scr->sid)) {
case SCRIPT_TYPE_SPATIAL:
if (fileWriteInt32(stream, scr->sp.built_tile) == -1) return -1;
if (fileWriteInt32(stream, scr->sp.radius) == -1) return -1;
@ -1911,7 +1918,7 @@ static int scriptRead(Script* scr, File* stream)
if (fileReadInt32(stream, &(scr->sid)) == -1) return -1;
if (fileReadInt32(stream, &(scr->field_4)) == -1) return -1;
switch (scr->sid >> 24) {
switch (SID_TYPE(scr->sid)) {
case SCRIPT_TYPE_SPATIAL:
if (fileReadInt32(stream, &(scr->sp.built_tile)) == -1) return -1;
if (fileReadInt32(stream, &(scr->sp.radius)) == -1) return -1;
@ -2066,7 +2073,7 @@ int scriptGetScript(int sid, Script** scriptPtr)
return -1;
}
ScriptList* scriptList = &(gScriptLists[sid >> 24]);
ScriptList* scriptList = &(gScriptLists[SID_TYPE(sid)]);
ScriptListExtent* scriptListExtent = scriptList->head;
while (scriptListExtent != NULL) {
@ -2221,7 +2228,7 @@ int scriptRemove(int sid)
return -1;
}
ScriptList* scriptList = &(gScriptLists[sid >> 24]);
ScriptList* scriptList = &(gScriptLists[SID_TYPE(sid)]);
ScriptListExtent* scriptListExtent = scriptList->head;
int index;
@ -2399,7 +2406,7 @@ static Script* scriptGetFirstSpatialScript(int elevation)
}
Script* script = &(gScriptsEnumerationScriptListExtent->scripts[0]);
if ((script->flags & SCRIPT_FLAG_0x02) != 0 || ((script->sp.built_tile & 0xE0000000) >> 29) != elevation) {
if ((script->flags & SCRIPT_FLAG_0x02) != 0 || builtTileGetElevation(script->sp.built_tile) != elevation) {
script = scriptGetNextSpatialScript();
}
@ -2431,7 +2438,7 @@ static Script* scriptGetNextSpatialScript()
}
Script* script = &(scriptListExtent->scripts[scriptIndex]);
if ((script->flags & SCRIPT_FLAG_0x02) == 0 && ((script->sp.built_tile & 0xE0000000) >> 29) == gScriptsEnumerationElevation) {
if ((script->flags & SCRIPT_FLAG_0x02) == 0 && builtTileGetElevation(script->sp.built_tile) == gScriptsEnumerationElevation) {
break;
}
}
@ -2486,7 +2493,7 @@ bool scriptsExecSpatialProc(Object* object, int tile, int elevation)
_scr_SpatialsEnabled = false;
int builtTile = ((elevation << 29) & 0xE0000000) | tile;
int builtTile = builtTileCreate(tile, elevation);
for (Script* script = scriptGetFirstSpatialScript(elevation); script != NULL; script = scriptGetNextSpatialScript()) {
if (builtTile == script->sp.built_tile) {
@ -2497,7 +2504,7 @@ bool scriptsExecSpatialProc(Object* object, int tile, int elevation)
continue;
}
int distance = tileDistanceBetween(script->sp.built_tile & 0x3FFFFFF, tile);
int distance = tileDistanceBetween(builtTileGetTile(script->sp.built_tile), tile);
if (distance > script->sp.radius) {
continue;
}
@ -2686,7 +2693,7 @@ char* _scr_get_msg_str_speech(int messageListId, int messageId, int a3)
return NULL;
}
if (((gGameDialogHeadFid & 0xF000000) >> 24) != 8) {
if (FID_TYPE(gGameDialogHeadFid) != OBJ_TYPE_HEAD) {
a3 = 0;
}
@ -2717,7 +2724,7 @@ char* _scr_get_msg_str_speech(int messageListId, int messageId, int a3)
// 0x4A6D64
int scriptGetLocalVar(int sid, int variable, int* value)
{
if (sid >> 24 == SCRIPT_TYPE_SYSTEM) {
if (SID_TYPE(sid) == SCRIPT_TYPE_SYSTEM) {
debugPrint("\nError! System scripts/Map scripts not allowed local_vars! ");
_tempStr1[0] = '\0';
@ -2859,8 +2866,8 @@ int _scr_explode_scenery(Object* a1, int tile, int radius, int elevation)
}
if (script->procs[SCRIPT_PROC_DAMAGE] > 0
&& (script->sp.built_tile & 0xE0000000) >> 29 == elevation
&& tileDistanceBetween(script->sp.built_tile & 0x3FFFFFF, tile) <= radius) {
&& builtTileGetElevation(script->sp.built_tile) == elevation
&& tileDistanceBetween(builtTileGetTile(script->sp.built_tile), tile) <= radius) {
scriptIds[scriptsCount] = script->sid;
scriptsCount += 1;
}

View File

@ -12,6 +12,9 @@
#define SCRIPT_FLAG_0x08 (0x08)
#define SCRIPT_FLAG_0x10 (0x10)
// 60 * 60 * 10
#define GAME_TIME_TICKS_PER_HOUR 36000
// 24 * 60 * 60 * 10
#define GAME_TIME_TICKS_PER_DAY (864000)
@ -175,6 +178,7 @@ void scriptsRequestDialog(Object* a1);
void scriptsRequestEndgame();
int scriptsRequestLooting(Object* a1, Object* a2);
int scriptsRequestStealing(Object* a1, Object* a2);
void _script_make_path(char* path);
int scriptExecProc(int sid, int proc);
bool scriptHasProc(int sid, int proc);
int _scr_find_str_run_info(int a1, int* a2, int sid);

View File

@ -1,15 +1,18 @@
#include "selfrun.h"
#include "core.h"
#include "db.h"
#include "game.h"
#include "game_config.h"
#include "platform_compat.h"
#include <stdlib.h>
// 0x51C8D8
int _selfrun_state = 0;
int gSelfrunState = SELFRUN_STATE_TURNED_OFF;
// 0x4A8BE0
int _selfrun_get_list(char*** fileListPtr, int* fileListLengthPtr)
int selfrunInitFileList(char*** fileListPtr, int* fileListLengthPtr)
{
if (fileListPtr == NULL) {
return -1;
@ -25,7 +28,7 @@ int _selfrun_get_list(char*** fileListPtr, int* fileListLengthPtr)
}
// 0x4A8C10
int _selfrun_free_list(char*** fileListPtr)
int selfrunFreeFileList(char*** fileListPtr)
{
if (fileListPtr == NULL) {
return -1;
@ -36,9 +39,198 @@ int _selfrun_free_list(char*** fileListPtr)
return 0;
}
// 0x4A8C28
int selfrunPreparePlayback(const char* fileName, SelfrunData* selfrunData)
{
if (fileName == NULL) {
return -1;
}
if (selfrunData == NULL) {
return -1;
}
if (vcrGetState() != VCR_STATE_TURNED_OFF) {
return -1;
}
if (gSelfrunState != SELFRUN_STATE_TURNED_OFF) {
return -1;
}
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s", "selfrun\\", fileName);
if (selfrunReadData(path, selfrunData) != 0) {
return -1;
}
gSelfrunState = SELFRUN_STATE_PLAYING;
return 0;
}
// 0x4A8C88
void selfrunPlaybackLoop(SelfrunData* selfrunData)
{
if (gSelfrunState == SELFRUN_STATE_PLAYING) {
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s", "selfrun\\", selfrunData->recordingFileName);
if (vcrPlay(path, VCR_TERMINATE_ON_KEY_PRESS | VCR_TERMINATE_ON_MOUSE_PRESS, selfrunPlaybackCompleted)) {
bool cursorWasHidden = cursorIsHidden();
if (cursorWasHidden) {
mouseShowCursor();
}
while (gSelfrunState == SELFRUN_STATE_PLAYING) {
int keyCode = _get_input();
if (keyCode != selfrunData->stopKeyCode) {
gameHandleKey(keyCode, false);
}
}
while (mouseGetEvent() != 0) {
_get_input();
}
if (cursorWasHidden) {
mouseHideCursor();
}
}
}
}
// 0x4A8D28
int selfrunPrepareRecording(const char* recordingName, const char* mapFileName, SelfrunData* selfrunData)
{
if (recordingName == NULL) {
return -1;
}
if (mapFileName == NULL) {
return -1;
}
if (vcrGetState() != VCR_STATE_TURNED_OFF) {
return -1;
}
if (gSelfrunState != SELFRUN_STATE_TURNED_OFF) {
return -1;
}
sprintf(selfrunData->recordingFileName, "%s%s", recordingName, ".vcr");
strcpy(selfrunData->mapFileName, mapFileName);
selfrunData->stopKeyCode = KEY_CTRL_R;
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s%s", "selfrun\\", recordingName, ".sdf");
if (selfrunWriteData(path, selfrunData) != 0) {
return -1;
}
gSelfrunState = SELFRUN_STATE_RECORDING;
return 0;
}
// 0x4A8DDC
void selfrunRecordingLoop(SelfrunData* selfrunData)
{
if (gSelfrunState == SELFRUN_STATE_RECORDING) {
char path[COMPAT_MAX_PATH];
sprintf(path, "%s%s", "selfrun\\", selfrunData->recordingFileName);
if (vcrRecord(path)) {
if (!cursorIsHidden()) {
mouseShowCursor();
}
bool done = false;
while (!done) {
int keyCode = _get_input();
if (keyCode == selfrunData->stopKeyCode) {
vcrStop();
_game_user_wants_to_quit = 2;
done = true;
} else {
gameHandleKey(keyCode, false);
}
}
}
gSelfrunState = SELFRUN_STATE_TURNED_OFF;
}
}
// 0x4A8E74
void _selfrun_playback_callback()
void selfrunPlaybackCompleted(int reason)
{
_game_user_wants_to_quit = 2;
_selfrun_state = 0;
gSelfrunState = SELFRUN_STATE_TURNED_OFF;
}
// 0x4A8E8C
int selfrunReadData(const char* path, SelfrunData* selfrunData)
{
if (path == NULL) {
return -1;
}
if (selfrunData == NULL) {
return -1;
}
File* stream = fileOpen(path, "rb");
if (stream == NULL) {
return -1;
}
int rc = -1;
if (fileReadFixedLengthString(stream, selfrunData->recordingFileName, SELFRUN_RECORDING_FILE_NAME_LENGTH) == 0
&& fileReadFixedLengthString(stream, selfrunData->mapFileName, SELFRUN_MAP_FILE_NAME_LENGTH) == 0
&& fileReadInt32(stream, &(selfrunData->stopKeyCode)) == 0) {
rc = 0;
}
fileClose(stream);
return rc;
}
// 0x4A8EF4
int selfrunWriteData(const char* path, SelfrunData* selfrunData)
{
if (path == NULL) {
return -1;
}
if (selfrunData == NULL) {
return -1;
}
char* masterPatches;
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_MASTER_PATCHES_KEY, &masterPatches);
char selfrunDirectoryPath[COMPAT_MAX_PATH];
sprintf(selfrunDirectoryPath, "%s\\%s", masterPatches, "selfrun\\");
compat_mkdir(selfrunDirectoryPath);
File* stream = fileOpen(path, "wb");
if (stream == NULL) {
return -1;
}
int rc = -1;
if (fileWriteFixedLengthString(stream, selfrunData->recordingFileName, SELFRUN_RECORDING_FILE_NAME_LENGTH) == 0
&& fileWriteFixedLengthString(stream, selfrunData->mapFileName, SELFRUN_MAP_FILE_NAME_LENGTH) == 0
&& fileWriteInt32(stream, selfrunData->stopKeyCode) == 0) {
rc = 0;
}
fileClose(stream);
return rc;
}

View File

@ -1,10 +1,33 @@
#ifndef SELFRUN_H
#define SELFRUN_H
extern int _selfrun_state;
#define SELFRUN_RECORDING_FILE_NAME_LENGTH 13
#define SELFRUN_MAP_FILE_NAME_LENGTH 13
int _selfrun_get_list(char*** fileListPtr, int* fileListLengthPtr);
int _selfrun_free_list(char*** fileListPtr);
void _selfrun_playback_callback();
typedef enum SelfrunState {
SELFRUN_STATE_TURNED_OFF,
SELFRUN_STATE_PLAYING,
SELFRUN_STATE_RECORDING,
} SelfrunState;
typedef struct SelfrunData {
char recordingFileName[SELFRUN_RECORDING_FILE_NAME_LENGTH];
char mapFileName[SELFRUN_MAP_FILE_NAME_LENGTH];
int stopKeyCode;
} SelfrunData;
static_assert(sizeof(SelfrunData) == 32, "wrong size");
extern int gSelfrunState;
int selfrunInitFileList(char*** fileListPtr, int* fileListLengthPtr);
int selfrunFreeFileList(char*** fileListPtr);
int selfrunPreparePlayback(const char* fileName, SelfrunData* selfrunData);
void selfrunPlaybackLoop(SelfrunData* selfrunData);
int selfrunPrepareRecording(const char* recordingName, const char* mapFileName, SelfrunData* selfrunData);
void selfrunRecordingLoop(SelfrunData* selfrunData);
void selfrunPlaybackCompleted(int reason);
int selfrunReadData(const char* path, SelfrunData* selfrunData);
int selfrunWriteData(const char* path, SelfrunData* selfrunData);
#endif /* SELFRUN_H */

View File

@ -1032,7 +1032,7 @@ int skillsPerformStealing(Object* a1, Object* a2, Object* item, bool isPlanting)
// -4% per item size
stealModifier -= 4 * itemGetSize(item);
if (((a2->fid & 0xF000000) >> 24) == OBJ_TYPE_CRITTER) {
if (FID_TYPE(a2->fid) == OBJ_TYPE_CRITTER) {
// check facing: -25% if face to face
if (_is_hit_from_front(a1, a2)) {
stealModifier -= 25;
@ -1064,7 +1064,7 @@ int skillsPerformStealing(Object* a1, Object* a2, Object* item, bool isPlanting)
catchRoll = ROLL_SUCCESS;
} else {
int catchChance;
if ((a2->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(a2->pid) == OBJ_TYPE_CRITTER) {
catchChance = skillGetValue(a2, SKILL_STEAL) - stealModifier;
} else {
catchChance = 30 - stealModifier;

View File

@ -162,7 +162,7 @@ static int skilldexWindowInit()
int frmIndex;
for (frmIndex = 0; frmIndex < SKILLDEX_FRM_COUNT; frmIndex++) {
int fid = buildFid(6, gSkilldexFrmIds[frmIndex], 0, 0, 0);
int fid = buildFid(OBJ_TYPE_INTERFACE, gSkilldexFrmIds[frmIndex], 0, 0, 0);
gSkilldexFrmData[frmIndex] = artLockFrameDataReturningSize(fid, &(gSkilldexFrmHandles[frmIndex]), &(gSkilldexFrmSizes[frmIndex].width), &(gSkilldexFrmSizes[frmIndex].height));
if (gSkilldexFrmData[frmIndex] == NULL) {
break;

View File

@ -446,7 +446,6 @@ Sound* soundAllocate(int a1, int a2)
sound->field_78 = _numBuffers;
sound->readLimit = sound->field_7C * _numBuffers;
if (a1 & 0x10) {
sound->field_50 = -1;
sound->field_3C |= 0x20;

View File

@ -57,13 +57,13 @@ typedef enum Stat {
STAT_CURRENT_POISON_LEVEL,
STAT_CURRENT_RADIATION_LEVEL,
STAT_COUNT,
// Number of primary stats.
PRIMARY_STAT_COUNT = 7,
// Number of SPECIAL stats (primary + secondary).
SPECIAL_STAT_COUNT = 33,
// Number of saveable stats (i.e. excluding CURRENT pseudostats).
SAVEABLE_STAT_COUNT = 35,
} Stat;
@ -81,4 +81,3 @@ typedef enum PcStat {
} PcStat;
#endif /* STAT_DEFS */

View File

@ -14,6 +14,7 @@
#include "platform_compat.h"
#include <assert.h>
#include <math.h>
#include <string.h>
typedef struct STRUCT_51D99C {
@ -1228,8 +1229,8 @@ void tileRenderRoofsInRect(Rect* rect, int elevation)
int frmId = gTileSquares[elevation]->field_0[squareTile];
frmId >>= 16;
if ((((frmId & 0xF000) >> 12) & 0x01) == 0) {
int fid = buildFid(4, frmId & 0xFFF, 0, 0, 0);
if (fid != buildFid(4, 1, 0, 0, 0)) {
int fid = buildFid(OBJ_TYPE_TILE, frmId & 0xFFF, 0, 0, 0);
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
int screenX;
int screenY;
squareTileToRoofScreenXY(squareTile, &screenX, &screenY, elevation);
@ -1250,7 +1251,7 @@ static void _roof_fill_on(int a1, int a2, int elevation)
int upper = (value >> 16) & 0xFFFF;
int id = upper & 0xFFF;
if (buildFid(4, id, 0, 0, 0) == buildFid(4, 1, 0, 0, 0)) {
if (buildFid(OBJ_TYPE_TILE, id, 0, 0, 0) == buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
break;
}
@ -1290,7 +1291,7 @@ static void sub_4B23DC(int a1, int a2, int elevation)
int upper = (value >> 16) & 0xFFFF;
int id = upper & 0xFFF;
if (buildFid(4, id, 0, 0, 0) == buildFid(4, 1, 0, 0, 0)) {
if (buildFid(OBJ_TYPE_TILE, id, 0, 0, 0) == buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
break;
}
@ -1462,7 +1463,7 @@ void tileRenderFloorsInRect(Rect* rect, int elevation)
int v12;
int v13;
squareTileToScreenXY(v3, &v12, &v13, elevation);
int fid = buildFid(4, frmId & 0xFFF, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_TILE, frmId & 0xFFF, 0, 0, 0);
tileRenderFloor(fid, v12, v13, rect);
}
}
@ -1486,10 +1487,10 @@ bool _square_roof_intersect(int x, int y, int elevation)
TileData* ptr = gTileSquares[elevation];
int idx = gSquareGridWidth * tileY + tileX;
int upper = ptr->field_0[gSquareGridWidth * tileY + tileX] >> 16;
int fid = buildFid(4, upper & 0xFFF, 0, 0, 0);
if (fid != buildFid(4, 1, 0, 0, 0)) {
int fid = buildFid(OBJ_TYPE_TILE, upper & 0xFFF, 0, 0, 0);
if (fid != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) {
if ((((upper & 0xF000) >> 12) & 1) == 0) {
int fid = buildFid(4, upper & 0xFFF, 0, 0, 0);
int fid = buildFid(OBJ_TYPE_TILE, upper & 0xFFF, 0, 0, 0);
CacheEntry* handle;
Art* art = artLock(fid, &handle);
if (art != NULL) {
@ -1583,7 +1584,7 @@ static void _draw_grid(int tile, int elevation, Rect* rect)
// 0x4B30C4
static void tileRenderFloor(int fid, int x, int y, Rect* rect)
{
if (artIsObjectTypeHidden((fid & 0xF000000) >> 24) != 0) {
if (artIsObjectTypeHidden(FID_TYPE(fid)) != 0) {
return;
}

View File

@ -5,7 +5,6 @@
#include "window.h"
static void _showRegion(int a1);
static int widgetGetTextFlags();
static unsigned char widgetGetHighlightColor();
// 0x50EB1C
@ -93,3 +92,9 @@ int widgetSetHighlightColor(float a1, float a2, float a3)
return 1;
}
// 0x4B5998
void sub_4B5998(int win)
{
// TODO: Incomplete.
}

View File

@ -4,9 +4,11 @@
int _update_widgets();
int widgetGetFont();
int widgetSetFont(int a1);
int widgetGetTextFlags();
int widgetSetTextFlags(int a1);
unsigned char widgetGetTextColor();
int widgetSetTextColor(float a1, float a2, float a3);
int widgetSetHighlightColor(float a1, float a2, float a3);
void sub_4B5998(int win);
#endif /* WIDGET_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,18 @@
#ifndef WINDOW_H
#define WINDOW_H
#include "geometry.h"
#include "interpreter.h"
#include "region.h"
#include "window_manager.h"
typedef void (*WINDOWDRAWINGPROC)(unsigned char* src, int src_pitch, int a3, int src_x, int src_y, int src_width, int src_height, int dest_x, int dest_y);
typedef void WindowDrawingProc2(unsigned char* buf, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, unsigned char a10);
typedef bool(WindowInputHandler)(int key);
typedef void(WindowDeleteCallback)(int windowIndex, const char* windowName);
typedef void(DisplayInWindowCallback)(int windowIndex, const char* windowName, unsigned char* data, int width, int height);
typedef void(ManagedButtonMouseEventCallback)(void* userData, int eventType);
typedef void(ManagedWindowCreateCallback)(int windowIndex, const char* windowName, int* flagsPtr);
typedef enum TextAlignment {
TEXT_ALIGNMENT_LEFT,
@ -12,6 +20,20 @@ typedef enum TextAlignment {
TEXT_ALIGNMENT_CENTER,
} TextAlignment;
typedef enum ManagedButtonMouseEvent {
MANAGED_BUTTON_MOUSE_EVENT_BUTTON_DOWN,
MANAGED_BUTTON_MOUSE_EVENT_BUTTON_UP,
MANAGED_BUTTON_MOUSE_EVENT_ENTER,
MANAGED_BUTTON_MOUSE_EVENT_EXIT,
MANAGED_BUTTON_MOUSE_EVENT_COUNT,
} ManagedButtonMouseEvent;
typedef enum ManagedButtonRightMouseEvent {
MANAGED_BUTTON_RIGHT_MOUSE_EVENT_BUTTON_DOWN,
MANAGED_BUTTON_RIGHT_MOUSE_EVENT_BUTTON_UP,
MANAGED_BUTTON_RIGHT_MOUSE_EVENT_COUNT,
} ManagedButtonRightMouseEvent;
extern int _currentHighlightColorR;
extern int gWidgetFont;
extern int _currentTextColorG;
@ -21,27 +43,86 @@ extern int _currentTextColorR;
extern int _currentHighlightColorG;
extern int _currentHighlightColorB;
bool _checkRegion(int windowIndex, int mouseX, int mouseY, int mouseEvent);
bool _windowCheckRegion(int windowIndex, int mouseX, int mouseY, int mouseEvent);
bool _windowRefreshRegions();
bool _checkAllRegions();
void _windowAddInputFunc(WindowInputHandler* handler);
void _doRegionRightFunc(Region* region, int a2);
void _doRegionFunc(Region* region, int a2);
bool _windowActivateRegion(const char* regionName, int a2);
int _getInput();
void _doButtonOn(int btn, int keyCode);
void sub_4B6F68(int btn, int mouseEvent);
void _doButtonOff(int btn, int keyCode);
void _doButtonPress(int btn, int keyCode);
void _doButtonRelease(int btn, int keyCode);
void _doRightButtonPress(int btn, int keyCode);
void sub_4B704C(int btn, int mouseEvent);
void _doRightButtonRelease(int btn, int keyCode);
void _setButtonGFX(int width, int height, unsigned char* normal, unsigned char* pressed, unsigned char* a5);
int _windowWidth();
int _windowHeight();
bool _windowDraw();
bool _deleteWindow(const char* windowName);
int sub_4B7AC4(const char* windowName, int x, int y, int width, int height);
int sub_4B7E7C(const char* windowName, int x, int y, int width, int height);
int _createWindow(const char* windowName, int x, int y, int width, int height, int a6, int flags);
int _windowOutput(char* string);
bool _windowGotoXY(int x, int y);
bool _selectWindowID(int index);
int _selectWindow(const char* windowName);
unsigned char* _windowGetBuffer();
int _pushWindow(const char* windowName);
int _popWindow();
void _windowPrintBuf(int win, char* string, int stringLength, int width, int maxY, int x, int y, int flags, int textAlignment);
char** _windowWordWrap(char* string, int maxLength, int a3, int* substringListLengthPtr);
void _windowFreeWordList(char** substringList, int substringListLength);
void _windowWrapLineWithSpacing(int win, char* string, int width, int height, int x, int y, int flags, int textAlignment, int a9);
void _windowWrapLine(int win, char* string, int width, int height, int x, int y, int flags, int textAlignment);
bool _windowPrintRect(char* string, int a2, int textAlignment);
bool _windowFormatMessage(char* string, int x, int y, int width, int height, int textAlignment);
bool _windowPrint(char* string, int a2, int x, int y, int a5);
void _displayInWindow(unsigned char* data, int width, int height, int pitch);
void _displayFile(char* fileName);
void _displayFileRaw(char* fileName);
bool _windowDisplay(char* fileName, int x, int y, int width, int height);
bool _windowDisplayBuf(unsigned char* src, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight);
int _windowGetXres();
int _windowGetYres();
void _removeProgramReferences_3(Program* program);
void _initWindow(int resolution, int a2);
void _windowClose();
bool _windowDeleteButton(const char* buttonName);
bool _windowSetButtonFlag(const char* buttonName, int value);
bool _windowAddButtonProc(const char* buttonName, Program* program, int a3, int a4, int a5, int a6);
bool _windowAddButton(const char* buttonName, int x, int y, int width, int height, int flags);
bool _windowAddButtonGfx(const char* buttonName, char* pressedFileName, char* normalFileName, char* hoverFileName);
bool _windowAddButtonProc(const char* buttonName, Program* program, int mouseEnterProc, int mouseExitProc, int mouseDownProc, int mouseUpProc);
bool _windowAddButtonRightProc(const char* buttonName, Program* program, int rightMouseDownProc, int rightMouseUpProc);
bool _windowAddButtonCfunc(const char* buttonName, ManagedButtonMouseEventCallback* callback, void* userData);
bool _windowAddButtonRightCfunc(const char* buttonName, ManagedButtonMouseEventCallback* callback, void* userData);
bool _windowAddButtonText(const char* buttonName, const char* text);
bool _windowAddButtonTextWithOffsets(const char* buttonName, const char* text, int pressedImageOffsetX, int pressedImageOffsetY, int normalImageOffsetX, int normalImageOffsetY);
bool _windowFill(float r, float g, float b);
bool _windowFillRect(int x, int y, int width, int height, float r, float g, float b);
void _windowEndRegion();
bool _windowCheckRegionExists(const char* regionName);
bool _windowStartRegion(int initialCapacity);
bool _windowAddRegionPoint(int x, int y, bool a3);
bool _windowAddRegionProc(const char* regionName, Program* program, int a3, int a4, int a5, int a6);
bool _windowAddRegionRightProc(const char* regionName, Program* program, int a3, int a4);
bool _windowSetRegionFlag(const char* regionName, int value);
bool _windowAddRegionName(const char* regionName);
bool _windowDeleteRegion(const char* regionName);
void _updateWindows();
int _windowMoviePlaying();
bool _windowSetMovieFlags(int flags);
bool _windowPlayMovie(char* filePath);
bool _windowPlayMovieRect(char* filePath, int a2, int a3, int a4, int a5);
void _windowStopMovie();
void _drawScaled(unsigned char* dest, int destWidth, int destHeight, int destPitch, unsigned char* src, int srcWidth, int srcHeight, int srcPitch);
void _drawScaledBuf(unsigned char* dest, int destWidth, int destHeight, unsigned char* src, int srcWidth, int srcHeight);
void _alphaBltBuf(unsigned char* src, int srcWidth, int srcHeight, int srcPitch, unsigned char* alphaWindowBuffer, unsigned char* alphaBuffer, unsigned char* dest, int destPitch);
void _fillBuf3x3(unsigned char* src, int srcWidth, int srcHeight, unsigned char* dest, int destWidth, int destHeight);
#endif /* WINDOW_H */

View File

@ -24,20 +24,16 @@
static void windowFree(int win);
static void _win_buffering(bool a1);
static void _win_move(int win_index, int x, int y);
static void _GNW_win_refresh(Window* window, Rect* rect, unsigned char* a3);
static void _win_clip(Window* window, RectListNode** rect, unsigned char* a3);
static void _win_drag(int win);
static void _refresh_all(Rect* rect, unsigned char* a2);
static Button* buttonGetButton(int btn, Window** out_win);
static void _win_text(int win, char** fileNameList, int fileNameListLength, int maxWidth, int x, int y, int flags);
static int paletteOpenFileImpl(const char* path, int flags);
static int paletteReadFileImpl(int fd, void* buf, size_t count);
static int paletteCloseFileImpl(int fd);
static int _win_register_button_image(int btn, unsigned char* up, unsigned char* down, unsigned char* hover, int a5);
static Button* buttonCreateInternal(int win, int x, int y, int width, int height, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, int flags, unsigned char* up, unsigned char* dn, unsigned char* hover);
static int _GNW_check_buttons(Window* window, int* out_a2);
static bool _button_under_mouse(Button* button, Rect* rect);
static int _win_last_button_winID();
static void buttonFree(Button* ptr);
static int _win_group_check_buttons(int a1, int* a2, int a3, void (*a4)(int));
static int _button_check_group(Button* button);
@ -59,7 +55,7 @@ static HANDLE _GNW95_title_mutex = INVALID_HANDLE_VALUE;
bool gWindowSystemInitialized = false;
// 0x51E3E4
static int _GNW_wcolor[6] = {
int _GNW_wcolor[6] = {
0,
0,
0,
@ -244,7 +240,7 @@ int windowManagerInit(VideoSystemInitProc* videoSystemInitProc, VideoSystemExitP
window->buttonListHead = NULL;
window->field_34 = NULL;
window->field_38 = 0;
window->field_3C = 0;
window->menuBar = NULL;
gWindowsLength = 1;
gWindowSystemInitialized = 1;
@ -363,14 +359,14 @@ int windowCreate(int x, int y, int width, int height, int a4, int flags)
a4 = _colorTable[_GNW_wcolor[0]];
}
} else if ((a4 & 0xFF00) != 0) {
int v1 = (a4 & 0xFF00) >> 8;
a4 = (a4 & ~0xFFFF) | _colorTable[_GNW_wcolor[v1]];
int colorIndex = (a4 & 0xFF) - 1;
a4 = (a4 & ~0xFFFF) | _colorTable[_GNW_wcolor[colorIndex]];
}
window->buttonListHead = 0;
window->field_34 = 0;
window->field_38 = 0;
window->field_3C = 0;
window->menuBar = NULL;
window->blitProc = blitBufferToBufferTrans;
window->field_20 = a4;
gOrderedWindowIds[index] = gWindowsLength;
@ -454,8 +450,8 @@ void windowFree(int win)
internal_free(window->buffer);
}
if (window->field_3C != NULL) {
internal_free(window->field_3C);
if (window->menuBar != NULL) {
internal_free(window->menuBar);
}
Button* curr = window->buttonListHead;
@ -500,7 +496,7 @@ void windowDrawBorder(int win)
}
// 0x4D684C
void windowDrawText(int win, char* str, int a3, int x, int y, int a6)
void windowDrawText(int win, const char* str, int a3, int x, int y, int a6)
{
int v7;
int v14;
@ -1021,7 +1017,7 @@ void _win_drag(int win)
tickersExecute();
if (_vcr_update() != 3) {
if (vcrUpdate() != 3) {
_mouse_info();
}
@ -1209,10 +1205,10 @@ int _GNW_check_menu_bars(int a1)
int v1 = a1;
for (int index = gWindowsLength - 1; index >= 1; index--) {
Window* window = gWindows[index];
if (window->field_3C != NULL) {
for (int v2 = 0; v2 < window->field_3C->entriesCount; v2++) {
if (v1 == window->field_3C->entries[v2].field_10) {
v1 = _GNW_process_menu(window->field_3C, v2);
if (window->menuBar != NULL) {
for (int pulldownIndex = 0; pulldownIndex < window->menuBar->pulldownsLength; pulldownIndex++) {
if (v1 == window->menuBar->pulldowns[pulldownIndex].keyCode) {
v1 = _GNW_process_menu(window->menuBar, pulldownIndex);
break;
}
}
@ -1242,7 +1238,7 @@ void _win_text(int win, char** fileNameList, int fileNameListLength, int maxWidt
int width = window->width;
unsigned char* ptr = window->buffer + y * width + x;
int lineHeight = fontGetLineHeight();
int step = width * lineHeight;
int v1 = lineHeight / 2;
int v2 = v1 + 1;
@ -1376,6 +1372,103 @@ int buttonCreate(int win, int x, int y, int width, int height, int mouseEnterEve
return button->id;
}
// 0x4D8308
int _win_register_text_button(int win, int x, int y, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, const char* title, int flags)
{
Window* window = windowGetWindow(win);
if (!gWindowSystemInitialized) {
return -1;
}
if (window == NULL) {
return -1;
}
int buttonWidth = fontGetStringWidth(title) + 16;
int buttonHeight = fontGetLineHeight() + 7;
unsigned char* normal = (unsigned char*)internal_malloc(buttonWidth * buttonHeight);
if (normal == NULL) {
return -1;
}
unsigned char* pressed = (unsigned char*)internal_malloc(buttonWidth * buttonHeight);
if (pressed == NULL) {
internal_free(normal);
return -1;
}
if (window->field_20 == 256 && _GNW_texture != NULL) {
// TODO: Incomplete.
} else {
bufferFill(normal, buttonWidth, buttonHeight, buttonWidth, window->field_20);
bufferFill(pressed, buttonWidth, buttonHeight, buttonWidth, window->field_20);
}
_lighten_buf(normal, buttonWidth, buttonHeight, buttonWidth);
fontDrawText(normal + buttonWidth * 3 + 8, title, buttonWidth, buttonWidth, _colorTable[_GNW_wcolor[3]]);
bufferDrawRectShadowed(normal,
buttonWidth,
2,
2,
buttonWidth - 3,
buttonHeight - 3,
_colorTable[_GNW_wcolor[1]],
_colorTable[_GNW_wcolor[2]]);
bufferDrawRectShadowed(normal,
buttonWidth,
1,
1,
buttonWidth - 2,
buttonHeight - 2,
_colorTable[_GNW_wcolor[1]],
_colorTable[_GNW_wcolor[2]]);
bufferDrawRect(normal, buttonWidth, 0, 0, buttonWidth - 1, buttonHeight - 1, _colorTable[0]);
fontDrawText(pressed + buttonWidth * 4 + 9, title, buttonWidth, buttonWidth, _colorTable[_GNW_wcolor[3]]);
bufferDrawRectShadowed(pressed,
buttonWidth,
2,
2,
buttonWidth - 3,
buttonHeight - 3,
_colorTable[_GNW_wcolor[2]],
_colorTable[_GNW_wcolor[1]]);
bufferDrawRectShadowed(pressed,
buttonWidth,
1,
1,
buttonWidth - 2,
buttonHeight - 2,
_colorTable[_GNW_wcolor[2]],
_colorTable[_GNW_wcolor[1]]);
bufferDrawRect(pressed, buttonWidth, 0, 0, buttonWidth - 1, buttonHeight - 1, _colorTable[0]);
Button* button = buttonCreateInternal(win,
x,
y,
buttonWidth,
buttonHeight,
mouseEnterEventCode,
mouseExitEventCode,
mouseDownEventCode,
mouseUpEventCode,
flags,
normal,
pressed,
NULL);
if (button == NULL) {
internal_free(normal);
internal_free(pressed);
return -1;
}
_button_draw(button, window, button->mouseUpImage, 0, NULL, 0);
return button->id;
}
// 0x4D8674
int _win_register_button_disable(int btn, unsigned char* up, unsigned char* down, unsigned char* hover)
{

View File

@ -61,26 +61,23 @@ typedef enum ButtonFlags {
BUTTON_FLAG_RIGHT_MOUSE_BUTTON_CONFIGURED = 0x080000,
} ButtonFlags;
typedef struct struc_176 {
int field_0;
int field_4;
int field_8;
int field_C;
int field_10;
int field_14;
int field_18;
typedef struct MenuPulldown {
Rect rect;
int keyCode;
int itemsLength;
char** items;
int field_1C;
int field_20;
} struc_176;
} MenuPulldown;
typedef struct struc_177 {
typedef struct MenuBar {
int win;
Rect rect;
int entriesCount;
struc_176 entries[15];
int field_234;
int field_238;
} struc_177;
int pulldownsLength;
MenuPulldown pulldowns[15];
int borderColor;
int backgroundColor;
} MenuBar;
typedef void WindowBlitProc(unsigned char* src, int width, int height, int srcPitch, unsigned char* dest, int destPitch);
@ -102,7 +99,7 @@ typedef struct Window {
Button* buttonListHead;
Button* field_34;
Button* field_38;
struc_177* field_3C;
MenuBar* menuBar;
WindowBlitProc* blitProc;
} Window;
@ -151,13 +148,15 @@ typedef int(VideoSystemInitProc)();
typedef void(VideoSystemExitProc)();
extern bool gWindowSystemInitialized;
extern int _GNW_wcolor[6];
int windowManagerInit(VideoSystemInitProc* videoSystemInitProc, VideoSystemExitProc* videoSystemExitProc, int a3);
void windowManagerExit(void);
int windowCreate(int x, int y, int width, int height, int a4, int flags);
void windowDestroy(int win);
void windowDrawBorder(int win);
void windowDrawText(int win, char* str, int a3, int x, int y, int a6);
void windowDrawText(int win, const char* str, int a3, int x, int y, int a6);
void _win_text(int win, char** fileNameList, int fileNameListLength, int maxWidth, int x, int y, int flags);
void windowDrawLine(int win, int left, int top, int right, int bottom, int color);
void windowDrawRect(int win, int left, int top, int right, int bottom, int color);
void windowFill(int win, int x, int y, int width, int height, int a6);
@ -165,6 +164,7 @@ void windowUnhide(int win);
void windowHide(int win);
void windowRefresh(int win);
void windowRefreshRect(int win, const Rect* rect);
void _GNW_win_refresh(Window* window, Rect* rect, unsigned char* a3);
void windowRefreshAll(Rect* rect);
void _win_get_mouse_buf(unsigned char* a1);
Window* windowGetWindow(int win);
@ -178,13 +178,16 @@ int _GNW_check_menu_bars(int a1);
void programWindowSetTitle(const char* title);
bool showMesageBox(const char* str);
int buttonCreate(int win, int x, int y, int width, int height, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, unsigned char* up, unsigned char* dn, unsigned char* hover, int flags);
int _win_register_text_button(int win, int x, int y, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, const char* title, int flags);
int _win_register_button_disable(int btn, unsigned char* up, unsigned char* down, unsigned char* hover);
int _win_register_button_image(int btn, unsigned char* up, unsigned char* down, unsigned char* hover, int a5);
int buttonSetMouseCallbacks(int btn, ButtonCallback* mouseEnterProc, ButtonCallback* mouseExitProc, ButtonCallback* mouseDownProc, ButtonCallback* mouseUpProc);
int buttonSetRightMouseCallbacks(int btn, int rightMouseDownEventCode, int rightMouseUpEventCode, ButtonCallback* rightMouseDownProc, ButtonCallback* rightMouseUpProc);
int buttonSetCallbacks(int btn, ButtonCallback* onPressed, ButtonCallback* onUnpressed);
int buttonSetMask(int btn, unsigned char* mask);
bool _win_button_down(int btn);
int buttonGetWindowId(int btn);
int _win_last_button_winID();
int buttonDestroy(int btn);
int buttonEnable(int btn);
int buttonDisable(int btn);

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,37 @@
#ifndef WINDOW_MANAGER_PRIVATE_H
#define WINDOW_MANAGER_PRIVATE_H
typedef struct struc_177 struc_177;
#include "geometry.h"
typedef struct MenuBar MenuBar;
typedef void(ListSelectionHandler)(char** items, int index);
extern char gProgramWindowTitle[256];
int _win_debug(char* a1);
int _GNW_process_menu(struc_177* ptr, int i);
int _win_list_select(const char* title, char** fileList, int fileListLength, ListSelectionHandler* callback, int x, int y, int a7);
int _win_list_select_at(const char* title, char** items, int itemsLength, ListSelectionHandler* callback, int x, int y, int a7, int a8);
int _win_get_str(char* dest, int length, const char* title, int x, int y);
int _win_msg(const char* string, int x, int y, int flags);
int _win_pull_down(char** items, int itemsLength, int x, int y, int a5);
int _create_pull_down(char** stringList, int stringListLength, int x, int y, int a5, int a6, Rect* rect);
int _win_debug(char* string);
void _win_debug_delete(int btn, int keyCode);
int _win_register_menu_bar(int win, int x, int y, int width, int height, int borderColor, int backgroundColor);
int _win_register_menu_pulldown(int win, int x, char* title, int keyCode, int itemsLength, char** items, int a7, int a8);
void _win_delete_menu_bar(int win);
int _find_first_letter(int ch, char** stringList, int stringListLength);
int _win_width_needed(char** fileNameList, int fileNameListLength);
int _win_input_str(int win, char* dest, int maxLength, int x, int y, int textColor, int backgroundColor);
int sub_4DBD04(int win, Rect* rect, char** items, int itemsLength, int a5, int a6, MenuBar* menuBar, int pulldownIndex);
int _GNW_process_menu(MenuBar* menuBar, int pulldownIndex);
int _calc_max_field_chars_wcursor(int a1, int a2);
void _GNW_intr_init();
void _GNW_intr_exit();
void _tm_watch_msgs();
void _tm_kill_msg();
void _tm_kill_out_of_order(int a1);
void _tm_click_response(int btn);
int _tm_index_active(int a1);
#endif /* WINDOW_MANAGER_PRIVATE_H */

View File

@ -102,7 +102,6 @@ typedef enum EncounterFormationType {
ENCOUNTER_FORMATION_TYPE_COUNT,
} EncounterFormationType;
typedef enum EncounterFrequencyType {
ENCOUNTER_FREQUENCY_TYPE_NONE,
ENCOUNTER_FREQUENCY_TYPE_RARE,
@ -1549,7 +1548,7 @@ int worldmapConfigInit()
// NOTE: Uninline.
worldmapTileInfoInit(tile);
tile->fid = buildFid(6, artIndex, 0, 0, 0);
tile->fid = buildFid(OBJ_TYPE_INTERFACE, artIndex, 0, 0, 0);
int encounterDifficulty;
if (configGetInt(&config, section, "encounter_difficulty", &encounterDifficulty)) {
@ -1876,7 +1875,7 @@ int _wmReadEncBaseType(char* name, int* valuePtr)
for (int index = 0; index < entry->field_34; index++) {
ENC_BASE_TYPE_38* ptr = &(entry->field_38[index]);
if ((ptr->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(ptr->pid) == OBJ_TYPE_CRITTER) {
ptr->team = team;
}
}
@ -2653,14 +2652,14 @@ int cityInit()
city->field_28 = area_idx;
if (num != -1) {
num = buildFid(6, num, 0, 0, 0);
num = buildFid(OBJ_TYPE_INTERFACE, num, 0, 0, 0);
}
city->mapFid = num;
if (configGetInt(&cfg, section, "townmap_label_art_idx", &num)) {
if (num != -1) {
num = buildFid(6, num, 0, 0, 0);
num = buildFid(OBJ_TYPE_INTERFACE, num, 0, 0, 0);
}
city->labelFid = num;
@ -4021,13 +4020,13 @@ int worldmapSetupCritters(int type_idx, Object** critterPtr, int critterCount)
}
if (*critterPtr == NULL) {
if ((v5->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(v5->pid) == OBJ_TYPE_CRITTER) {
*critterPtr = object;
}
}
if (v5->team != -1) {
if ((object->pid >> 24) == OBJ_TYPE_CRITTER) {
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
object->data.critter.combat.team = v5->team;
}
}
@ -4644,7 +4643,7 @@ int worldmapWindowInit()
int fid;
Art* frm;
CacheEntry* frmHandle;
_wmLastRndTime = _get_time();
_fontnum = fontGetCurrent();
fontSetCurrent(0);
@ -4666,7 +4665,7 @@ int worldmapWindowInit()
return -1;
}
fid = buildFid(6, 136, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 136, 0, 0, 0);
frm = artLock(fid, &gWorldmapBoxFrmHandle);
if (frm == NULL) {
return -1;
@ -4678,7 +4677,7 @@ int worldmapWindowInit()
artUnlock(gWorldmapBoxFrmHandle);
gWorldmapBoxFrmHandle = INVALID_CACHE_ENTRY;
fid = buildFid(6, 136, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 136, 0, 0, 0);
gWorldmapBoxFrmData = artLockFrameData(fid, 0, 0, &gWorldmapBoxFrmHandle);
if (gWorldmapBoxFrmData == NULL) {
return -1;
@ -4694,7 +4693,7 @@ int worldmapWindowInit()
for (int citySize = 0; citySize < CITY_SIZE_COUNT; citySize++) {
CitySizeDescription* citySizeDescription = &(gCitySizeDescriptions[citySize]);
fid = buildFid(6, 336 + citySize, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 336 + citySize, 0, 0, 0);
citySizeDescription->fid = fid;
frm = artLock(fid, &(citySizeDescription->handle));
@ -4715,7 +4714,7 @@ int worldmapWindowInit()
}
}
fid = buildFid(6, 168, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 168, 0, 0, 0);
frm = artLock(fid, &gWorldmapHotspotUpFrmHandle);
if (frm == NULL) {
return -1;
@ -4728,18 +4727,18 @@ int worldmapWindowInit()
gWorldmapHotspotUpFrmHandle = INVALID_CACHE_ENTRY;
// hotspot1.frm - town map selector shape #1
fid = buildFid(6, 168, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 168, 0, 0, 0);
gWorldmapHotspotUpFrmData = artLockFrameData(fid, 0, 0, &gWorldmapHotspotUpFrmHandle);
// hotspot2.frm - town map selector shape #2
fid = buildFid(6, 223, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 223, 0, 0, 0);
gWorldmapHotspotDownFrmData = artLockFrameData(fid, 0, 0, &gWorldmapHotspotDownFrmHandle);
if (gWorldmapHotspotDownFrmData == NULL) {
return -1;
}
// wmaptarg.frm - world map move target maker #1
fid = buildFid(6, 139, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 139, 0, 0, 0);
frm = artLock(fid, &gWorldmapDestinationMarkerFrmHandle);
if (frm == NULL) {
return -1;
@ -4752,7 +4751,7 @@ int worldmapWindowInit()
gWorldmapDestinationMarkerFrmHandle = INVALID_CACHE_ENTRY;
// wmaploc.frm - world map location marker
fid = buildFid(6, 138, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 138, 0, 0, 0);
frm = artLock(fid, &gWorldmapLocationMarkerFrmHandle);
if (frm == NULL) {
return -1;
@ -4765,21 +4764,21 @@ int worldmapWindowInit()
gWorldmapLocationMarkerFrmHandle = INVALID_CACHE_ENTRY;
// wmaptarg.frm - world map move target maker #1
fid = buildFid(6, 139, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 139, 0, 0, 0);
gWorldmapDestinationMarkerFrmData = artLockFrameData(fid, 0, 0, &gWorldmapDestinationMarkerFrmHandle);
if (gWorldmapDestinationMarkerFrmData == NULL) {
return -1;
}
// wmaploc.frm - world map location marker
fid = buildFid(6, 138, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 138, 0, 0, 0);
gWorldmapLocationMarkerFrmData = artLockFrameData(fid, 0, 0, &gWorldmapLocationMarkerFrmHandle);
if (gWorldmapLocationMarkerFrmData == NULL) {
return -1;
}
for (int index = 0; index < WORLD_MAP_ENCOUNTER_FRM_COUNT; index++) {
fid = buildFid(6, gWorldmapEncounterFrmIds[index], 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, gWorldmapEncounterFrmIds[index], 0, 0, 0);
frm = artLock(fid, &(gWorldmapEncounterFrmHandles[index]));
if (frm == NULL) {
return -1;
@ -4799,7 +4798,7 @@ int worldmapWindowInit()
}
// wmtabs.frm - worldmap town tabs underlay
fid = buildFid(6, 364, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 364, 0, 0, 0);
frm = artLock(fid, &frmHandle);
if (frm == NULL) {
return -1;
@ -4816,14 +4815,14 @@ int worldmapWindowInit()
}
// wmtbedge.frm - worldmap town tabs edging overlay
fid = buildFid(6, 367, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 367, 0, 0, 0);
gWorldmapTownTabsEdgeFrmData = artLockFrameData(fid, 0, 0, &gWorldmapTownTabsEdgeFrmHandle);
if (gWorldmapTownTabsEdgeFrmData == NULL) {
return -1;
}
// wmdial.frm - worldmap night/day dial
fid = buildFid(6, 365, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 365, 0, 0, 0);
gWorldmapDialFrm = artLock(fid, &gWorldmapDialFrmHandle);
if (gWorldmapDialFrm == NULL) {
return -1;
@ -4833,7 +4832,7 @@ int worldmapWindowInit()
gWorldmapDialFrmHeight = artGetHeight(gWorldmapDialFrm, 0, 0);
// wmscreen - worldmap overlay screen
fid = buildFid(6, 363, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 363, 0, 0, 0);
frm = artLock(fid, &frmHandle);
if (frm == NULL) {
return -1;
@ -4850,7 +4849,7 @@ int worldmapWindowInit()
}
// wmglobe.frm - worldmap globe stamp overlay
fid = buildFid(6, 366, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 366, 0, 0, 0);
frm = artLock(fid, &frmHandle);
if (frm == NULL) {
return -1;
@ -4867,7 +4866,7 @@ int worldmapWindowInit()
}
// lilredup.frm - little red button up
fid = buildFid(6, 8, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 8, 0, 0, 0);
frm = artLock(fid, &frmHandle);
if (frm == NULL) {
return -1;
@ -4881,18 +4880,18 @@ int worldmapWindowInit()
gWorldmapLittleRedButtonUpFrmData = artLockFrameData(fid, 0, 0, &gWorldmapLittleRedButtonUpFrmHandle);
// lilreddn.frm - little red button down
fid = buildFid(6, 9, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 9, 0, 0, 0);
gWorldmapLittleRedButtonDownFrmData = artLockFrameData(fid, 0, 0, &gWorldmapLittleRedButtonDownFrmHandle);
// months.frm - month strings for pip boy
fid = buildFid(6, 129, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 129, 0, 0, 0);
gWorldmapMonthsFrm = artLock(fid, &gWorldmapMonthsFrmHandle);
if (gWorldmapMonthsFrm == NULL) {
return -1;
}
// numbers.frm - numbers for the hit points and fatigue counters
fid = buildFid(6, 82, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 82, 0, 0, 0);
gWorldmapNumbersFrm = artLock(fid, &gWorldmapNumbersFrmHandle);
if (gWorldmapNumbersFrm == NULL) {
return -1;
@ -4902,37 +4901,37 @@ int worldmapWindowInit()
buttonCreate(gWorldmapWindow,
WM_TOWN_WORLD_SWITCH_X,
WM_TOWN_WORLD_SWITCH_Y,
littleRedButtonUpWidth,
littleRedButtonUpHeight,
-1,
-1,
littleRedButtonUpWidth,
littleRedButtonUpHeight,
-1,
-1,
-1,
KEY_UPPERCASE_T,
gWorldmapLittleRedButtonUpFrmData,
gWorldmapLittleRedButtonDownFrmData,
NULL,
NULL,
BUTTON_FLAG_TRANSPARENT);
for (int index = 0; index < 7; index++) {
_wmTownMapSubButtonIds[index] = buttonCreate(gWorldmapWindow,
508,
508,
138 + 27 * index,
littleRedButtonUpWidth,
littleRedButtonUpHeight,
-1,
littleRedButtonUpWidth,
littleRedButtonUpHeight,
-1,
-1,
KEY_CTRL_F1 + index,
gWorldmapLittleRedButtonUpFrmData,
gWorldmapLittleRedButtonDownFrmData,
NULL,
-1,
-1,
KEY_CTRL_F1 + index,
gWorldmapLittleRedButtonUpFrmData,
gWorldmapLittleRedButtonDownFrmData,
NULL,
BUTTON_FLAG_TRANSPARENT);
}
for (int index = 0; index < WORLDMAP_ARROW_FRM_COUNT; index++) {
// 200 - uparwon.frm - character editor
// 199 - uparwoff.frm - character editor
fid = buildFid(6, 200 - index, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 200 - index, 0, 0, 0);
frm = artLock(fid, &(gWorldmapTownListScrollUpFrmHandle[index]));
if (frm == NULL) {
return -1;
@ -4946,7 +4945,7 @@ int worldmapWindowInit()
for (int index = 0; index < WORLDMAP_ARROW_FRM_COUNT; index++) {
// 182 - dnarwon.frm - character editor
// 181 - dnarwoff.frm - character editor
fid = buildFid(6, 182 - index, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 182 - index, 0, 0, 0);
frm = artLock(fid, &(gWorldmapTownListScrollDownFrmHandle[index]));
if (frm == NULL) {
return -1;
@ -4961,35 +4960,35 @@ int worldmapWindowInit()
buttonCreate(gWorldmapWindow,
WM_TOWN_LIST_SCROLL_UP_X,
WM_TOWN_LIST_SCROLL_UP_Y,
gWorldmapTownListScrollUpFrmWidth,
gWorldmapTownListScrollUpFrmHeight,
-1,
-1,
gWorldmapTownListScrollUpFrmWidth,
gWorldmapTownListScrollUpFrmHeight,
-1,
-1,
-1,
KEY_CTRL_ARROW_UP,
gWorldmapTownListScrollUpFrmData[WORLDMAP_ARROW_FRM_NORMAL],
gWorldmapTownListScrollUpFrmData[WORLDMAP_ARROW_FRM_NORMAL],
gWorldmapTownListScrollUpFrmData[WORLDMAP_ARROW_FRM_PRESSED],
NULL,
BUTTON_FLAG_TRANSPARENT);
// Scroll down button.
buttonCreate(gWorldmapWindow,
WM_TOWN_LIST_SCROLL_DOWN_X,
WM_TOWN_LIST_SCROLL_DOWN_Y,
gWorldmapTownListScrollDownFrmWidth,
buttonCreate(gWorldmapWindow,
WM_TOWN_LIST_SCROLL_DOWN_X,
WM_TOWN_LIST_SCROLL_DOWN_Y,
gWorldmapTownListScrollDownFrmWidth,
gWorldmapTownListScrollDownFrmHeight,
-1,
-1,
-1,
-1,
KEY_CTRL_ARROW_DOWN,
gWorldmapTownListScrollDownFrmData[WORLDMAP_ARROW_FRM_NORMAL],
gWorldmapTownListScrollDownFrmData[WORLDMAP_ARROW_FRM_NORMAL],
gWorldmapTownListScrollDownFrmData[WORLDMAP_ARROW_FRM_PRESSED],
NULL,
NULL,
BUTTON_FLAG_TRANSPARENT);
if (gWorldmapIsInCar) {
// wmcarmve.frm - worldmap car movie
fid = buildFid(6, 433, 0, 0, 0);
fid = buildFid(OBJ_TYPE_INTERFACE, 433, 0, 0, 0);
gWorldmapCarFrm = artLock(fid, &gWorldmapCarFrmHandle);
if (gWorldmapCarFrm == NULL) {
return -1;