Reconcile with reference edition

This commit is contained in:
Alexander Batalov 2022-09-01 18:41:37 +03:00
parent 039ad65557
commit 629978d7a6
33 changed files with 1641 additions and 856 deletions

View File

@ -81,6 +81,7 @@ static int _action_melee(Attack* attack, int a2);
static int _action_ranged(Attack* attack, int a2);
static int _is_next_to(Object* a1, Object* a2);
static int _action_climb_ladder(Object* a1, Object* a2);
static int _action_use_skill_in_combat_error(Object* critter);
static int _pick_fall(Object* obj, int anim);
static int _report_explosion(Attack* attack, Object* a2);
static int _finished_explosion(Object* a1, Object* a2);
@ -1289,23 +1290,33 @@ int _action_skill_use(int skill)
return -1;
}
// NOTE: Inlined.
//
// 0x412500
static int _action_use_skill_in_combat_error(Object* critter)
{
MessageListItem messageListItem;
if (critter == gDude) {
messageListItem.num = 902;
if (messageListGetItem(&gProtoMessageList, &messageListItem) == 1) {
displayMonitorAddMessage(messageListItem.text);
}
}
return -1;
}
// skill_use
// 0x41255C
int actionUseSkill(Object* a1, Object* a2, int skill)
{
MessageListItem messageListItem;
switch (skill) {
case SKILL_FIRST_AID:
case SKILL_DOCTOR:
if (isInCombat()) {
if (a1 == gDude) {
messageListItem.num = 902;
if (messageListGetItem(&gProtoMessageList, &messageListItem)) {
displayMonitorAddMessage(messageListItem.text);
}
}
return -1;
// NOTE: Uninline.
return _action_use_skill_in_combat_error(a1);
}
if (PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) {
@ -1314,13 +1325,8 @@ int actionUseSkill(Object* a1, Object* a2, int skill)
break;
case SKILL_LOCKPICK:
if (isInCombat()) {
if (a1 == gDude) {
messageListItem.num = 902;
if (messageListGetItem(&gProtoMessageList, &messageListItem)) {
displayMonitorAddMessage(messageListItem.text);
}
}
return -1;
// NOTE: Uninline.
return _action_use_skill_in_combat_error(a1);
}
if (PID_TYPE(a2->pid) != OBJ_TYPE_ITEM && PID_TYPE(a2->pid) != OBJ_TYPE_SCENERY) {
@ -1330,13 +1336,8 @@ int actionUseSkill(Object* a1, Object* a2, int skill)
break;
case SKILL_STEAL:
if (isInCombat()) {
if (a1 == gDude) {
messageListItem.num = 902;
if (messageListGetItem(&gProtoMessageList, &messageListItem)) {
displayMonitorAddMessage(messageListItem.text);
}
}
return -1;
// NOTE: Uninline.
return _action_use_skill_in_combat_error(a1);
}
if (PID_TYPE(a2->pid) != OBJ_TYPE_ITEM && PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) {
@ -1350,13 +1351,8 @@ int actionUseSkill(Object* a1, Object* a2, int skill)
break;
case SKILL_TRAPS:
if (isInCombat()) {
if (a1 == gDude) {
messageListItem.num = 902;
if (messageListGetItem(&gProtoMessageList, &messageListItem)) {
displayMonitorAddMessage(messageListItem.text);
}
}
return -1;
// NOTE: Uninline.
return _action_use_skill_in_combat_error(a1);
}
if (PID_TYPE(a2->pid) == OBJ_TYPE_CRITTER) {
@ -1367,13 +1363,8 @@ int actionUseSkill(Object* a1, Object* a2, int skill)
case SKILL_SCIENCE:
case SKILL_REPAIR:
if (isInCombat()) {
if (a1 == gDude) {
messageListItem.num = 902;
if (messageListGetItem(&gProtoMessageList, &messageListItem)) {
displayMonitorAddMessage(messageListItem.text);
}
}
return -1;
// NOTE: Uninline.
return _action_use_skill_in_combat_error(a1);
}
if (PID_TYPE(a2->pid) != OBJ_TYPE_CRITTER) {

View File

@ -57,8 +57,8 @@ typedef enum AnimationKind {
ANIM_KIND_SET_FID = 17,
ANIM_KIND_TAKE_OUT_WEAPON = 18,
ANIM_KIND_SET_LIGHT_DISTANCE = 19,
ANIM_KIND_20 = 20,
ANIM_KIND_23 = 23,
ANIM_KIND_MOVE_ON_STAIRS = 20,
ANIM_KIND_CHECK_FALLING = 23,
ANIM_KIND_TOGGLE_OUTLINE = 24,
ANIM_KIND_ANIMATE_FOREVER = 25,
ANIM_KIND_26 = 26,
@ -254,6 +254,7 @@ typedef struct AnimationSad {
} AnimationSad;
static int _anim_free_slot(int a1);
static int _anim_preload(Object* object, int fid, CacheEntry** cacheEntryPtr);
static void _anim_cleanup();
static int _check_registry(Object* obj);
static int animationRunSequence(int a1);
@ -273,6 +274,7 @@ static void _object_straight_move(int index);
static int _anim_animate(Object* obj, int anim, int animationSequenceIndex, int flags);
static void _object_anim_compact();
static int actionRotate(Object* obj, int delta, int animationSequenceIndex);
static int _anim_hide(Object* object, int animationSequenceIndex);
static int _anim_change_fid(Object* obj, int animationSequenceIndex, int fid);
static int _check_gravity(int tile, int elevation);
static unsigned int animationComputeTicksPerFrame(Object* object, int fid);
@ -501,6 +503,22 @@ int reg_anim_end()
return 0;
}
// NOTE: Inlined.
//
// 0x413D6C
static int _anim_preload(Object* object, int fid, CacheEntry** cacheEntryPtr)
{
*cacheEntryPtr = NULL;
if (artLock(fid, cacheEntryPtr) != NULL) {
artUnlock(*cacheEntryPtr);
*cacheEntryPtr = NULL;
return 0;
}
return -1;
}
// 0x413D98
static void _anim_cleanup()
{
@ -618,14 +636,12 @@ int animationRegisterMoveToObject(Object* owner, Object* destination, int action
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return animationRegisterRotateToTile(owner, destination->tile);
@ -680,15 +696,12 @@ int animationRegisterRunToObject(Object* owner, Object* destination, int actionP
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
animationDescription->artCacheKey = NULL;
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return animationRegisterRotateToTile(owner, destination->tile);
}
@ -713,17 +726,15 @@ int animationRegisterMoveToTile(Object* owner, int tile, int elevation, int acti
animationDescription->elevation = elevation;
animationDescription->actionPoints = actionPoints;
animationDescription->delay = delay;
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -781,15 +792,12 @@ int animationRegisterRunToTile(Object* owner, int tile, int elevation, int actio
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
animationDescription->artCacheKey = NULL;
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -816,17 +824,15 @@ int animationRegisterMoveToTileStraight(Object* object, int tile, int elevation,
animationDescription->elevation = elevation;
animationDescription->anim = anim;
animationDescription->delay = delay;
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(object->fid), object->fid & 0xFFF, animationDescription->anim, (object->fid & 0xF000) >> 12, object->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(object, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -852,17 +858,15 @@ int animationRegisterMoveToTileStraightAndWaitForComplete(Object* owner, int til
animationDescription->elevation = elevation;
animationDescription->anim = anim;
animationDescription->delay = delay;
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -882,17 +886,15 @@ int animationRegisterAnimate(Object* owner, int anim, int delay)
animationDescription->owner = owner;
animationDescription->anim = anim;
animationDescription->delay = delay;
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -915,14 +917,13 @@ int animationRegisterAnimateReversed(Object* owner, int anim, int delay)
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, animationDescription->anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -945,14 +946,13 @@ int animationRegisterAnimateAndHide(Object* owner, int anim, int delay)
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -1199,16 +1199,13 @@ int animationRegisterSetFid(Object* owner, int fid, int delay)
animationDescription->owner = owner;
animationDescription->fid = fid;
animationDescription->delay = delay;
animationDescription->artCacheKey = NULL;
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -1236,14 +1233,13 @@ int animationRegisterTakeOutWeapon(Object* owner, int weaponAnimationCode, int d
animationDescription->weaponAnimationCode = weaponAnimationCode;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, ANIM_TAKE_OUT, weaponAnimationCode, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -1339,17 +1335,15 @@ int animationRegisterAnimateForever(Object* owner, int anim, int delay)
animationDescription->owner = owner;
animationDescription->anim = anim;
animationDescription->delay = delay;
animationDescription->artCacheKey = NULL;
int fid = buildFid(FID_TYPE(owner->fid), owner->fid & 0xFFF, anim, (owner->fid & 0xF000) >> 12, owner->rotation + 1);
if (artLock(fid, &(animationDescription->artCacheKey)) == NULL) {
// NOTE: Uninline.
if (_anim_preload(owner, fid, &(animationDescription->artCacheKey)) == -1) {
_anim_cleanup();
return -1;
}
artUnlock(animationDescription->artCacheKey);
animationDescription->artCacheKey = NULL;
gAnimationDescriptionCurrentIndex++;
return 0;
@ -1438,15 +1432,8 @@ static int animationRunSequence(int animationSequenceIndex)
case ANIM_KIND_ANIMATE_AND_HIDE:
rc = _anim_animate(animationDescription->owner, animationDescription->anim, animationSequenceIndex, ANIM_SAD_HIDE_ON_END);
if (rc == -1) {
Rect rect;
if (objectHide(animationDescription->owner, &rect) == 0) {
tileWindowRefreshRect(&rect, animationDescription->elevation);
}
if (animationSequenceIndex != -1) {
_anim_set_continue(animationSequenceIndex, 0);
}
rc = 0;
// NOTE: Uninline.
rc = _anim_hide(animationDescription->owner, animationSequenceIndex);
}
break;
case ANIM_KIND_ANIMATE_FOREVER:
@ -1467,13 +1454,8 @@ static int animationRunSequence(int animationSequenceIndex)
rc = actionRotate(animationDescription->owner, -1, animationSequenceIndex);
break;
case ANIM_KIND_HIDE:
if (objectHide(animationDescription->owner, &rect) == 0) {
tileWindowRefreshRect(&rect, animationDescription->owner->elevation);
}
if (animationSequenceIndex != -1) {
_anim_set_continue(animationSequenceIndex, 0);
}
rc = 0;
// NOTE: Uninline.
rc = _anim_hide(animationDescription->owner, animationSequenceIndex);
break;
case ANIM_KIND_CALLBACK:
rc = animationDescription->callback(animationDescription->param1, animationDescription->param2);
@ -1539,10 +1521,10 @@ static int animationRunSequence(int animationSequenceIndex)
tileWindowRefreshRect(&rect, animationDescription->owner->elevation);
rc = _anim_set_continue(animationSequenceIndex, 0);
break;
case ANIM_KIND_20:
case ANIM_KIND_MOVE_ON_STAIRS:
rc = _anim_move_on_stairs(animationDescription->owner, animationDescription->tile, animationDescription->elevation, animationDescription->anim, animationSequenceIndex);
break;
case ANIM_KIND_23:
case ANIM_KIND_CHECK_FALLING:
rc = _check_for_falling(animationDescription->owner, animationDescription->anim, animationSequenceIndex);
break;
case ANIM_KIND_TOGGLE_OUTLINE:
@ -2849,9 +2831,8 @@ void _object_animate()
artUnlock(cacheHandle);
if ((sad->flags & ANIM_SAD_HIDE_ON_END) != 0) {
if (objectHide(object, &tempRect) == 0) {
tileWindowRefreshRect(&tempRect, object->elevation);
}
// NOTE: Uninline.
_anim_hide(object, -1);
}
_anim_set_continue(sad->animationSequenceIndex, 1);
@ -3262,6 +3243,24 @@ static int actionRotate(Object* obj, int delta, int animationSequenceIndex)
return 0;
}
// NOTE: Inlined.
//
// 0x41862C
static int _anim_hide(Object* object, int animationSequenceIndex)
{
Rect rect;
if (objectHide(object, &rect) == 0) {
tileWindowRefreshRect(&rect, object->elevation);
}
if (animationSequenceIndex != -1) {
_anim_set_continue(animationSequenceIndex, 0);
}
return 0;
}
// 0x418660
static int _anim_change_fid(Object* obj, int animationSequenceIndex, int fid)
{

View File

@ -2917,7 +2917,7 @@ static void characterEditorDrawSkills(int a1)
int color;
int y;
int value;
char valueString[12]; // TODO: Size might be wrong.
char valueString[32];
if (characterEditorSelectedItem >= EDITOR_FIRST_SKILL && characterEditorSelectedItem < 79) {
selectedSkill = characterEditorSelectedItem - EDITOR_FIRST_SKILL;
@ -2950,7 +2950,6 @@ static void characterEditorDrawSkills(int a1)
str = getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 138);
fontDrawText(gCharacterEditorWindowBuffer + 640 * 233 + 422, str, 640, 640, _colorTable[18979]);
// TODO: Check.
if (a1 == 2 && !gCharacterEditorIsSkillsFirstDraw) {
characterEditorDrawBigNumber(522, 228, ANIMATE, gCharacterEditorTaggedSkillCount, gCharacterEditorOldTaggedSkillCount, gCharacterEditorWindow);
} else {
@ -2985,7 +2984,6 @@ static void characterEditorDrawSkills(int a1)
value = skillGetValue(gDude, i);
sprintf(valueString, "%d%%", value);
// TODO: Check text position.
fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 573, valueString, 640, 640, color);
y += fontGetLineHeight() + 1;

View File

@ -86,9 +86,12 @@ typedef struct DamageCalculationContext {
} DamageCalculationContext;
static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapon, int hitMode, Object* a4, int* a5, Object* a6);
static void _combatInitAIInfoList();
static int aiInfoCopy(int srcIndex, int destIndex);
static int _combatAIInfoSetLastMove(Object* object, int move);
static void _combat_begin(Object* a1);
static void _combat_begin_extra(Object* a1);
static void _combat_update_critters_in_los(bool a1);
static void _combat_over();
static void _combat_add_noncoms();
static int _compare_faster(const void* a1, const void* a2);
@ -107,6 +110,7 @@ static int attackCompute(Attack* attack);
static int attackComputeCriticalHit(Attack* a1);
static int _attackFindInvalidFlags(Object* a1, Object* a2);
static int attackComputeCriticalFailure(Attack* attack);
static void _do_random_cripple(int* flagsPtr);
static int attackDetermineToHit(Object* attacker, int tile, Object* defender, int hitLocation, int hitMode, bool a6);
static void attackComputeDamage(Attack* attack, int ammoQuantity, int a3);
static void _check_for_death(Object* a1, int a2, int* a3);
@ -2375,6 +2379,21 @@ void _combat_data_init(Object* obj)
obj->data.critter.combat.results = 0;
}
// NOTE: Inlined.
//
// 0x4217FC
static void _combatInitAIInfoList()
{
int index;
for (index = 0; index < _list_total; index++) {
_aiInfoList[index].friendlyDead = NULL;
_aiInfoList[index].lastTarget = NULL;
_aiInfoList[index].lastItem = NULL;
_aiInfoList[index].lastMove = 0;
}
}
// 0x421850
static int aiInfoCopy(int srcIndex, int destIndex)
{
@ -2521,6 +2540,28 @@ int aiInfoSetLastItem(Object* obj, Object* a2)
return 0;
}
// NOTE: Inlined.
//
// 0x421A00
static int _combatAIInfoSetLastMove(Object* object, int move)
{
if (!isInCombat()) {
return 0;
}
if (object == NULL) {
return -1;
}
if (object->cid == -1) {
return -1;
}
_aiInfoList[object->cid].lastMove = move;
return 0;
}
// 0x421A34
static void _combat_begin(Object* a1)
{
@ -2541,13 +2582,8 @@ static void _combat_begin(Object* a1)
return;
}
for (int index = 0; index < _list_total; index++) {
CombatAiInfo* aiInfo = &(_aiInfoList[index]);
aiInfo->friendlyDead = NULL;
aiInfo->lastTarget = NULL;
aiInfo->lastItem = NULL;
aiInfo->lastMove = 0;
}
// NOTE: Uninline.
_combatInitAIInfoList();
Object* v1 = NULL;
for (int index = 0; index < _list_total; index++) {
@ -2559,10 +2595,8 @@ static void _combat_begin(Object* a1)
combatData->ap = 0;
critter->cid = index;
// NOTE: Not sure about this code, field_C is already reset.
if (isInCombat() && critter != NULL && index != -1) {
_aiInfoList[index].lastMove = 0;
}
// NOTE: Uninline.
_combatAIInfoSetLastMove(critter, 0);
scriptSetObjects(critter->sid, NULL, NULL);
scriptSetFixedParam(critter->sid, 0);
@ -2621,6 +2655,18 @@ static void _combat_begin_extra(Object* a1)
configGetInt(&gGameConfig, GAME_CONFIG_PREFERENCES_KEY, GAME_CONFIG_TARGET_HIGHLIGHT_KEY, &_combat_highlight);
}
// NOTE: Inlined.
//
// 0x421D18
static void _combat_update_critters_in_los(bool a1)
{
int index;
for (index = 0; index < _list_total; index++) {
_combat_update_critter_outline_for_los(_combat_list[index], a1);
}
}
// Something with outlining.
//
// 0x421D50
@ -3149,11 +3195,8 @@ static void _combat_set_move_all()
object->data.critter.combat.ap = actionPoints;
if (isInCombat()) {
if (object->cid != -1) {
_aiInfoList[object->cid].lastMove = 0;
}
}
// NOTE: Uninline.
_combatAIInfoSetLastMove(object, 0);
}
}
@ -3211,9 +3254,8 @@ static int _combat_turn(Object* a1, bool a2)
interfaceBarEndButtonsRenderGreenLights();
for (int index = 0; index < _list_total; index++) {
_combat_update_critter_outline_for_los(_combat_list[index], false);
}
// NOTE: Uninline.
_combat_update_critters_in_los(false);
if (_combat_highlight != 0) {
_combat_outline_on();
@ -4075,22 +4117,8 @@ static int attackComputeCriticalHit(Attack* attack)
}
if ((attack->defenderFlags & DAM_CRIP_RANDOM) != 0) {
attack->defenderFlags &= ~DAM_CRIP_RANDOM;
switch (randomBetween(0, 3)) {
case 0:
attack->defenderFlags |= DAM_CRIP_LEG_LEFT;
break;
case 1:
attack->defenderFlags |= DAM_CRIP_LEG_RIGHT;
break;
case 2:
attack->defenderFlags |= DAM_CRIP_ARM_LEFT;
break;
case 3:
attack->defenderFlags |= DAM_CRIP_ARM_RIGHT;
break;
}
// NOTE: Uninline.
_do_random_cripple(&(attack->defenderFlags));
}
if (weaponGetPerk(attack->weapon) == PERK_WEAPON_ENHANCED_KNOCKOUT) {
@ -4195,22 +4223,8 @@ static int attackComputeCriticalFailure(Attack* attack)
}
if ((attack->attackerFlags & DAM_CRIP_RANDOM) != 0) {
attack->attackerFlags &= ~DAM_CRIP_RANDOM;
switch (randomBetween(0, 3)) {
case 0:
attack->attackerFlags |= DAM_CRIP_LEG_LEFT;
break;
case 1:
attack->attackerFlags |= DAM_CRIP_LEG_RIGHT;
break;
case 2:
attack->attackerFlags |= DAM_CRIP_ARM_LEFT;
break;
case 3:
attack->attackerFlags |= DAM_CRIP_ARM_RIGHT;
break;
}
// NOTE: Uninline.
_do_random_cripple(&(attack->attackerFlags));
}
if ((attack->attackerFlags & DAM_RANDOM_HIT) != 0) {
@ -4234,6 +4248,27 @@ static int attackComputeCriticalFailure(Attack* attack)
return 0;
}
// 0x42432C
static void _do_random_cripple(int* flagsPtr)
{
*flagsPtr &= ~DAM_CRIP_RANDOM;
switch (randomBetween(0, 3)) {
case 0:
*flagsPtr |= DAM_CRIP_LEG_LEFT;
break;
case 1:
*flagsPtr |= DAM_CRIP_LEG_RIGHT;
break;
case 2:
*flagsPtr |= DAM_CRIP_ARM_LEFT;
break;
case 3:
*flagsPtr |= DAM_CRIP_ARM_RIGHT;
break;
}
}
// 0x42436C
int _determine_to_hit(Object* a1, Object* a2, int hitLocation, int hitMode)
{
@ -5781,9 +5816,8 @@ void _combat_outline_on()
}
}
for (int index = 0; index < _list_total; index++) {
_combat_update_critter_outline_for_los(_combat_list[index], 1);
}
// NOTE: Uninline.
_combat_update_critters_in_los(true);
tileWindowRefresh();
}

View File

@ -99,8 +99,11 @@ static void _ai_run_away(Object* a1, Object* a2);
static int _ai_move_away(Object* a1, Object* a2, int a3);
static bool _ai_find_friend(Object* a1, int a2, int a3);
static int _compare_nearer(const void* a1, const void* a2);
static void _ai_sort_list_distance(Object** critterList, int length, Object* origin);
static int _compare_strength(const void* p1, const void* p2);
static void _ai_sort_list_strength(Object** critterList, int length);
static int _compare_weakness(const void* p1, const void* p2);
static void _ai_sort_list_weakness(Object** critterList, int length);
static Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3);
static Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3);
static int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4);
@ -114,6 +117,7 @@ static Object* _ai_search_environ(Object* critter, int itemType);
static Object* _ai_retrieve_object(Object* a1, Object* a2);
static int _ai_pick_hit_mode(Object* a1, Object* a2, Object* a3);
static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4);
static int _ai_move_closer(Object* a1, Object* a2, int a3);
static int _cai_retargetTileFromFriendlyFire(Object* source, Object* target, int* tilePtr);
static int _cai_retargetTileFromFriendlyFireSubFunc(AiRetargetData* aiRetargetData, int tile);
static bool _cai_attackWouldIntersect(Object* a1, Object* a2, Object* a3, int tile, int* distance);
@ -1236,6 +1240,15 @@ static int _compare_nearer(const void* a1, const void* a2)
}
}
// NOTE: Inlined.
//
// 0x428B74
static void _ai_sort_list_distance(Object** critterList, int length, Object* origin)
{
_combat_obj = origin;
qsort(critterList, length, sizeof(*critterList), _compare_nearer);
}
// qsort compare function - melee then ranged.
//
// 0x428B8C
@ -1270,6 +1283,14 @@ static int _compare_strength(const void* p1, const void* p2)
return 0;
}
// NOTE: Inlined.
//
// 0x428BD0
static void _ai_sort_list_strength(Object** critterList, int length)
{
qsort(critterList, length, sizeof(*critterList), _compare_strength);
}
// qsort compare unction - ranged then melee
//
// 0x428BE4
@ -1304,6 +1325,14 @@ static int _compare_weakness(const void* p1, const void* p2)
return 0;
}
// NOTE: Inlined.
//
// 0x428C28
static void _ai_sort_list_weakness(Object** critterList, int length)
{
qsort(critterList, length, sizeof(*critterList), _compare_weakness);
}
// 0x428C3C
static Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3)
{
@ -1318,8 +1347,8 @@ static Object* _ai_find_nearest_team(Object* a1, Object* a2, int a3)
return NULL;
}
_combat_obj = a1;
qsort(_curr_crit_list, _curr_crit_num, sizeof(*_curr_crit_list), _compare_nearer);
// NOTE: Uninline.
_ai_sort_list_distance(_curr_crit_list, _curr_crit_num, a1);
for (i = 0; i < _curr_crit_num; i++) {
obj = _curr_crit_list[i];
@ -1344,8 +1373,8 @@ static Object* _ai_find_nearest_team_in_combat(Object* a1, Object* a2, int a3)
int team = a2->data.critter.combat.team;
_combat_obj = a1;
qsort(_curr_crit_list, _curr_crit_num, sizeof(*_curr_crit_list), _compare_nearer);
// NOTE: Uninline.
_ai_sort_list_distance(_curr_crit_list, _curr_crit_num, a1);
for (int index = 0; index < _curr_crit_num; index++) {
Object* obj = _curr_crit_list[index];
@ -1381,8 +1410,8 @@ static int _ai_find_attackers(Object* a1, Object** a2, Object** a3, Object** a4)
return 0;
}
_combat_obj = a1;
qsort(_curr_crit_list, _curr_crit_num, sizeof(*_curr_crit_list), _compare_nearer);
// NOTE: Uninline.
_ai_sort_list_distance(_curr_crit_list, _curr_crit_num, a1);
int foundTargetCount = 0;
int team = a1->data.critter.combat.team;
@ -1521,22 +1550,21 @@ static Object* _ai_danger_source(Object* a1)
}
}
int (*compareProc)(const void*, const void*);
switch (attackWho) {
case ATTACK_WHO_STRONGEST:
compareProc = _compare_strength;
// NOTE: Uninline.
_ai_sort_list_strength(targets, 4);
break;
case ATTACK_WHO_WEAKEST:
compareProc = _compare_weakness;
// NOTE: Uninline.
_ai_sort_list_weakness(targets, 4);
break;
default:
compareProc = _compare_nearer;
_combat_obj = a1;
// NOTE: Uninline.
_ai_sort_list_distance(targets, 4, a1);
break;
}
qsort(targets, 4, sizeof(*targets), compareProc);
for (int index = 0; index < 4; index++) {
Object* candidate = targets[index];
if (candidate != NULL && objectCanHearObject(a1, candidate)) {
@ -2022,8 +2050,8 @@ static Object* _ai_search_environ(Object* critter, int itemType)
return NULL;
}
_combat_obj = critter;
qsort(objects, count, sizeof(*objects), _compare_nearer);
// NOTE: Uninline.
_ai_sort_list_distance(objects, count, critter);
int perception = critterGetStat(critter, STAT_PERCEPTION) + 5;
Object* item2 = critterGetItem2(critter);
@ -2273,6 +2301,14 @@ static int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a
return 0;
}
// NOTE: Inlined.
//
// 0x42A1C0
static int _ai_move_closer(Object* a1, Object* a2, int a3)
{
return _ai_move_steps_closer(a1, a2, a1->data.critter.combat.ap, a3);
}
// 0x42A1D4
static int _cai_retargetTileFromFriendlyFire(Object* source, Object* target, int* tilePtr)
{
@ -2328,9 +2364,8 @@ static int _cai_retargetTileFromFriendlyFire(Object* source, Object* target, int
}
}
_combat_obj = source;
qsort(aiRetargetData.critterList, aiRetargetData.critterCount, sizeof(*aiRetargetData.critterList), _compare_nearer);
// NOTE: Uninline.
_ai_sort_list_distance(aiRetargetData.critterList, aiRetargetData.critterCount, source);
if (_cai_retargetTileFromFriendlyFireSubFunc(&aiRetargetData, *tilePtr) == 0) {
int minDistance = 99999;
@ -2650,7 +2685,8 @@ static int _ai_try_attack(Object* a1, Object* a2)
v38 = 0;
} else {
if (_ai_switch_weapons(a1, &hitMode, &weapon, a2) == -1 || weapon == NULL) {
if (_ai_move_steps_closer(a1, a2, a1->data.critter.combat.ap, v38) == -1) {
// NOTE: Uninline.
if (_ai_move_closer(a1, a2, v38) == -1) {
return -1;
}
}
@ -2822,7 +2858,8 @@ int _cai_perform_distance_prefs(Object* a1, Object* a2)
break;
case DISTANCE_CHARGE:
if (a2 != NULL) {
_ai_move_steps_closer(a1, a2, a1->data.critter.combat.ap, 1);
// NOTE: Uninline.
_ai_move_closer(a1, a2, 1);
}
break;
case DISTANCE_SNIPE:

View File

@ -68,6 +68,7 @@ typedef enum RadiationLevel {
} RadiationLevel;
static int _get_rad_damage_level(Object* obj, void* data);
static int critter_kill_count_clear();
static int _critterClearObjDrugs(Object* obj, void* data);
// 0x50141C
@ -159,7 +160,8 @@ int critterInit()
{
dudeResetName();
memset(gKillsByType, 0, sizeof(gKillsByType));
// NOTE: Uninline;
critter_kill_count_clear();
if (!messageListInit(&gCritterMessageList)) {
debugPrint("\nError: Initing critter name message file!");
@ -181,7 +183,9 @@ int critterInit()
void critterReset()
{
dudeResetName();
memset(gKillsByType, 0, sizeof(gKillsByType));
// NOTE: Uninline;
critter_kill_count_clear();
}
// 0x42D004
@ -680,6 +684,15 @@ int critterGetDamageType(Object* obj)
return proto->critter.data.damageType;
}
// NOTE: Inlined.
//
// 0x42D860
static int critter_kill_count_clear()
{
memset(gKillsByType, 0, sizeof(gKillsByType));
return 0;
}
// 0x42D878
int killsIncByType(int killType)
{

View File

@ -19,7 +19,8 @@ static void _debug_clear();
static int _debug_mono(char* string);
static int _debug_log(char* string);
static int _debug_screen(char* string);
static void _debug_putc(char ch);
static void _debug_putc(int ch);
static void _debug_scroll();
// 0x51DEF8
static FILE* _fd = NULL;
@ -174,7 +175,28 @@ static int _debug_puts(char* string)
// 0x4C6FAC
static void _debug_clear()
{
// TODO: Something with segments.
char* buffer;
int x;
int y;
buffer = NULL;
if (gDebugPrintProc == _debug_mono) {
buffer = (char*)0xB0000;
} else if (gDebugPrintProc == _debug_screen) {
buffer = (char*)0xB8000;
}
if (buffer != NULL) {
for (y = 0; y < 25; y++) {
for (x = 0; x < 80; x++) {
*buffer++ = ' ';
*buffer++ = 7;
}
}
_cury = 0;
_curx = 0;
}
}
// 0x4C7004
@ -220,15 +242,72 @@ static int _debug_screen(char* string)
}
// 0x4C709C
static void _debug_putc(char ch)
static void _debug_putc(int ch)
{
// TODO: Something with segments.
char* buffer;
buffer = (char*)0xB0000;
switch (ch) {
case 7:
printf("\x07");
return;
case 8:
if (_curx > 0) {
_curx--;
buffer += 2 * _curx + 2 * 80 * _cury;
*buffer++ = ' ';
*buffer = 7;
}
return;
case 9:
do {
_debug_putc(' ');
} while ((_curx - 1) % 4 != 0);
return;
case 13:
_curx = 0;
return;
default:
buffer += 2 * _curx + 2 * 80 * _cury;
*buffer++ = ch;
*buffer = 7;
_curx++;
if (_curx < 80) {
return;
}
// FALLTHROUGH
case 10:
_curx = 0;
_cury++;
if (_cury > 24) {
_cury = 24;
_debug_scroll();
}
return;
}
}
// 0x4C71AC
void _debug_scroll()
static void _debug_scroll()
{
// TODO: Something with segments.
char* buffer;
int x;
int y;
buffer = (char*)0xB0000;
for (y = 0; y < 24; y++) {
for (x = 0; x < 80 * 2; x++) {
buffer[0] = buffer[80 * 2];
buffer++;
}
}
for (x = 0; x < 80; x++) {
*buffer++ = ' ';
*buffer++ = 7;
}
}
// 0x4C71E8

View File

@ -5,7 +5,6 @@
#include "movie.h"
#include "platform_compat.h"
#include "text_font.h"
#include "widget.h"
#include "window_manager.h"
#include <string.h>
@ -209,7 +208,7 @@ void _replyAddOption(const char* a1, const char* a2, int a3)
v18->field_C[v17].string = NULL;
}
v18->field_C[v17].field_18 = widgetGetFont();
v18->field_C[v17].field_18 = windowGetFont();
v18->field_C[v17].field_1A = word_56DB60;
v18->field_C[v17].field_14 = a3;
}
@ -236,7 +235,7 @@ void _replyAddOptionProc(const char* a1, int a2, int a3)
v5->field_C[v13].proc = a2;
v5->field_C[v13].field_18 = widgetGetFont();
v5->field_C[v13].field_18 = windowGetFont();
v5->field_C[v13].field_1A = word_56DB60;
v5->field_C[v13].field_14 = a3;
}
@ -388,8 +387,8 @@ void _drawStr(int win, char* str, int font, int width, int height, int left, int
int old_font;
Rect rect;
old_font = widgetGetFont();
widgetSetFont(font);
old_font = windowGetFont();
windowSetFont(font);
_printStr(win, str, width, height, left, top, a8, a9, a10);
@ -398,7 +397,7 @@ void _drawStr(int win, char* str, int font, int width, int height, int left, int
rect.right = width + left;
rect.bottom = height + top;
windowRefreshRect(win, &rect);
widgetSetFont(old_font);
windowSetFont(old_font);
}
// 0x430D40

View File

@ -36,6 +36,7 @@
#define DISPLAY_MONITOR_BEEP_DELAY (500U)
static void display_clear();
static void displayMonitorRefresh();
static void displayMonitorScrollUpOnMouseDown(int btn, int keyCode);
static void displayMonitorScrollDownOnMouseDown(int btn, int keyCode);
@ -180,14 +181,8 @@ int displayMonitorInit()
gDisplayMonitorEnabled = true;
gDisplayMonitorInitialized = true;
for (int index = 0; index < gDisplayMonitorLinesCapacity; index++) {
gDisplayMonitorLines[index][0] = '\0';
}
_disp_start = 0;
_disp_curr = 0;
displayMonitorRefresh();
// NOTE: Uninline.
display_clear();
// SFALL
consoleFileInit();
@ -199,18 +194,12 @@ int displayMonitorInit()
// 0x431800
int displayMonitorReset()
{
if (gDisplayMonitorInitialized) {
for (int index = 0; index < gDisplayMonitorLinesCapacity; index++) {
gDisplayMonitorLines[index][0] = '\0';
}
_disp_start = 0;
_disp_curr = 0;
displayMonitorRefresh();
// NOTE: Uninline.
display_clear();
// SFALL
consoleFileReset();
}
return 0;
}
@ -319,6 +308,24 @@ void displayMonitorAddMessage(char* str)
displayMonitorRefresh();
}
// NOTE: Inlined.
//
// 0x431A2C
static void display_clear()
{
int index;
if (gDisplayMonitorInitialized) {
for (index = 0; index < gDisplayMonitorLinesCapacity; index++) {
gDisplayMonitorLines[index][0] = '\0';
}
_disp_start = 0;
_disp_curr = 0;
displayMonitorRefresh();
}
}
// 0x431A78
static void displayMonitorRefresh()
{

View File

@ -90,7 +90,7 @@ static char _aDec11199816543[] = VERSION_BUILD_TIME;
static bool gGameUiDisabled = false;
// 0x5186B8
static int _game_state_cur = 0;
static int _game_state_cur = GAME_STATE_0;
// 0x5186BC
static bool gIsMapper = false;
@ -439,7 +439,8 @@ void gameExit()
// 0x442D44
int gameHandleKey(int eventCode, bool isInCombatMode)
{
if (_game_state_cur == 5) {
// NOTE: Uninline.
if (_game_state() == GAME_STATE_5) {
_gdialogSystemEnter();
}
@ -479,6 +480,8 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
if (mouseX == _scr_size.left || mouseX == _scr_size.right
|| mouseY == _scr_size.top || mouseY == _scr_size.bottom) {
_gmouse_clicked_on_edge = true;
} else {
_gmouse_clicked_on_edge = false;
}
}
} else {
@ -501,6 +504,31 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
_intface_use_item();
}
break;
case -2:
if (1) {
int mouseEvent = mouseGetEvent();
int mouseX;
int mouseY;
mouseGetPosition(&mouseX, &mouseY);
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) != 0) {
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_REPEAT) == 0) {
if (mouseX == _scr_size.left || mouseX == _scr_size.right
|| mouseY == _scr_size.top || mouseY == _scr_size.bottom) {
_gmouse_clicked_on_edge = true;
} else {
_gmouse_clicked_on_edge = false;
}
}
} else {
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_UP) != 0) {
_gmouse_clicked_on_edge = false;
}
}
_gmouse_handle_event(mouseX, mouseY, mouseEvent);
}
break;
case KEY_CTRL_Q:
case KEY_CTRL_X:
case KEY_F10:
@ -746,14 +774,14 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
break;
case KEY_COMMA:
case KEY_LESS:
if (reg_anim_begin(0) == 0) {
if (reg_anim_begin(ANIMATION_REQUEST_RESERVED) == 0) {
animationRegisterRotateCounterClockwise(gDude);
reg_anim_end();
}
break;
case KEY_DOT:
case KEY_GREATER:
if (reg_anim_begin(0) == 0) {
if (reg_anim_begin(ANIMATION_REQUEST_RESERVED) == 0) {
animationRegisterRotateClockwise(gDude);
reg_anim_end();
}
@ -868,8 +896,6 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
break;
}
// TODO: Incomplete.
return 0;
}
@ -1024,15 +1050,15 @@ int _game_state()
// 0x443E34
int _game_state_request(int a1)
{
if (a1 == 0) {
a1 = 1;
} else if (a1 == 2) {
a1 = 3;
} else if (a1 == 4) {
a1 = 5;
if (a1 == GAME_STATE_0) {
a1 = GAME_STATE_1;
} else if (a1 == GAME_STATE_2) {
a1 = GAME_STATE_3;
} else if (a1 == GAME_STATE_4) {
a1 = GAME_STATE_5;
}
if (_game_state_cur != 4 || a1 != 5) {
if (_game_state_cur != GAME_STATE_4 || a1 != GAME_STATE_5) {
_game_state_cur = a1;
return 0;
}
@ -1047,14 +1073,14 @@ void _game_state_update()
v0 = _game_state_cur;
switch (_game_state_cur) {
case 1:
v0 = 0;
case GAME_STATE_1:
v0 = GAME_STATE_0;
break;
case 3:
v0 = 2;
case GAME_STATE_3:
v0 = GAME_STATE_2;
break;
case 5:
v0 = 4;
case GAME_STATE_5:
v0 = GAME_STATE_4;
}
_game_state_cur = v0;

View File

@ -4,6 +4,15 @@
#include "game_vars.h"
#include "message.h"
typedef enum GameState {
GAME_STATE_0,
GAME_STATE_1,
GAME_STATE_2,
GAME_STATE_3,
GAME_STATE_4,
GAME_STATE_5,
} GameState;
extern int* gGameGlobalVars;
extern int gGameGlobalVarsLength;
extern const char* asc_5186C8;

View File

@ -604,6 +604,8 @@ static int gGameDialogFidgetFrmCurrentFrame;
static int _gdialogReset();
static void gameDialogEndLips();
static int gdHide();
static int gdUnhide();
static int gameDialogAddMessageOption(int a1, int a2, int a3);
static int gameDialogAddTextOption(int a1, const char* a2, int a3);
static int gameDialogReviewWindowInit(int* win);
@ -640,6 +642,7 @@ static void _gDialogRefreshOptionsRect(int win, Rect* drawRect);
static void gameDialogTicker();
static void _gdialog_scroll_subwin(int a1, int a2, unsigned char* a3, unsigned char* a4, unsigned char* a5, int a6, int a7);
static int _text_num_lines(const char* a1, int a2);
static int text_to_rect_wrapped(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color);
static int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color, int a7);
static int _gdialog_barter_create_win();
static void _gdialog_barter_destroy_win();
@ -661,6 +664,7 @@ static void _gdCustomUpdateSetting(int option, int value);
static void gameDialogBarterButtonUpMouseUp(int btn, int a2);
static int _gdialog_window_create();
static void _gdialog_window_destroy();
static int talk_to_create_background_window();
static int gameDialogWindowRenderBackground();
static int _talkToRefreshDialogWindowRect(Rect* rect);
static void gameDialogRenderHighlight(unsigned char* src, int srcWidth, int srcHeight, int srcPitch, unsigned char* dest, int x, int y, int destPitch, unsigned char* a9, unsigned char* a10);
@ -854,7 +858,7 @@ void _gdialogSystemEnter()
_tile_scroll_to(gGameDialogOldCenterTile, 2);
}
_game_state_request(2);
_game_state_request(GAME_STATE_2);
_game_state_update();
}
@ -1081,7 +1085,15 @@ void gameDialogRenderSupplementaryMessage(char* msg)
int lineHeight = fontGetLineHeight();
int a4 = 0;
gameDialogDrawText(windowBuffer, &_replyRect, msg, &a4, lineHeight, 379, _colorTable[992] | 0x2000000, 1);
// NOTE: Uninline.
text_to_rect_wrapped(windowBuffer,
&_replyRect,
msg,
&a4,
lineHeight,
379,
_colorTable[992] | 0x2000000);
windowUnhide(_gd_replyWin);
windowRefresh(gGameDialogReplyWindow);
@ -1222,6 +1234,24 @@ void _gdialogUpdatePartyStatus()
return;
}
// NOTE: Uninline.
gdHide();
_gdialog_window_destroy();
gGameDialogSpeakerIsPartyMember = isPartyMember;
_gdialog_window_create();
// NOTE: Uninline.
gdUnhide();
}
// NOTE: Inlined.
//
// 0x4457EC
static int gdHide()
{
if (_gd_replyWin != -1) {
windowHide(_gd_replyWin);
}
@ -1230,12 +1260,14 @@ void _gdialogUpdatePartyStatus()
windowHide(_gd_optionsWin);
}
_gdialog_window_destroy();
gGameDialogSpeakerIsPartyMember = isPartyMember;
_gdialog_window_create();
return 0;
}
// NOTE: Inlined.
//
// 0x445818
static int gdUnhide()
{
if (_gd_replyWin != -1) {
windowUnhide(_gd_replyWin);
}
@ -1243,6 +1275,8 @@ void _gdialogUpdatePartyStatus()
if (_gd_optionsWin != -1) {
windowUnhide(_gd_optionsWin);
}
return 0;
}
// 0x44585C
@ -1554,7 +1588,14 @@ void gameDialogReviewWindowUpdate(int win, int origin)
exit(1);
}
y = gameDialogDrawText(windowBuffer + 113, &entriesRect, replyText, NULL, fontGetLineHeight(), 640, _colorTable[768] | 0x2000000, 1);
// NOTE: Uninline.
y = text_to_rect_wrapped(windowBuffer + 113,
&entriesRect,
replyText,
NULL,
fontGetLineHeight(),
640,
_colorTable[768] | 0x2000000);
// SFALL: Cosmetic fix to the dialog review interface to prevent the
// player name from being displayed at the bottom of the window when the
@ -1580,7 +1621,14 @@ void gameDialogReviewWindowUpdate(int win, int origin)
exit(1);
}
y = gameDialogDrawText(windowBuffer + 113, &entriesRect, optionText, NULL, fontGetLineHeight(), 640, _colorTable[15855] | 0x2000000, 1);
// NOTE: Uninline.
y = text_to_rect_wrapped(windowBuffer + 113,
&entriesRect,
optionText,
NULL,
fontGetLineHeight(),
640,
_colorTable[15855] | 0x2000000);
}
if (y >= 407) {
@ -2104,8 +2152,14 @@ void gameDialogOptionOnMouseEnter(int index)
}
}
unsigned char* windowBuffer = windowGetBuffer(gGameDialogOptionsWindow);
gameDialogDrawText(windowBuffer, &_optionRect, dialogOptionEntry->text, NULL, fontGetLineHeight(), 393, color, 1);
// NOTE: Uninline.
text_to_rect_wrapped(windowGetBuffer(gGameDialogOptionsWindow),
&_optionRect,
dialogOptionEntry->text,
NULL,
fontGetLineHeight(),
393,
color);
_optionRect.left = 0;
_optionRect.right = 391;
@ -2146,8 +2200,14 @@ void gameDialogOptionOnMouseExit(int index)
_optionRect.left = 5;
_optionRect.right = 388;
unsigned char* windowBuffer = windowGetBuffer(gGameDialogOptionsWindow);
gameDialogDrawText(windowBuffer, &_optionRect, dialogOptionEntry->text, NULL, fontGetLineHeight(), 393, color, 1);
// NOTE: Uninline.
text_to_rect_wrapped(windowGetBuffer(gGameDialogOptionsWindow),
&_optionRect,
dialogOptionEntry->text,
NULL,
fontGetLineHeight(),
393,
color);
_optionRect.right = 391;
_optionRect.top = dialogOptionEntry->field_14;
@ -2168,16 +2228,14 @@ void gameDialogRenderReply()
_demo_copy_title(gGameDialogReplyWindow);
// Render reply.
unsigned char* windowBuffer = windowGetBuffer(gGameDialogReplyWindow);
gameDialogDrawText(windowBuffer,
// NOTE: Uninline.
text_to_rect_wrapped(windowGetBuffer(gGameDialogReplyWindow),
&_replyRect,
gDialogReplyText,
&dword_58F4E0,
fontGetLineHeight(),
379,
_colorTable[992] | 0x2000000,
1);
_colorTable[992] | 0x2000000);
windowRefresh(gGameDialogReplyWindow);
}
@ -2287,14 +2345,14 @@ void _gdProcessUpdate()
y = 0;
}
gameDialogDrawText(windowGetBuffer(gGameDialogOptionsWindow),
// NOTE: Uninline.
text_to_rect_wrapped(windowGetBuffer(gGameDialogOptionsWindow),
&_optionRect,
dialogOptionEntry->text,
NULL,
fontGetLineHeight(),
393,
color,
1);
color);
_optionRect.top += 2;
@ -2325,14 +2383,8 @@ int _gdCreateHeadWindow()
int windowWidth = GAME_DIALOG_WINDOW_WIDTH;
int backgroundWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
int backgroundWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2;
gGameDialogBackgroundWindow = windowCreate(backgroundWindowX,
backgroundWindowY,
windowWidth,
GAME_DIALOG_WINDOW_HEIGHT,
256,
WINDOW_FLAG_0x02);
// NOTE: Uninline.
talk_to_create_background_window();
gameDialogWindowRenderBackground();
unsigned char* buf = windowGetBuffer(gGameDialogBackgroundWindow);
@ -2746,12 +2798,11 @@ void gameDialogTicker()
_dialogue_switch_mode = 0;
_gdialog_barter_destroy_win();
_gdialog_window_create();
if (_gd_replyWin != -1) {
windowUnhide(_gd_replyWin);
}
// NOTE: Uninline.
gdUnhide();
if (_gd_optionsWin != -1) {
windowUnhide(_gd_optionsWin);
// SFALL: Fix for the player's money not being displayed in the
// dialog window after leaving the barter/combat control interface.
gameDialogRenderCaps();
@ -2966,6 +3017,14 @@ int _text_num_lines(const char* a1, int a2)
return v1;
}
// NOTE: Inlined.
//
// 0x447F80
static int text_to_rect_wrapped(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color)
{
return gameDialogDrawText(buffer, rect, string, a4, height, pitch, color, 1);
}
// display_msg
// 0x447FA0
int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color, int a7)
@ -3573,13 +3632,8 @@ void gameDialogCombatControlButtonOnMouseUp(int btn, int keyCode)
_dialogue_switch_mode = 8;
_dialogue_state = 10;
if (_gd_replyWin != -1) {
windowHide(_gd_replyWin);
}
if (_gd_optionsWin != -1) {
windowHide(_gd_optionsWin);
}
// NOTE: Uninline.
gdHide();
}
// 0x4492D0
@ -4226,13 +4280,8 @@ void gameDialogBarterButtonUpMouseUp(int btn, int keyCode)
_dialogue_switch_mode = 2;
_dialogue_state = 4;
if (_gd_replyWin != -1) {
windowHide(_gd_replyWin);
}
if (_gd_optionsWin != -1) {
windowHide(_gd_optionsWin);
}
// NOTE: Uninline.
gdHide();
} else {
MessageListItem messageListItem;
// This person will not barter with you.
@ -4395,6 +4444,27 @@ void _gdialog_window_destroy()
}
}
// NOTE: Inlined.
//
// 0x44AAD8
static int talk_to_create_background_window()
{
int backgroundWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
int backgroundWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2;
gGameDialogBackgroundWindow = windowCreate(backgroundWindowX,
backgroundWindowY,
GAME_DIALOG_WINDOW_WIDTH,
GAME_DIALOG_WINDOW_HEIGHT,
256,
WINDOW_FLAG_0x02);
if (gGameDialogBackgroundWindow != -1) {
return 0;
}
return -1;
}
// 0x44AB18
int gameDialogWindowRenderBackground()
{

View File

@ -309,6 +309,7 @@ static int gameMouseObjectsReset();
static void gameMouseObjectsFree();
static int gameMouseActionMenuInit();
static void gameMouseActionMenuFree();
static int gmouse_3d_set_flat_fid(int fid, Rect* rect);
static int gameMouseUpdateHexCursorFid(Rect* rect);
static int _gmouse_3d_move_to(int x, int y, int elevation, Rect* a4);
static int gameMouseHandleScrolling(int x, int y, int cursor);
@ -426,6 +427,14 @@ void _gmouse_disable_scrolling()
_gmouse_scrolling_enabled = 0;
}
// NOTE: Inlined.
//
// 0x44B4E4
bool gmouse_scrolling_is_enabled()
{
return _gmouse_scrolling_enabled;
}
// 0x44B504
int _gmouse_get_click_to_scroll()
{
@ -483,7 +492,8 @@ void gameMouseRefresh()
if (gGameMouseCursor >= FIRST_GAME_MOUSE_ANIMATED_CURSOR) {
_mouse_info();
if (_gmouse_scrolling_enabled) {
// NOTE: Uninline.
if (gmouse_scrolling_is_enabled()) {
mouseGetPosition(&mouseX, &mouseY);
int oldMouseCursor = gGameMouseCursor;
@ -525,7 +535,8 @@ void gameMouseRefresh()
}
if (!_gmouse_enabled) {
if (_gmouse_scrolling_enabled) {
// NOTE: Uninline.
if (gmouse_scrolling_is_enabled()) {
mouseGetPosition(&mouseX, &mouseY);
int oldMouseCursor = gGameMouseCursor;
@ -700,7 +711,8 @@ void gameMouseRefresh()
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(OBJ_TYPE_INTERFACE, 282, 0, 0, 0);
if (objectSetFid(gGameMouseHexCursor, fid, &tmp) == 0) {
// NOTE: Uninline.
if (gmouse_3d_set_flat_fid(fid, &tmp) == 0) {
tileWindowRefreshRect(&tmp, gElevation);
}
}
@ -763,7 +775,8 @@ void gameMouseRefresh()
if (gameMouseRenderAccuracy(formattedAccuracy, color) == 0) {
Rect tmp;
int fid = buildFid(OBJ_TYPE_INTERFACE, 284, 0, 0, 0);
if (objectSetFid(gGameMouseHexCursor, fid, &tmp) == 0) {
// NOTE: Uninline.
if (gmouse_3d_set_flat_fid(fid, &tmp) == 0) {
tileWindowRefreshRect(&tmp, gElevation);
}
}
@ -1115,7 +1128,8 @@ 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(OBJ_TYPE_INTERFACE, 283, 0, 0, 0);
if (objectSetFid(gGameMouseHexCursor, fid, &v43) == 0 && _gmouse_3d_move_to(mouseX, mouseY, gElevation, &v43) == 0) {
// NOTE: Uninline.
if (gmouse_3d_set_flat_fid(fid, &v43) == 0 && _gmouse_3d_move_to(mouseX, mouseY, gElevation, &v43) == 0) {
tileWindowRefreshRect(&v43, gElevation);
isoDisable();
@ -1339,7 +1353,8 @@ void gameMouseSetMode(int mode)
fid = buildFid(OBJ_TYPE_INTERFACE, gGameMouseModeFrmIds[mode], 0, 0, 0);
Rect rect;
if (objectSetFid(gGameMouseHexCursor, fid, &rect) == -1) {
// NOTE: Uninline.
if (gmouse_3d_set_flat_fid(fid, &rect) == -1) {
return;
}
@ -2148,6 +2163,18 @@ void gameMouseActionMenuFree()
gGameMouseActionPickFrmDataSize = 0;
}
// NOTE: Inlined.
//
// 0x44DF1C
static int gmouse_3d_set_flat_fid(int fid, Rect* rect)
{
if (objectSetFid(gGameMouseHexCursor, fid, rect) == 0) {
return 0;
}
return -1;
}
// 0x44DF40
int gameMouseUpdateHexCursorFid(Rect* rect)
{
@ -2156,7 +2183,8 @@ int gameMouseUpdateHexCursorFid(Rect* rect)
return -1;
}
return objectSetFid(gGameMouseHexCursor, fid, rect);
// NOTE: Uninline.
return gmouse_3d_set_flat_fid(fid, rect);
}
// 0x44DF94

View File

@ -78,6 +78,7 @@ void _gmouse_enable();
void _gmouse_disable(int a1);
void _gmouse_enable_scrolling();
void _gmouse_disable_scrolling();
bool gmouse_scrolling_is_enabled();
int _gmouse_is_scrolling();
void gameMouseRefresh();
void _gmouse_handle_event(int mouseX, int mouseY, int mouseState);

View File

@ -13,7 +13,6 @@
#include "palette.h"
#include "platform_compat.h"
#include "text_font.h"
#include "widget.h"
#include "window_manager.h"
#include <stdio.h>
@ -221,11 +220,11 @@ int gameMoviePlay(int movie, int flags)
colorPaletteLoad(subtitlesPaletteFilePath);
oldTextColor = widgetGetTextColor();
widgetSetTextColor(1.0, 1.0, 1.0);
oldTextColor = windowGetTextColor();
windowSetTextColor(1.0, 1.0, 1.0);
oldFont = fontGetCurrent();
widgetSetFont(101);
windowSetFont(101);
}
bool cursorWasHidden = cursorIsHidden();
@ -278,12 +277,12 @@ int gameMoviePlay(int movie, int flags)
if (subtitlesEnabled) {
colorPaletteLoad("color.pal");
widgetSetFont(oldFont);
windowSetFont(oldFont);
float r = (float)((_Color2RGB_(oldTextColor) & 0x7C00) >> 10) * flt_50352A;
float g = (float)((_Color2RGB_(oldTextColor) & 0x3E0) >> 5) * flt_50352A;
float b = (float)(_Color2RGB_(oldTextColor) & 0x1F) * flt_50352A;
widgetSetTextColor(r, g, b);
windowSetTextColor(r, g, b);
}
windowDestroy(win);

View File

@ -103,6 +103,7 @@ typedef struct InterfaceItemState {
static int _intface_redraw_items_callback(Object* a1, Object* a2);
static int _intface_change_fid_callback(Object* a1, Object* a2);
static void interfaceBarSwapHandsAnimatePutAwayTakeOutSequence(int previousWeaponAnimationCode, int weaponAnimationCode);
static int intface_init_items();
static int interfaceBarRefreshMainAction();
static int endTurnButtonInit();
static int endTurnButtonFree();
@ -111,6 +112,7 @@ static int endCombatButtonFree();
static void interfaceUpdateAmmoBar(int x, int ratio);
static int _intface_item_reload();
static void interfaceRenderCounter(int x, int y, int previousValue, int value, int offset, int delay);
static int intface_fatal_error(int rc);
static int indicatorBarInit();
static void interfaceBarFree();
static void indicatorBarReset();
@ -430,18 +432,21 @@ int interfaceInit()
gInterfaceBarWindow = windowCreate(interfaceBarWindowX, interfaceBarWindowY, INTERFACE_BAR_WIDTH, INTERFACE_BAR_HEIGHT, _colorTable[0], WINDOW_HIDDEN);
if (gInterfaceBarWindow == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gInterfaceWindowBuffer = windowGetBuffer(gInterfaceBarWindow);
if (gInterfaceWindowBuffer == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 16, 0, 0, 0);
backgroundFrmData = artLockFrameData(fid, 0, 0, &backgroundFrmHandle);
if (backgroundFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
blitBufferToBuffer(backgroundFrmData, INTERFACE_BAR_WIDTH, INTERFACE_BAR_HEIGHT - 1, INTERFACE_BAR_WIDTH, gInterfaceWindowBuffer, 640);
@ -450,18 +455,21 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 47, 0, 0, 0);
gInventoryButtonUpFrmData = artLockFrameData(fid, 0, 0, &gInventoryButtonUpFrmHandle);
if (gInventoryButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 46, 0, 0, 0);
gInventoryButtonDownFrmData = artLockFrameData(fid, 0, 0, &gInventoryButtonDownFrmHandle);
if (gInventoryButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gInventoryButton = buttonCreate(gInterfaceBarWindow, 211, 40, 32, 21, -1, -1, -1, KEY_LOWERCASE_I, gInventoryButtonUpFrmData, gInventoryButtonDownFrmData, NULL, 0);
if (gInventoryButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetCallbacks(gInventoryButton, _gsound_med_butt_press, _gsound_med_butt_release);
@ -469,18 +477,21 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 18, 0, 0, 0);
gOptionsButtonUpFrmData = artLockFrameData(fid, 0, 0, &gOptionsButtonUpFrmHandle);
if (gOptionsButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 17, 0, 0, 0);
gOptionsButtonDownFrmData = artLockFrameData(fid, 0, 0, &gOptionsButtonDownFrmHandle);
if (gOptionsButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gOptionsButton = buttonCreate(gInterfaceBarWindow, 210, 61, 34, 34, -1, -1, -1, KEY_LOWERCASE_O, gOptionsButtonUpFrmData, gOptionsButtonDownFrmData, NULL, 0);
if (gOptionsButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetCallbacks(gOptionsButton, _gsound_med_butt_press, _gsound_med_butt_release);
@ -488,24 +499,28 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gSkilldexButtonUpFrmData = artLockFrameData(fid, 0, 0, &gSkilldexButtonUpFrmHandle);
if (gSkilldexButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 7, 0, 0, 0);
gSkilldexButtonDownFrmData = artLockFrameData(fid, 0, 0, &gSkilldexButtonDownFrmHandle);
if (gSkilldexButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gSkilldexButtonMaskFrmData = artLockFrameData(fid, 0, 0, &gSkilldexButtonMaskFrmHandle);
if (gSkilldexButtonMaskFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gSkilldexButton = buttonCreate(gInterfaceBarWindow, 523, 6, 22, 21, -1, -1, -1, KEY_LOWERCASE_S, gSkilldexButtonUpFrmData, gSkilldexButtonDownFrmData, NULL, BUTTON_FLAG_TRANSPARENT);
if (gSkilldexButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetMask(gSkilldexButton, gSkilldexButtonMaskFrmData);
@ -514,24 +529,28 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 13, 0, 0, 0);
gMapButtonUpFrmData = artLockFrameData(fid, 0, 0, &gMapButtonUpFrmHandle);
if (gMapButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 10, 0, 0, 0);
gMapButtonDownFrmData = artLockFrameData(fid, 0, 0, &gMapButtonDownFrmHandle);
if (gMapButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 13, 0, 0, 0);
gMapButtonMaskFrmData = artLockFrameData(fid, 0, 0, &gMapButtonMaskFrmHandle);
if (gMapButtonMaskFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gMapButton = buttonCreate(gInterfaceBarWindow, 526, 39, 41, 19, -1, -1, -1, KEY_TAB, gMapButtonUpFrmData, gMapButtonDownFrmData, NULL, BUTTON_FLAG_TRANSPARENT);
if (gMapButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetMask(gMapButton, gMapButtonMaskFrmData);
@ -540,18 +559,21 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 59, 0, 0, 0);
gPipboyButtonUpFrmData = artLockFrameData(fid, 0, 0, &gPipboyButtonUpFrmHandle);
if (gPipboyButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 58, 0, 0, 0);
gPipboyButtonDownFrmData = artLockFrameData(fid, 0, 0, &gPipboyButtonDownFrmHandle);
if (gPipboyButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gPipboyButton = buttonCreate(gInterfaceBarWindow, 526, 77, 41, 19, -1, -1, -1, KEY_LOWERCASE_P, gPipboyButtonUpFrmData, gPipboyButtonDownFrmData, NULL, 0);
if (gPipboyButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetMask(gPipboyButton, gMapButtonMaskFrmData);
@ -560,18 +582,21 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 57, 0, 0, 0);
gCharacterButtonUpFrmData = artLockFrameData(fid, 0, 0, &gCharacterButtonUpFrmHandle);
if (gCharacterButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 56, 0, 0, 0);
gCharacterButtonDownFrmData = artLockFrameData(fid, 0, 0, &gCharacterButtonDownFrmHandle);
if (gCharacterButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gCharacterButton = buttonCreate(gInterfaceBarWindow, 526, 58, 41, 19, -1, -1, -1, KEY_LOWERCASE_C, gCharacterButtonUpFrmData, gCharacterButtonDownFrmData, NULL, 0);
if (gCharacterButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetMask(gCharacterButton, gMapButtonMaskFrmData);
@ -580,19 +605,22 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 32, 0, 0, 0);
gSingleAttackButtonUpData = artLockFrameData(fid, 0, 0, &gSingleAttackButtonUpHandle);
if (gSingleAttackButtonUpData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 31, 0, 0, 0);
gSingleAttackButtonDownData = artLockFrameData(fid, 0, 0, &gSingleAttackButtonDownHandle);
if (gSingleAttackButtonDownData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 73, 0, 0, 0);
_itemButtonDisabled = artLockFrameData(fid, 0, 0, &_itemButtonDisabledKey);
if (_itemButtonDisabled == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
memcpy(_itemButtonUp, gSingleAttackButtonUpData, sizeof(_itemButtonUp));
@ -600,7 +628,8 @@ int interfaceInit()
gSingleAttackButton = buttonCreate(gInterfaceBarWindow, 267, 26, 188, 67, -1, -1, -1, -20, _itemButtonUp, _itemButtonDown, NULL, BUTTON_FLAG_TRANSPARENT);
if (gSingleAttackButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetRightMouseCallbacks(gSingleAttackButton, -1, KEY_LOWERCASE_N, NULL, NULL);
@ -609,25 +638,29 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gChangeHandsButtonUpFrmData = artLockFrameData(fid, 0, 0, &gChangeHandsButtonUpFrmHandle);
if (gChangeHandsButtonUpFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 7, 0, 0, 0);
gChangeHandsButtonDownFrmData = artLockFrameData(fid, 0, 0, &gChangeHandsButtonDownFrmHandle);
if (gChangeHandsButtonDownFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 6, 0, 0, 0);
gChangeHandsButtonMaskFrmData = artLockFrameData(fid, 0, 0, &gChangeHandsButtonMaskFrmHandle);
if (gChangeHandsButtonMaskFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
// Swap hands button
gChangeHandsButton = buttonCreate(gInterfaceBarWindow, 218, 6, 22, 21, -1, -1, -1, KEY_LOWERCASE_B, gChangeHandsButtonUpFrmData, gChangeHandsButtonDownFrmData, NULL, BUTTON_FLAG_TRANSPARENT);
if (gChangeHandsButton == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
buttonSetMask(gChangeHandsButton, gChangeHandsButtonMaskFrmData);
@ -636,39 +669,42 @@ int interfaceInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 82, 0, 0, 0);
gNumbersFrmData = artLockFrameData(fid, 0, 0, &gNumbersFrmHandle);
if (gNumbersFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 83, 0, 0, 0);
gGreenLightFrmData = artLockFrameData(fid, 0, 0, &gGreenLightFrmHandle);
if (gGreenLightFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 84, 0, 0, 0);
gYellowLightFrmData = artLockFrameData(fid, 0, 0, &gYellowLightFrmHandle);
if (gYellowLightFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
fid = buildFid(OBJ_TYPE_INTERFACE, 85, 0, 0, 0);
gRedLightFrmData = artLockFrameData(fid, 0, 0, &gRedLightFrmHandle);
if (gRedLightFrmData == NULL) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
blitBufferToBuffer(gInterfaceWindowBuffer + 640 * 14 + 316, 90, 5, 640, gInterfaceActionPointsBarBackground, 90);
if (indicatorBarInit() == -1) {
goto err;
// NOTE: Uninline.
return intface_fatal_error(-1);
}
gInterfaceCurrentHand = HAND_LEFT;
// FIXME: For unknown reason these values initialized with -1. It's never
// checked for -1, so I have no explanation for this.
gInterfaceItemStates[HAND_LEFT].item = (Object*)-1;
gInterfaceItemStates[HAND_RIGHT].item = (Object*)-1;
// NOTE: Uninline.
intface_init_items();
displayMonitorInit();
@ -677,12 +713,6 @@ int interfaceInit()
_intfaceHidden = 1;
return 0;
err:
interfaceFree();
return -1;
}
// 0x45E3D0
@ -690,10 +720,8 @@ void interfaceReset()
{
interfaceBarEnable();
if (gInterfaceBarWindow != -1 && !_intfaceHidden) {
windowHide(gInterfaceBarWindow);
_intfaceHidden = 1;
}
// NOTE: Uninline.
intface_hide();
indicatorBarRefresh();
displayMonitorReset();
@ -925,11 +953,8 @@ int interfaceLoad(File* stream)
}
if (v2) {
if (gInterfaceBarWindow != -1 && !_intfaceHidden) {
windowHide(gInterfaceBarWindow);
_intfaceHidden = 1;
}
indicatorBarRefresh();
// NOTE: Uninline.
intface_hide();
} else {
_intface_show();
}
@ -975,6 +1000,20 @@ int interfaceSave(File* stream)
return 0;
}
// NOTE: Inlined.
//
// 0x45E9E0
void intface_hide()
{
if (gInterfaceBarWindow != -1) {
if (!_intfaceHidden) {
windowHide(gInterfaceBarWindow);
_intfaceHidden = 1;
}
}
indicatorBarRefresh();
}
// 0x45EA10
void _intface_show()
{
@ -1708,6 +1747,19 @@ void interfaceBarEndButtonsRenderRedLights()
}
}
// NOTE: Inlined.
//
// 0x45FD2C
static int intface_init_items()
{
// FIXME: For unknown reason these values initialized with -1. It's never
// checked for -1, so I have no explanation for this.
gInterfaceItemStates[HAND_LEFT].item = (Object*)-1;
gInterfaceItemStates[HAND_RIGHT].item = (Object*)-1;
return 0;
}
// 0x45FD88
static int interfaceBarRefreshMainAction()
{
@ -2358,6 +2410,16 @@ static void interfaceRenderCounter(int x, int y, int previousValue, int value, i
}
}
// NOTE: Inlined.
//
// 0x461128
static int intface_fatal_error(int rc)
{
interfaceFree();
return rc;
}
// 0x461134
static int indicatorBarInit()
{

View File

@ -37,6 +37,7 @@ void interfaceReset();
void interfaceFree();
int interfaceLoad(File* stream);
int interfaceSave(File* stream);
void intface_hide();
void _intface_show();
void interfaceBarEnable();
void interfaceBarDisable();

View File

@ -21,7 +21,7 @@ typedef struct ProgramListNode {
struct ProgramListNode* prev; // prev
} ProgramListNode;
static int _defaultTimerFunc();
static unsigned int _defaultTimerFunc();
static char* _defaultFilename_(char* s);
static int _outputStr(char* a1);
static int _checkWait(Program* program);
@ -34,12 +34,14 @@ static void stackPushInt16(unsigned char* a1, int* a2, int value);
static void stackPushInt32(unsigned char* a1, int* a2, int value);
static int stackPopInt32(unsigned char* a1, int* a2);
static opcode_t stackPopInt16(unsigned char* a1, int* a2);
static void _interpretIncStringRef(Program* program, opcode_t opcode, int value);
static void programReturnStackPushInt16(Program* program, int value);
static opcode_t programReturnStackPopInt16(Program* program);
static int programReturnStackPopInt32(Program* program);
static void _detachProgram(Program* program);
static void _purgeProgram(Program* program);
static void programFree(Program* program);
static opcode_t _getOp(Program* program);
static void programMarkHeap(Program* program);
static void opNoop(Program* program);
static void opPush(Program* program);
@ -117,7 +119,9 @@ static void opExec(Program* program);
static void opCheckProcedureArgumentCount(Program* program);
static void opLookupStringProc(Program* program);
static void _setupCallWithReturnVal(Program* program, int address, int a3);
static void _setupCall(Program* program, int address, int returnAddress);
static void _setupExternalCallWithReturnVal(Program* program1, Program* program2, int address, int a4);
static void _setupExternalCall(Program* program1, Program* program2, int address, int a4);
static void _doEvents();
static void programListNodeFree(ProgramListNode* programListNode);
static void interpreterPrintStats();
@ -133,10 +137,10 @@ int _TimeOut = 0;
static int _Enabled = 1;
// 0x519040
static int (*_timerFunc)() = _defaultTimerFunc;
InterpretTimerFunc* _timerFunc = _defaultTimerFunc;
// 0x519044
static int _timerTick = 1000;
static unsigned int _timerTick = 1000;
// 0x519048
static char* (*_filenameFunc)(char*) = _defaultFilename_;
@ -163,7 +167,7 @@ static int _suspendEvents;
static int _busy;
// 0x4670A0
static int _defaultTimerFunc()
static unsigned int _defaultTimerFunc()
{
return _get_time();
}
@ -189,7 +193,7 @@ static int _outputStr(char* a1)
// 0x4670C8
static int _checkWait(Program* program)
{
return 1000 * _timerFunc() / _timerTick <= program->field_70;
return 1000 * _timerFunc() / _timerTick <= program->waitEnd;
}
// 0x4670FC
@ -360,8 +364,18 @@ static opcode_t stackPopInt16(unsigned char* data, int* pointer)
return stackReadInt16(data, *pointer);
}
// NOTE: Inlined.
//
// 0x467424
static void _interpretIncStringRef(Program* program, opcode_t opcode, int value)
{
if (opcode == VALUE_TYPE_DYNAMIC_STRING) {
*(short*)(program->dynamicStrings + 4 + value - 2) += 1;
}
}
// 0x467440
void programPopString(Program* program, opcode_t opcode, int value)
void _interpretDecStringRef(Program* program, opcode_t opcode, int value)
{
if (opcode == VALUE_TYPE_DYNAMIC_STRING) {
char* string = (char*)(program->dynamicStrings + 4 + value);
@ -483,6 +497,20 @@ Program* programCreateByPath(const char* path)
return program;
}
// NOTE: Inlined.
//
// 0x4678BC
opcode_t _getOp(Program* program)
{
int instructionPointer;
instructionPointer = program->instructionPointer;
program->instructionPointer = instructionPointer + 2;
// NOTE: Uninline.
return stackReadInt16(program->data, instructionPointer);
}
// 0x4678E0
char* programGetString(Program* program, opcode_t opcode, int offset)
{
@ -741,10 +769,10 @@ static void opWait(Program* program)
{
int data = programStackPopInteger(program);
program->field_74 = 1000 * _timerFunc() / _timerTick;
program->field_70 = program->field_74 + data;
program->field_7C = _checkWait;
program->flags |= PROGRAM_FLAG_0x10;
program->waitStart = 1000 * _timerFunc() / _timerTick;
program->waitEnd = program->waitStart + data;
program->checkWaitFunc = _checkWait;
program->flags |= PROGRAM_IS_WAITING;
}
// 0x468218
@ -809,13 +837,14 @@ static void opStore(Program* program)
ProgramValue oldValue = program->stackValues->at(pos);
if (oldValue.opcode == VALUE_TYPE_DYNAMIC_STRING) {
programPopString(program, oldValue.opcode, oldValue.integerValue);
_interpretDecStringRef(program, oldValue.opcode, oldValue.integerValue);
}
program->stackValues->at(pos) = value;
if (value.opcode == VALUE_TYPE_DYNAMIC_STRING) {
*(short*)(program->dynamicStrings + 4 + value.integerValue - 2) += 1;
// NOTE: Uninline.
_interpretIncStringRef(program, VALUE_TYPE_DYNAMIC_STRING, value.integerValue);
}
}
@ -1988,7 +2017,7 @@ static void opCall(Program* program)
static void op801F(Program* program)
{
program->windowId = programStackPopInteger(program);
program->field_7C = (int (*)(Program*))programStackPopPointer(program);
program->checkWaitFunc = (InterpretCheckWaitFunc*)programStackPopPointer(program);
program->flags = programStackPopInteger(program) & 0xFFFF;
}
@ -2041,7 +2070,7 @@ static void op8026(Program* program)
op801F(program);
Program* v1 = (Program*)programReturnStackPopPointer(program);
v1->field_7C = (int (*)(Program*))programReturnStackPopPointer(program);
v1->checkWaitFunc = (InterpretCheckWaitFunc*)programReturnStackPopPointer(program);
v1->flags = programReturnStackPopInteger(program);
program->instructionPointer = programReturnStackPopInteger(program);
@ -2057,7 +2086,7 @@ static void op8022(Program* program)
op801F(program);
Program* v1 = (Program*)programReturnStackPopPointer(program);
v1->field_7C = (int (*)(Program*))programReturnStackPopPointer(program);
v1->checkWaitFunc = (InterpretCheckWaitFunc*)programReturnStackPopPointer(program);
v1->flags = programReturnStackPopInteger(program);
program->instructionPointer = programReturnStackPopInteger(program);
@ -2069,7 +2098,7 @@ static void op8023(Program* program)
op801F(program);
Program* v1 = (Program*)programReturnStackPopPointer(program);
v1->field_7C = (int (*)(Program*))programReturnStackPopPointer(program);
v1->checkWaitFunc = (InterpretCheckWaitFunc*)programReturnStackPopPointer(program);
v1->flags = programReturnStackPopInteger(program);
program->instructionPointer = programReturnStackPopInteger(program);
@ -2086,7 +2115,7 @@ static void op8024(Program* program)
op801F(program);
Program* v10 = (Program*)programReturnStackPopPointer(program);
v10->field_7C = (int (*)(Program*))programReturnStackPopPointer(program);
v10->checkWaitFunc = (InterpretCheckWaitFunc*)programReturnStackPopPointer(program);
v10->flags = programReturnStackPopInteger(program);
if ((value.opcode & 0xF7FF) == VALUE_TYPE_STRING) {
char* string = programGetString(program, value.opcode, value.integerValue);
@ -2155,13 +2184,14 @@ static void opStoreGlobalVariable(Program* program)
ProgramValue oldValue = program->stackValues->at(program->basePointer + addr);
if (oldValue.opcode == VALUE_TYPE_DYNAMIC_STRING) {
programPopString(program, oldValue.opcode, oldValue.integerValue);
_interpretDecStringRef(program, oldValue.opcode, oldValue.integerValue);
}
program->stackValues->at(program->basePointer + addr) = value;
if (value.opcode == VALUE_TYPE_DYNAMIC_STRING) {
*(short*)(program->dynamicStrings + 4 + value.integerValue - 2) += 1;
// NOTE: Uninline.
_interpretIncStringRef(program, VALUE_TYPE_DYNAMIC_STRING, value.integerValue);
}
}
@ -2309,17 +2339,15 @@ static void opCallStart(Program* program)
program->flags |= PROGRAM_FLAG_0x20;
char* name = programStackPopString(program);
name = _interpretMangleName(name);
program->child = programCreateByPath(name);
// NOTE: Uninline.
program->child = runScript(name);
if (program->child == NULL) {
char err[260];
sprintf(err, "Error spawning child %s", name);
programFatalError(err);
}
programListNodeCreate(program->child);
_interpret(program->child, 24);
program->child->parent = program;
program->child->windowId = program->windowId;
}
@ -2335,17 +2363,15 @@ static void opSpawn(Program* program)
program->flags |= PROGRAM_FLAG_0x0100;
char* name = programStackPopString(program);
name = _interpretMangleName(name);
program->child = programCreateByPath(name);
// NOTE: Uninline.
program->child = runScript(name);
if (program->child == NULL) {
char err[256];
char err[260];
sprintf(err, "Error spawning child %s", name);
programFatalError(err);
}
programListNodeCreate(program->child);
_interpret(program->child, 24);
program->child->parent = program;
program->child->windowId = program->windowId;
@ -2360,8 +2386,7 @@ static void opSpawn(Program* program)
static Program* forkProgram(Program* program)
{
char* name = programStackPopString(program);
name = _interpretMangleName(name);
Program* forked = programCreateByPath(name);
Program* forked = runScript(name);
if (forked == NULL) {
char err[256];
@ -2369,10 +2394,6 @@ static Program* forkProgram(Program* program)
programFatalError(err);
}
programListNodeCreate(forked);
_interpret(forked, 24);
forked->windowId = program->windowId;
return forked;
@ -2595,25 +2616,24 @@ void _interpret(Program* program, int a2)
break;
}
if ((program->flags & PROGRAM_FLAG_0x10) != 0) {
if ((program->flags & PROGRAM_IS_WAITING) != 0) {
_busy = 1;
if (program->field_7C != NULL) {
if (!program->field_7C(program)) {
if (program->checkWaitFunc != NULL) {
if (!program->checkWaitFunc(program)) {
_busy = 0;
continue;
}
}
_busy = 0;
program->field_7C = NULL;
program->flags &= ~PROGRAM_FLAG_0x10;
program->checkWaitFunc = NULL;
program->flags &= ~PROGRAM_IS_WAITING;
}
int instructionPointer = program->instructionPointer;
program->instructionPointer = instructionPointer + 2;
// NOTE: Uninline.
opcode_t opcode = _getOp(program);
opcode_t opcode = stackReadInt16(program->data, instructionPointer);
// TODO: Replace with field_82 and field_80?
program->flags &= 0xFFFF;
program->flags |= (opcode << 16);
@ -2663,7 +2683,7 @@ static void _setupCallWithReturnVal(Program* program, int address, int returnAdd
// Save program flags
programStackPushInteger(program, program->flags & 0xFFFF);
programStackPushPointer(program, (void*)program->field_7C);
programStackPushPointer(program, (void*)program->checkWaitFunc);
programStackPushInteger(program, program->windowId);
@ -2671,6 +2691,15 @@ static void _setupCallWithReturnVal(Program* program, int address, int returnAdd
program->instructionPointer = address;
}
// NOTE: Inlined.
//
// 0x46CF78
static void _setupCall(Program* program, int address, int returnAddress)
{
_setupCallWithReturnVal(program, address, returnAddress);
programStackPushInteger(program, 0);
}
// 0x46CF9C
static void _setupExternalCallWithReturnVal(Program* program1, Program* program2, int address, int a4)
{
@ -2678,7 +2707,7 @@ static void _setupExternalCallWithReturnVal(Program* program1, Program* program2
programReturnStackPushInteger(program2, program1->flags & 0xFFFF);
programReturnStackPushPointer(program2, (void*)program1->field_7C);
programReturnStackPushPointer(program2, (void*)program1->checkWaitFunc);
programReturnStackPushPointer(program2, program1);
@ -2686,7 +2715,7 @@ static void _setupExternalCallWithReturnVal(Program* program1, Program* program2
programStackPushInteger(program2, program2->flags & 0xFFFF);
programStackPushPointer(program2, (void*)program2->field_7C);
programStackPushPointer(program2, (void*)program2->checkWaitFunc);
programStackPushInteger(program2, program2->windowId);
@ -2697,66 +2726,66 @@ static void _setupExternalCallWithReturnVal(Program* program1, Program* program2
program1->flags |= PROGRAM_FLAG_0x20;
}
// 0x46DB58
void _executeProc(Program* program, int procedure_index)
// NOTE: Inlined.
//
// 0x46D0B0
static void _setupExternalCall(Program* program1, Program* program2, int address, int a4)
{
Program* external_program;
char* identifier;
int address;
int arguments_count;
unsigned char* procedure_ptr;
int flags;
_setupExternalCallWithReturnVal(program1, program2, address, a4);
programStackPushInteger(program2, 0);
}
// 0x46DB58
void _executeProc(Program* program, int procedureIndex)
{
unsigned char* procedurePtr;
char* procedureIdentifier;
int procedureAddress;
Program* externalProgram;
int externalProcedureAddress;
int externalProcedureArgumentCount;
int procedureFlags;
char err[256];
Program* context;
procedure_ptr = program->procedures + 4 + sizeof(Procedure) * procedure_index;
flags = stackReadInt32(procedure_ptr, 4);
if (!(flags & PROCEDURE_FLAG_IMPORTED)) {
address = stackReadInt32(procedure_ptr, 16);
_setupCallWithReturnVal(program, address, 20);
programStackPushInteger(program, 0);
if (!(flags & PROCEDURE_FLAG_CRITICAL)) {
return;
}
program->flags |= PROGRAM_FLAG_CRITICAL_SECTION;
context = program;
procedurePtr = program->procedures + 4 + sizeof(Procedure) * procedureIndex;
procedureFlags = stackReadInt32(procedurePtr, 4);
if ((procedureFlags & PROCEDURE_FLAG_IMPORTED) != 0) {
procedureIdentifier = programGetIdentifier(program, stackReadInt32(procedurePtr, 0));
externalProgram = externalProcedureGetProgram(procedureIdentifier, &externalProcedureAddress, &externalProcedureArgumentCount);
if (externalProgram != NULL) {
if (externalProcedureArgumentCount == 0) {
} else {
identifier = programGetIdentifier(program, stackReadInt32(procedure_ptr, 0));
external_program = externalProcedureGetProgram(identifier, &address, &arguments_count);
if (external_program == NULL) {
sprintf(err, "External procedure %s not found\n", identifier);
// TODO: Incomplete.
// _interpretOutput(err);
return;
}
if (arguments_count != 0) {
sprintf(err, "External procedure cannot take arguments in interrupt context");
// TODO: Incomplete.
// _interpretOutput(err);
return;
_interpretOutput(err);
}
} else {
sprintf(err, "External procedure %s not found\n", procedureIdentifier);
_interpretOutput(err);
}
_setupExternalCallWithReturnVal(program, external_program, address, 28);
// NOTE: Uninline.
_setupExternalCall(program, externalProgram, externalProcedureAddress, 28);
programStackPushInteger(external_program, 0);
procedurePtr = externalProgram->procedures + 4 + sizeof(Procedure) * procedureIndex;
procedureFlags = stackReadInt32(procedurePtr, 4);
procedure_ptr = external_program->procedures + 4 + sizeof(Procedure) * procedure_index;
flags = stackReadInt32(procedure_ptr, 4);
if (!(flags & PROCEDURE_FLAG_CRITICAL)) {
return;
if ((procedureFlags & PROCEDURE_FLAG_CRITICAL) != 0) {
// NOTE: Uninline.
opEnterCriticalSection(externalProgram);
_interpret(externalProgram, 0);
}
} else {
procedureAddress = stackReadInt32(procedurePtr, 16);
external_program->flags |= PROGRAM_FLAG_CRITICAL_SECTION;
context = external_program;
// NOTE: Uninline.
_setupCall(program, procedureAddress, 20);
if ((procedureFlags & PROCEDURE_FLAG_CRITICAL) != 0) {
// NOTE: Uninline.
opEnterCriticalSection(program);
_interpret(program, 0);
}
}
_interpret(context, 0);
}
// Returns index of the procedure with specified name or -1 if no such
@ -2781,68 +2810,112 @@ int programFindProcedure(Program* program, const char* name)
}
// 0x46DD2C
void _executeProcedure(Program* program, int procedure_index)
void _executeProcedure(Program* program, int procedureIndex)
{
Program* external_program;
char* identifier;
int address;
int arguments_count;
unsigned char* procedure_ptr;
int flags;
unsigned char* procedurePtr;
char* procedureIdentifier;
int procedureAddress;
Program* externalProgram;
int externalProcedureAddress;
int externalProcedureArgumentCount;
int procedureFlags;
char err[256];
jmp_buf jmp_buf;
Program* v13;
jmp_buf env;
procedure_ptr = program->procedures + 4 + sizeof(Procedure) * procedure_index;
flags = stackReadInt32(procedure_ptr, 4);
procedurePtr = program->procedures + 4 + sizeof(Procedure) * procedureIndex;
procedureFlags = stackReadInt32(procedurePtr, 4);
if (flags & PROCEDURE_FLAG_IMPORTED) {
identifier = programGetIdentifier(program, stackReadInt32(procedure_ptr, 0));
external_program = externalProcedureGetProgram(identifier, &address, &arguments_count);
if (external_program == NULL) {
sprintf(err, "External procedure %s not found\n", identifier);
// TODO: Incomplete.
// _interpretOutput(err);
return;
}
if (arguments_count != 0) {
sprintf(err, "External procedure cannot take arguments in interrupt context");
// TODO: Incomplete.
// _interpretOutput(err);
return;
}
_setupExternalCallWithReturnVal(program, external_program, address, 32);
programStackPushInteger(external_program, 0);
memcpy(jmp_buf, program->env, sizeof(jmp_buf));
v13 = external_program;
if ((procedureFlags & PROCEDURE_FLAG_IMPORTED) != 0) {
procedureIdentifier = programGetIdentifier(program, stackReadInt32(procedurePtr, 0));
externalProgram = externalProcedureGetProgram(procedureIdentifier, &externalProcedureAddress, &externalProcedureArgumentCount);
if (externalProgram != NULL) {
if (externalProcedureArgumentCount == 0) {
// NOTE: Uninline.
_setupExternalCall(program, externalProgram, externalProcedureAddress, 32);
memcpy(env, program->env, sizeof(env));
_interpret(externalProgram, -1);
memcpy(externalProgram->env, env, sizeof(env));
} else {
address = stackReadInt32(procedure_ptr, 16);
_setupCallWithReturnVal(program, address, 24);
// Push number of arguments. It's always zero for built-in procs. This
// number is consumed by 0x802B.
programStackPushInteger(program, 0);
memcpy(jmp_buf, program->env, sizeof(jmp_buf));
v13 = program;
sprintf(err, "External procedure cannot take arguments in interrupt context");
_interpretOutput(err);
}
} else {
sprintf(err, "External procedure %s not found\n", procedureIdentifier);
_interpretOutput(err);
}
} else {
procedureAddress = stackReadInt32(procedurePtr, 16);
_interpret(v13, -1);
memcpy(v13->env, jmp_buf, sizeof(jmp_buf));
// NOTE: Uninline.
_setupCall(program, procedureAddress, 24);
memcpy(env, program->env, sizeof(env));
_interpret(program, -1);
memcpy(program->env, env, sizeof(env));
}
}
// 0x46DEE4
static void _doEvents()
{
// TODO: Incomplete.
ProgramListNode* programListNode;
unsigned int time;
int procedureCount;
int procedureIndex;
unsigned char* procedurePtr;
int procedureFlags;
int oldProgramFlags;
int oldInstructionPointer;
int data;
jmp_buf env;
if (_suspendEvents) {
return;
}
programListNode = gInterpreterProgramListHead;
time = 1000 * _timerFunc() / _timerTick;
while (programListNode != NULL) {
procedureCount = stackReadInt32(programListNode->program->procedures, 0);
procedurePtr = programListNode->program->procedures + 4;
for (procedureIndex = 0; procedureIndex < procedureCount; procedureIndex++) {
procedureFlags = stackReadInt32(procedurePtr, 4);
if ((procedureFlags & PROCEDURE_FLAG_CONDITIONAL) != 0) {
memcpy(env, programListNode->program, sizeof(env));
oldProgramFlags = programListNode->program->flags;
oldInstructionPointer = programListNode->program->instructionPointer;
programListNode->program->flags = 0;
programListNode->program->instructionPointer = stackReadInt32(procedurePtr, 12);
_interpret(programListNode->program, -1);
if ((programListNode->program->flags & PROGRAM_FLAG_0x04) == 0) {
data = programStackPopInteger(programListNode->program);
programListNode->program->flags = oldProgramFlags;
programListNode->program->instructionPointer = oldInstructionPointer;
if (data != 0) {
// NOTE: Uninline.
stackWriteInt32(0, procedurePtr, 4);
_executeProc(programListNode->program, procedureIndex);
}
}
memcpy(programListNode->program, env, sizeof(env));
} else if ((procedureFlags & PROCEDURE_FLAG_TIMED) != 0) {
if ((unsigned int)stackReadInt32(procedurePtr, 8) < time) {
// NOTE: Uninline.
stackWriteInt32(0, procedurePtr, 4);
_executeProc(programListNode->program, procedureIndex);
}
}
procedurePtr += sizeof(Procedure);
}
programListNode = programListNode->next;
}
}
// 0x46E10C
@ -2869,8 +2942,6 @@ static void programListNodeFree(ProgramListNode* programListNode)
// 0x46E154
void programListNodeCreate(Program* program)
{
program->flags |= PROGRAM_FLAG_0x02;
ProgramListNode* programListNode = (ProgramListNode*)internal_malloc_safe(sizeof(*programListNode), __FILE__, __LINE__); // .\\int\\INTRPRET.C, 2907
programListNode->program = program;
programListNode->next = gInterpreterProgramListHead;
@ -2883,6 +2954,33 @@ void programListNodeCreate(Program* program)
gInterpreterProgramListHead = programListNode;
}
// NOTE: Inlined.
//
// 0x46E15C
void runProgram(Program* program)
{
program->flags |= PROGRAM_FLAG_0x02;
programListNodeCreate(program);
}
// NOTE: Inlined.
//
// 0x46E19C
Program* runScript(char* name)
{
Program* program;
// NOTE: Uninline.
program = programCreateByPath(_interpretMangleName(name));
if (program != NULL) {
// NOTE: Uninline.
runProgram(program);
_interpret(program, 24);
}
return program;
}
// 0x46E1EC
void _updatePrograms()
{
@ -2971,7 +3069,8 @@ void programStackPushValue(Program* program, ProgramValue& programValue)
program->stackValues->push_back(programValue);
if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) {
*(short*)(program->dynamicStrings + 4 + programValue.integerValue - 2) += 1;
// NOTE: Uninline.
_interpretIncStringRef(program, VALUE_TYPE_DYNAMIC_STRING, programValue.integerValue);
}
}
@ -3017,7 +3116,7 @@ ProgramValue programStackPopValue(Program* program)
program->stackValues->pop_back();
if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) {
programPopString(program, programValue.opcode, programValue.integerValue);
_interpretDecStringRef(program, programValue.opcode, programValue.integerValue);
}
return programValue;
@ -3076,7 +3175,8 @@ void programReturnStackPushValue(Program* program, ProgramValue& programValue)
program->returnStackValues->push_back(programValue);
if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) {
*(short*)(program->dynamicStrings + 4 + programValue.integerValue - 2) += 1;
// NOTE: Uninline.
_interpretIncStringRef(program, VALUE_TYPE_DYNAMIC_STRING, programValue.integerValue);
}
}
@ -3106,7 +3206,7 @@ ProgramValue programReturnStackPopValue(Program* program)
program->returnStackValues->pop_back();
if (programValue.opcode == VALUE_TYPE_DYNAMIC_STRING) {
programPopString(program, programValue.opcode, programValue.integerValue);
_interpretDecStringRef(program, programValue.opcode, programValue.integerValue);
}
return programValue;

View File

@ -100,7 +100,9 @@ typedef enum ProgramFlags {
PROGRAM_FLAG_0x02 = 0x02,
PROGRAM_FLAG_0x04 = 0x04,
PROGRAM_FLAG_STOPPED = 0x08,
PROGRAM_FLAG_0x10 = 0x10,
// Program is in waiting state with `checkWaitFunc` set.
PROGRAM_IS_WAITING = 0x10,
PROGRAM_FLAG_0x20 = 0x20,
PROGRAM_FLAG_0x40 = 0x40,
PROGRAM_FLAG_CRITICAL_SECTION = 0x80,
@ -147,6 +149,9 @@ typedef struct ProgramValue {
typedef std::vector<ProgramValue> ProgramStack;
typedef struct Program Program;
typedef int(InterpretCheckWaitFunc)(Program* program);
// It's size in original code is 144 (0x8C) bytes due to the different
// size of `jmp_buf`.
typedef struct Program {
@ -162,10 +167,10 @@ typedef struct Program {
unsigned char* identifiers;
unsigned char* procedures;
jmp_buf env;
int field_70; // end time of timer (field_74 + wait time)
int field_74; // time when wait was called
unsigned int waitEnd; // end time of timer (field_74 + wait time)
unsigned int waitStart; // time when wait was called
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
InterpretCheckWaitFunc* checkWaitFunc;
int flags; // flags
int windowId;
bool exited;
@ -173,6 +178,7 @@ typedef struct Program {
ProgramStack* returnStackValues;
} Program;
typedef unsigned int(InterpretTimerFunc)();
typedef void OpcodeHandler(Program* program);
extern int _TimeOut;
@ -181,7 +187,7 @@ char* _interpretMangleName(char* s);
void _interpretOutputFunc(int (*func)(char*));
int _interpretOutput(const char* format, ...);
[[noreturn]] void programFatalError(const char* str, ...);
void programPopString(Program* program, opcode_t a2, int a3);
void _interpretDecStringRef(Program* program, opcode_t a2, int a3);
Program* programCreateByPath(const char* path);
char* programGetString(Program* program, opcode_t opcode, int offset);
char* programGetIdentifier(Program* program, int offset);
@ -189,10 +195,12 @@ int programPushString(Program* program, char* string);
void interpreterRegisterOpcodeHandlers();
void _interpretClose();
void _interpret(Program* program, int a2);
void _executeProc(Program* program, int procedure_index);
void _executeProc(Program* program, int procedureIndex);
int programFindProcedure(Program* prg, const char* name);
void _executeProcedure(Program* program, int procedure_index);
void _executeProcedure(Program* program, int procedureIndex);
void programListNodeCreate(Program* program);
void runProgram(Program* program);
Program* runScript(char* name);
void _updatePrograms();
void programListFree();
void interpreterRegisterOpcode(int opcode, OpcodeHandler* handler);

View File

@ -2025,7 +2025,7 @@ static void opMetarule3(Program* program)
}
break;
case METARULE3_MARK_SUBTILE:
result.integerValue = _wmSubTileMarkRadiusVisited(param1.integerValue, param2.integerValue, param3.integerValue);
result.integerValue = wmSubTileMarkRadiusVisited(param1.integerValue, param2.integerValue, param3.integerValue);
break;
case METARULE3_GET_KILL_COUNT:
result.integerValue = killsGetByType(param1.integerValue);
@ -2694,7 +2694,7 @@ static void opGameDialogSystemEnter(Program* program)
return;
}
if (_game_state_request(4) == -1) {
if (_game_state_request(GAME_STATE_4) == -1) {
return;
}

View File

@ -12,7 +12,6 @@
#include "select_file_list.h"
#include "sound.h"
#include "text_font.h"
#include "widget.h"
#include "window.h"
#include "window_manager_private.h"
@ -33,7 +32,13 @@ static void opPrintRect(Program* program);
static void opSelect(Program* program);
static void opDisplay(Program* program);
static void opDisplayRaw(Program* program);
static void sub_46222C(unsigned char* a1, unsigned char* a2, int a3, float a4, int a5);
static void _interpretFadePaletteBK(unsigned char* oldPalette, unsigned char* newPalette, int a3, float duration, bool shouldProcessBk);
static void interpretFadePalette(unsigned char* oldPalette, unsigned char* newPalette, int a3, float duration);
static int intlibGetFadeIn();
static void interpretFadeOut(float duration);
static void interpretFadeIn(float duration);
static void interpretFadeOutNoBK(float duration);
static void interpretFadeInNoBK(float duration);
static void opFadeIn(Program* program);
static void opFadeOut(Program* program);
static int intLibCheckMovie(Program* program);
@ -60,6 +65,8 @@ static int intLibCheckDialog(Program* program);
static void opSayEnd(Program* program);
static void opSayGetLastPos(Program* program);
static void opSayQuit(Program* program);
static int getTimeOut();
static void setTimeOut(int value);
static void opSayMessageTimeout(Program* program);
static void opSayMessage(Program* program);
static void opGotoXY(Program* program);
@ -388,9 +395,109 @@ void opDisplayRaw(Program* program)
}
// 0x46222C
void sub_46222C(unsigned char* a1, unsigned char* a2, int a3, float a4, int a5)
static void _interpretFadePaletteBK(unsigned char* oldPalette, unsigned char* newPalette, int a3, float duration, int shouldProcessBk)
{
// TODO: Incomplete.
unsigned int time;
unsigned int previousTime;
unsigned int delta;
int step;
int steps;
int index;
unsigned char palette[256 * 3];
time = _get_time();
previousTime = time;
steps = (int)duration;
step = 0;
delta = 0;
if (duration != 0.0) {
while (step < steps) {
if (delta != 0) {
for (index = 0; index < 768; index++) {
palette[index] = oldPalette[index] - (oldPalette[index] - newPalette[index]) * step / steps;
}
_setSystemPalette(palette);
previousTime = time;
step += delta;
}
if (shouldProcessBk) {
_process_bk();
}
time = _get_time();
delta = time - previousTime;
}
}
_setSystemPalette(newPalette);
}
// NOTE: Unused.
//
// 0x462330
static void interpretFadePalette(unsigned char* oldPalette, unsigned char* newPalette, int a3, float duration)
{
_interpretFadePaletteBK(oldPalette, newPalette, a3, duration, 1);
}
// NOTE: Unused.
static int intlibGetFadeIn()
{
return gIntLibIsPaletteFaded;
}
// NOTE: Inlined.
//
// 0x462348
static void interpretFadeOut(float duration)
{
int cursorWasHidden;
cursorWasHidden = cursorIsHidden();
mouseHideCursor();
_interpretFadePaletteBK(_getSystemPalette(), gIntLibFadePalette, 64, duration, 1);
if (!cursorWasHidden) {
mouseShowCursor();
}
}
// NOTE: Inlined.
//
// 0x462380
static void interpretFadeIn(float duration)
{
_interpretFadePaletteBK(gIntLibFadePalette, _cmap, 64, duration, 1);
}
// NOTE: Unused.
//
// 0x4623A4
static void interpretFadeOutNoBK(float duration)
{
int cursorWasHidden;
cursorWasHidden = cursorIsHidden();
mouseHideCursor();
_interpretFadePaletteBK(_getSystemPalette(), gIntLibFadePalette, 64, duration, 0);
if (!cursorWasHidden) {
mouseShowCursor();
}
}
// NOTE: Unused.
//
// 0x4623DC
static void interpretFadeInNoBK(float duration)
{
_interpretFadePaletteBK(gIntLibFadePalette, _cmap, 64, duration, 0);
}
// fadein
@ -403,7 +510,9 @@ void opFadeIn(Program* program)
_setSystemPalette(gIntLibFadePalette);
sub_46222C(gIntLibFadePalette, _cmap, 64, (float)data, 1);
// NOTE: Uninline.
interpretFadeIn((float)data);
gIntLibIsPaletteFaded = true;
program->flags &= ~PROGRAM_FLAG_0x20;
@ -420,7 +529,8 @@ void opFadeOut(Program* program)
bool cursorWasHidden = cursorIsHidden();
mouseHideCursor();
sub_46222C(_getSystemPalette(), gIntLibFadePalette, 64, (float)data, 1);
// NOTE: Uninline.
interpretFadeOut((float)data);
if (!cursorWasHidden) {
mouseShowCursor();
@ -466,8 +576,8 @@ void opPlayMovie(Program* program)
_selectWindowID(program->windowId);
program->flags |= PROGRAM_FLAG_0x10;
program->field_7C = intLibCheckMovie;
program->flags |= PROGRAM_IS_WAITING;
program->checkWaitFunc = intLibCheckMovie;
char* mangledFileName = _interpretMangleName(gIntLibPlayMovieFileName);
if (!_windowPlayMovie(mangledFileName)) {
@ -493,8 +603,8 @@ void opPlayMovieRect(Program* program)
_selectWindowID(program->windowId);
program->field_7C = intLibCheckMovie;
program->flags |= PROGRAM_FLAG_0x10;
program->checkWaitFunc = intLibCheckMovie;
program->flags |= PROGRAM_IS_WAITING;
char* mangledFileName = _interpretMangleName(gIntLibPlayMovieRectFileName);
if (!_windowPlayMovieRect(mangledFileName, x, y, width, height)) {
@ -834,8 +944,8 @@ void opSayEnd(Program* program)
program->flags &= ~PROGRAM_FLAG_0x20;
if (rc == -2) {
program->field_7C = intLibCheckDialog;
program->flags |= PROGRAM_FLAG_0x10;
program->checkWaitFunc = intLibCheckDialog;
program->flags |= PROGRAM_IS_WAITING;
}
}
@ -856,6 +966,22 @@ static void opSayQuit(Program* program)
}
}
// NOTE: Unused.
//
// 0x463828
static int getTimeOut()
{
return _TimeOut;
}
// NOTE: Unused.
//
// 0x463830
static void setTimeOut(int value)
{
_TimeOut = value;
}
// saymessagetimeout
// 0x463838
static void opSayMessageTimeout(Program* program)
@ -1307,7 +1433,7 @@ static void opSetFont(Program* program)
{
int data = programStackPopInteger(program);
if (!widgetSetFont(data)) {
if (!windowSetFont(data)) {
programFatalError("Error setting font");
}
}
@ -1318,7 +1444,7 @@ static void opSetTextFlags(Program* program)
{
int data = programStackPopInteger(program);
if (!widgetSetTextFlags(data)) {
if (!windowSetTextFlags(data)) {
programFatalError("Error setting text flags");
}
}
@ -1345,7 +1471,7 @@ static void opSetTextColor(Program* program)
float g = value[1].floatValue;
float b = value[0].floatValue;
if (!widgetSetTextColor(r, g, b)) {
if (!windowSetTextColor(r, g, b)) {
programFatalError("Error setting text color");
}
}
@ -1426,7 +1552,7 @@ static void opSetHighlightColor(Program* program)
float g = value[1].floatValue;
float b = value[0].floatValue;
if (!widgetSetHighlightColor(r, g, b)) {
if (!windowSetHighlightColor(r, g, b)) {
programFatalError("Error setting text highlight color");
}
}

View File

@ -599,7 +599,7 @@ void inventoryOpen()
_display_body(-1, INVENTORY_WINDOW_TYPE_NORMAL);
if (_game_state() == 5) {
if (_game_state() == GAME_STATE_5) {
break;
}

View File

@ -70,7 +70,11 @@ typedef enum MainMenuOption {
} MainMenuOption;
static bool falloutInit(int argc, char** argv);
static int main_reset_system();
static void main_exit_system();
static int _main_load_new(char* fname);
static int main_loadgame_new();
static void main_unload_new();
static void mainLoop(FpsLimiter& fpsLimiter);
static void _main_selfrun_exit();
static void _main_selfrun_record();
@ -85,6 +89,8 @@ static void mainMenuWindowHide(bool animate);
static void mainMenuWindowUnhide(bool animate);
static int _main_menu_is_enabled();
static int mainMenuWindowHandleEvents(FpsLimiter& fpsLimiter);
static int main_menu_fatal_error();
static void main_menu_play_sound(const char* fileName);
// 0x5194C8
static char _mainMap[] = "artemple.map";
@ -236,9 +242,13 @@ int falloutMain(int argc, char** argv)
mainLoop(fpsLimiter);
paletteFadeTo(gPaletteWhite);
objectHide(gDude, NULL);
_map_exit();
gameReset();
// NOTE: Uninline.
main_unload_new();
// NOTE: Uninline.
main_reset_system();
if (_main_show_death_scene != 0) {
showDeath();
_main_show_death_scene = 0;
@ -253,14 +263,10 @@ int falloutMain(int argc, char** argv)
int win = windowCreate(0, 0, screenGetWidth(), screenGetHeight(), _colorTable[0], WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
mainMenuWindowHide(true);
mainMenuWindowFree();
_game_user_wants_to_quit = 0;
gDude->flags &= ~OBJECT_FLAT;
_main_show_death_scene = 0;
objectShow(gDude, NULL);
mouseHideCursor();
_map_init();
gameMouseSetCursor(MOUSE_CURSOR_NONE);
mouseShowCursor();
// NOTE: Uninline.
main_loadgame_new();
colorPaletteLoad("color.pal");
paletteFadeTo(_cmap);
int loadGameRc = lsgLoadGame(LOAD_SAVE_MODE_FROM_MAIN_MENU);
@ -275,9 +281,13 @@ int falloutMain(int argc, char** argv)
if (win != -1) {
windowDestroy(win);
}
objectHide(gDude, NULL);
_map_exit();
gameReset();
// NOTE: Uninline.
main_unload_new();
// NOTE: Uninline.
main_reset_system();
if (_main_show_death_scene != 0) {
showDeath();
_main_show_death_scene = 0;
@ -324,9 +334,8 @@ int falloutMain(int argc, char** argv)
}
}
backgroundSoundDelete();
_main_selfrun_exit();
gameExit();
// NOTE: Uninline.
main_exit_system();
autorunMutexClose();
@ -351,6 +360,29 @@ static bool falloutInit(int argc, char** argv)
return true;
}
// NOTE: Inlined.
//
// 0x480D0C
static int main_reset_system()
{
gameReset();
return 1;
}
// NOTE: Inlined.
//
// 0x480D18
static void main_exit_system()
{
backgroundSoundDelete();
// NOTE: Uninline.
_main_selfrun_exit();
gameExit();
}
// 0x480D4C
static int _main_load_new(char* mapFileName)
{
@ -377,6 +409,34 @@ static int _main_load_new(char* mapFileName)
return 0;
}
// NOTE: Inlined.
//
// 0x480DF8
static int main_loadgame_new()
{
_game_user_wants_to_quit = 0;
_main_show_death_scene = 0;
gDude->flags &= ~OBJECT_FLAT;
objectShow(gDude, NULL);
mouseHideCursor();
_map_init();
gameMouseSetCursor(MOUSE_CURSOR_NONE);
mouseShowCursor();
return 0;
}
// 0x480E34
static void main_unload_new()
{
objectHide(gDude, NULL);
_map_exit();
}
// 0x480E48
static void mainLoop(FpsLimiter& fpsLimiter)
{
@ -461,14 +521,21 @@ static void _main_selfrun_record()
mainMenuWindowFree();
backgroundSoundDelete();
randomSeedPrerandom(0xBEEFFEED);
gameReset();
// NOTE: Uninline.
main_reset_system();
_proto_dude_init("premade\\combat.gcd");
_main_load_new(selfrunData.mapFileName);
selfrunRecordingLoop(&selfrunData);
paletteFadeTo(gPaletteWhite);
objectHide(gDude, NULL);
_map_exit();
gameReset();
// NOTE: Uninline.
main_unload_new();
// NOTE: Uninline.
main_reset_system();
mainMenuWindowInit();
if (_main_selfrun_list != NULL) {
@ -491,14 +558,21 @@ static void _main_selfrun_play()
mainMenuWindowFree();
backgroundSoundDelete();
randomSeedPrerandom(0xBEEFFEED);
gameReset();
// NOTE: Uninline.
main_reset_system();
_proto_dude_init("premade\\combat.gcd");
_main_load_new(selfrunData.mapFileName);
selfrunPlaybackLoop(&selfrunData);
paletteFadeTo(gPaletteWhite);
objectHide(gDude, NULL);
_map_exit();
gameReset();
// NOTE: Uninline.
main_unload_new();
// NOTE: Uninline.
main_reset_system();
mainMenuWindowInit();
}
@ -747,8 +821,8 @@ static int mainMenuWindowInit()
0,
WINDOW_HIDDEN | WINDOW_FLAG_0x04);
if (gMainMenuWindow == -1) {
mainMenuWindowFree();
return -1;
// NOTE: Uninline.
return main_menu_fatal_error();
}
gMainMenuWindowBuffer = windowGetBuffer(gMainMenuWindow);
@ -757,8 +831,8 @@ static int mainMenuWindowInit()
int backgroundFid = buildFid(OBJ_TYPE_INTERFACE, 140, 0, 0, 0);
gMainMenuBackgroundFrmData = artLockFrameData(backgroundFid, 0, 0, &gMainMenuBackgroundFrmHandle);
if (gMainMenuBackgroundFrmData == NULL) {
mainMenuWindowFree();
return -1;
// NOTE: Uninline.
return main_menu_fatal_error();
}
blitBufferToBuffer(gMainMenuBackgroundFrmData, 640, 480, 640, gMainMenuWindowBuffer, 640);
@ -803,16 +877,16 @@ static int mainMenuWindowInit()
fid = buildFid(OBJ_TYPE_INTERFACE, 299, 0, 0, 0);
gMainMenuButtonUpFrmData = artLockFrameData(fid, 0, 0, &gMainMenuButtonUpFrmHandle);
if (gMainMenuButtonUpFrmData == NULL) {
mainMenuWindowFree();
return -1;
// NOTE: Uninline.
return main_menu_fatal_error();
}
// menudown.frm
fid = buildFid(OBJ_TYPE_INTERFACE, 300, 0, 0, 0);
gMainMenuButtonDownFrmData = artLockFrameData(fid, 0, 0, &gMainMenuButtonDownFrmHandle);
if (gMainMenuButtonDownFrmData == NULL) {
mainMenuWindowFree();
return -1;
// NOTE: Uninline.
return main_menu_fatal_error();
}
for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) {
@ -827,8 +901,8 @@ static int mainMenuWindowInit()
for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) {
gMainMenuButtons[index] = buttonCreate(gMainMenuWindow, offsetX + 30, offsetY + 19 + index * 42 - index, 26, 26, -1, -1, 1111, gMainMenuButtonKeyBindings[index], gMainMenuButtonUpFrmData, gMainMenuButtonDownFrmData, 0, 32);
if (gMainMenuButtons[index] == -1) {
mainMenuWindowFree();
return -1;
// NOTE: Uninline.
return main_menu_fatal_error();
}
buttonSetMask(gMainMenuButtons[index], gMainMenuButtonUpFrmData);
@ -962,7 +1036,8 @@ static int mainMenuWindowHandleEvents(FpsLimiter& fpsLimiter)
for (int buttonIndex = 0; buttonIndex < MAIN_MENU_BUTTON_COUNT; buttonIndex++) {
if (keyCode == gMainMenuButtonKeyBindings[buttonIndex] || keyCode == toupper(gMainMenuButtonKeyBindings[buttonIndex])) {
soundPlayFile("nmselec1");
// NOTE: Uninline.
main_menu_play_sound("nmselec1");
rc = _return_values[buttonIndex];
@ -987,7 +1062,8 @@ static int mainMenuWindowHandleEvents(FpsLimiter& fpsLimiter)
continue;
} else if (keyCode == 1111) {
if (!(mouseGetEvent() & MOUSE_EVENT_LEFT_BUTTON_REPEAT)) {
soundPlayFile("nmselec0");
// NOTE: Uninline.
main_menu_play_sound("nmselec0");
}
continue;
}
@ -995,7 +1071,9 @@ static int mainMenuWindowHandleEvents(FpsLimiter& fpsLimiter)
if (keyCode == KEY_ESCAPE || _game_user_wants_to_quit == 3) {
rc = MAIN_MENU_EXIT;
soundPlayFile("nmselec1");
// NOTE: Uninline.
main_menu_play_sound("nmselec1");
break;
} else if (_game_user_wants_to_quit == 2) {
_game_user_wants_to_quit = 0;
@ -1016,3 +1094,21 @@ static int mainMenuWindowHandleEvents(FpsLimiter& fpsLimiter)
return rc;
}
// NOTE: Inlined.
//
// 0x481C88
static int main_menu_fatal_error()
{
mainMenuWindowFree();
return -1;
}
// NOTE: Inlined.
//
// 0x481C94
static void main_menu_play_sound(const char* fileName)
{
soundPlayFile(fileName);
}

View File

@ -31,6 +31,7 @@ static void* memoryBlockMallocImpl(size_t size);
static void* memoryBlockReallocImpl(void* ptr, size_t size);
static void memoryBlockFreeImpl(void* ptr);
static void memoryBlockPrintStats();
static void* mem_prep_block(void* block, size_t size);
static void memoryBlockValidate(void* block);
// 0x51DED0
@ -81,12 +82,8 @@ static void* memoryBlockMallocImpl(size_t size)
unsigned char* block = (unsigned char*)malloc(size);
if (block != NULL) {
MemoryBlockHeader* header = (MemoryBlockHeader*)block;
header->size = size;
header->guard = MEMORY_BLOCK_HEADER_GUARD;
MemoryBlockFooter* footer = (MemoryBlockFooter*)(block + size - sizeof(MemoryBlockFooter));
footer->guard = MEMORY_BLOCK_FOOTER_GUARD;
// NOTE: Uninline.
ptr = mem_prep_block(block, size);
gMemoryBlocksCurrentCount++;
if (gMemoryBlocksCurrentCount > gMemoryBlockMaximumCount) {
@ -97,8 +94,6 @@ static void* memoryBlockMallocImpl(size_t size)
if (gMemoryBlocksCurrentSize > gMemoryBlocksMaximumSize) {
gMemoryBlocksMaximumSize = gMemoryBlocksCurrentSize;
}
ptr = block + sizeof(MemoryBlockHeader);
}
}
@ -130,19 +125,13 @@ static void* memoryBlockReallocImpl(void* ptr, size_t size)
unsigned char* newBlock = (unsigned char*)realloc(block, size);
if (newBlock != NULL) {
MemoryBlockHeader* newHeader = (MemoryBlockHeader*)newBlock;
newHeader->size = size;
newHeader->guard = MEMORY_BLOCK_HEADER_GUARD;
MemoryBlockFooter* newFooter = (MemoryBlockFooter*)(newBlock + size - sizeof(MemoryBlockFooter));
newFooter->guard = MEMORY_BLOCK_FOOTER_GUARD;
gMemoryBlocksCurrentSize += size;
if (gMemoryBlocksCurrentSize > gMemoryBlocksMaximumSize) {
gMemoryBlocksMaximumSize = gMemoryBlocksCurrentSize;
}
ptr = newBlock + sizeof(MemoryBlockHeader);
// NOTE: Uninline.
ptr = mem_prep_block(newBlock, size);
} else {
if (size != 0) {
gMemoryBlocksCurrentSize += oldSize;
@ -194,6 +183,24 @@ static void memoryBlockPrintStats()
}
}
// NOTE: Inlined.
//
// 0x4C5CC4
static void* mem_prep_block(void* block, size_t size)
{
MemoryBlockHeader* header;
MemoryBlockFooter* footer;
header = (MemoryBlockHeader*)block;
header->guard = MEMORY_BLOCK_HEADER_GUARD;
header->size = size;
footer = (MemoryBlockFooter*)((unsigned char*)block + size - sizeof(*footer));
footer->guard = MEMORY_BLOCK_FOOTER_GUARD;
return (unsigned char*)block + sizeof(*header);
}
// Validates integrity of the memory block.
//
// [block] is a pointer to the the memory block itself, not it's data.

View File

@ -744,7 +744,7 @@ static void _script_chk_timed_events()
v1 = true;
}
if (_game_state() != 4) {
if (_game_state() != GAME_STATE_4) {
if (getTicksBetween(v0, _last_light_time) >= 30000) {
_last_light_time = v0;
scriptsExecMapUpdateScripts(SCRIPT_PROC_MAP_UPDATE);
@ -1308,7 +1308,8 @@ int scriptExecProc(int sid, int proc)
}
script->action = 0;
programListNodeCreate(program);
// NOTE: Uninline.
runProgram(program);
_interpret(program, -1);
}

View File

@ -48,6 +48,7 @@ typedef struct SkillDescription {
static void _show_skill_use_messages(Object* obj, int skill, Object* a3, int a4, int a5);
static int skillGetFreeUsageSlot(int skill);
static int skill_use_slot_clear();
// Damage flags which can be repaired using "Repair" skill.
//
@ -152,7 +153,8 @@ int skillsInit()
gTaggedSkills[index] = -1;
}
memset(_timesSkillUsed, 0, sizeof(_timesSkillUsed));
// NOTE: Uninline.
skill_use_slot_clear();
return 0;
}
@ -164,7 +166,8 @@ void skillsReset()
gTaggedSkills[index] = -1;
}
memset(_timesSkillUsed, 0, sizeof(_timesSkillUsed));
// NOTE: Uninline.
skill_use_slot_clear();
}
// 0x4AA478
@ -1172,6 +1175,15 @@ int skillUpdateLastUse(int skill)
return 0;
}
// NOTE: Inlined.
//
// 0x4ABF24
int skill_use_slot_clear()
{
memset(_timesSkillUsed, 0, sizeof(_timesSkillUsed));
return 0;
}
// 0x4ABF3C
int skillsUsageSave(File* stream)
{

View File

@ -1,17 +1,6 @@
#include "widget.h"
#include "color.h"
#include "text_font.h"
#include "window.h"
static void _showRegion(int a1);
static unsigned char widgetGetHighlightColor();
// 0x50EB1C
static const float flt_50EB1C = 31.0f;
// 0x50EB20
static const float flt_50EB20 = 31.0f;
// 0x66E6A0
static int _updateRegions[32];
@ -34,65 +23,6 @@ int _update_widgets()
return 1;
}
// 0x4B6120
int widgetGetFont()
{
return gWidgetFont;
}
// 0x4B6128
int widgetSetFont(int a1)
{
gWidgetFont = a1;
fontSetCurrent(a1);
return 1;
}
// 0x4B6160
int widgetGetTextFlags()
{
return gWidgetTextFlags;
}
// 0x4B6168
int widgetSetTextFlags(int a1)
{
gWidgetTextFlags = a1;
return 1;
}
// 0x4B6174
unsigned char widgetGetTextColor()
{
return _colorTable[_currentTextColorB | (_currentTextColorG << 5) | (_currentTextColorR << 10)];
}
// 0x4B6198
unsigned char widgetGetHighlightColor()
{
return _colorTable[_currentHighlightColorB | (_currentHighlightColorG << 5) | (_currentHighlightColorR << 10)];
}
// 0x4B61BC
int widgetSetTextColor(float a1, float a2, float a3)
{
_currentTextColorR = (int)(a1 * flt_50EB1C);
_currentTextColorG = (int)(a2 * flt_50EB1C);
_currentTextColorB = (int)(a3 * flt_50EB1C);
return 1;
}
// 0x4B6208
int widgetSetHighlightColor(float a1, float a2, float a3)
{
_currentHighlightColorR = (int)(a1 * flt_50EB20);
_currentHighlightColorG = (int)(a2 * flt_50EB20);
_currentHighlightColorB = (int)(a3 * flt_50EB20);
return 1;
}
// 0x4B5998
void sub_4B5998(int win)
{

View File

@ -2,13 +2,6 @@
#define WIDGET_H
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 */

View File

@ -152,10 +152,10 @@ static int _yres;
// Highlight color (maybe r).
//
// 0x672D8C
int _currentHighlightColorR;
static int _currentHighlightColorR;
// 0x672D90
int gWidgetFont;
static int gWidgetFont;
// 0x672D98
ButtonCallback* off_672D98;
@ -166,30 +166,101 @@ ButtonCallback* off_672D9C;
// Text color (maybe g).
//
// 0x672DA0
int _currentTextColorG;
static int _currentTextColorG;
// text color (maybe b).
//
// 0x672DA4
int _currentTextColorB;
static int _currentTextColorB;
// 0x672DA8
int gWidgetTextFlags;
static int gWidgetTextFlags;
// Text color (maybe r)
//
// 0x672DAC
int _currentTextColorR;
static int _currentTextColorR;
// highlight color (maybe g)
//
// 0x672DB0
int _currentHighlightColorG;
static int _currentHighlightColorG;
// Highlight color (maybe b).
//
// 0x672DB4
int _currentHighlightColorB;
static int _currentHighlightColorB;
// 0x4B6120
int windowGetFont()
{
return gWidgetFont;
}
// 0x4B6128
int windowSetFont(int a1)
{
gWidgetFont = a1;
fontSetCurrent(a1);
return 1;
}
// NOTE: Unused.
//
// 0x4B6138
void windowResetTextAttributes()
{
// NOTE: Uninline.
windowSetTextColor(1.0, 1.0, 1.0);
// NOTE: Uninline.
windowSetTextFlags(0x2000000 | 0x10000);
}
// 0x4B6160
int windowGetTextFlags()
{
return gWidgetTextFlags;
}
// 0x4B6168
int windowSetTextFlags(int a1)
{
gWidgetTextFlags = a1;
return 1;
}
// 0x4B6174
unsigned char windowGetTextColor()
{
return _colorTable[_currentTextColorB | (_currentTextColorG << 5) | (_currentTextColorR << 10)];
}
// 0x4B6198
unsigned char windowGetHighlightColor()
{
return _colorTable[_currentHighlightColorB | (_currentHighlightColorG << 5) | (_currentHighlightColorR << 10)];
}
// 0x4B61BC
int windowSetTextColor(float r, float g, float b)
{
_currentTextColorR = (int)(r * 31.0);
_currentTextColorG = (int)(g * 31.0);
_currentTextColorB = (int)(b * 31.0);
return 1;
}
// 0x4B6208
int windowSetHighlightColor(float r, float g, float b)
{
_currentHighlightColorR = (int)(r * 31.0);
_currentHighlightColorG = (int)(g * 31.0);
_currentHighlightColorB = (int)(b * 31.0);
return 1;
}
// 0x4B62E4
bool _checkRegion(int windowIndex, int mouseX, int mouseY, int mouseEvent)
@ -750,7 +821,7 @@ int _windowOutput(char* string)
int x = (int)(managedWindow->field_44 * managedWindow->field_54);
int y = (int)(managedWindow->field_48 * managedWindow->field_58);
// NOTE: Uses `add` at 0x4B810E, not bitwise `or`.
int flags = widgetGetTextColor() + widgetGetTextFlags();
int flags = windowGetTextColor() + windowGetTextFlags();
windowDrawText(managedWindow->window, string, 0, x, y, flags);
return 1;
@ -1067,7 +1138,7 @@ bool _windowPrintRect(char* string, int a2, int textAlignment)
int height = windowGetHeight(managedWindow->window);
int x = managedWindow->field_44;
int y = managedWindow->field_48;
int flags = widgetGetTextColor() | 0x2000000;
int flags = windowGetTextColor() | 0x2000000;
_windowWrapLineWithSpacing(managedWindow->window, string, width, height, x, y, flags, textAlignment, 0);
return true;
@ -1077,7 +1148,7 @@ bool _windowPrintRect(char* string, int a2, int textAlignment)
bool _windowFormatMessage(char* string, int x, int y, int width, int height, int textAlignment)
{
ManagedWindow* managedWindow = &(gManagedWindows[gCurrentManagedWindowIndex]);
int flags = widgetGetTextColor() | 0x2000000;
int flags = windowGetTextColor() | 0x2000000;
_windowWrapLineWithSpacing(managedWindow->window, string, width, height, x, y, flags, textAlignment, 0);
return true;
@ -1812,7 +1883,7 @@ bool _windowAddButtonTextWithOffsets(const char* buttonName, const char* text, i
text,
normalImageWidth,
normalImageWidth,
widgetGetTextColor() + widgetGetTextFlags());
windowGetTextColor() + windowGetTextFlags());
blitBufferToBufferTrans(buffer,
normalImageWidth,
@ -1860,7 +1931,7 @@ bool _windowAddButtonTextWithOffsets(const char* buttonName, const char* text, i
text,
pressedImageWidth,
pressedImageWidth,
widgetGetTextColor() + widgetGetTextFlags());
windowGetTextColor() + windowGetTextFlags());
blitBufferToBufferTrans(buffer,
pressedImageWidth,

View File

@ -34,15 +34,15 @@ typedef enum ManagedButtonRightMouseEvent {
MANAGED_BUTTON_RIGHT_MOUSE_EVENT_COUNT,
} ManagedButtonRightMouseEvent;
extern int _currentHighlightColorR;
extern int gWidgetFont;
extern int _currentTextColorG;
extern int _currentTextColorB;
extern int gWidgetTextFlags;
extern int _currentTextColorR;
extern int _currentHighlightColorG;
extern int _currentHighlightColorB;
int windowGetFont();
int windowSetFont(int a1);
void windowResetTextAttributes();
int windowGetTextFlags();
int windowSetTextFlags(int a1);
unsigned char windowGetTextColor();
unsigned char windowGetHighlightColor();
int windowSetTextColor(float a1, float a2, float a3);
int windowSetHighlightColor(float a1, float a2, float a3);
bool _checkRegion(int windowIndex, int mouseX, int mouseY, int mouseEvent);
bool _windowCheckRegion(int windowIndex, int mouseX, int mouseY, int mouseEvent);
bool _windowRefreshRegions();

View File

@ -35,6 +35,7 @@ static Button* buttonCreateInternal(int win, int x, int y, int width, int height
static int _GNW_check_buttons(Window* window, int* out_a2);
static bool _button_under_mouse(Button* button, Rect* rect);
static void buttonFree(Button* ptr);
static int button_new_id();
static int _win_group_check_buttons(int a1, int* a2, int a3, void (*a4)(int));
static int _button_check_group(Button* button);
static void _button_draw(Button* button, Window* window, unsigned char* data, int a4, Rect* a5, int a6);
@ -1642,10 +1643,8 @@ Button* buttonCreateInternal(int win, int x, int y, int width, int height, int m
}
}
int buttonId = 1;
while (buttonGetButton(buttonId, NULL) != NULL) {
buttonId++;
}
// NOTE: Uninline.
int buttonId = button_new_id();
button->id = buttonId;
button->flags = flags;
@ -2183,6 +2182,21 @@ void buttonFree(Button* button)
internal_free(button);
}
// NOTE: Inlined.
//
// 0x4D9458
static int button_new_id()
{
int btn;
btn = 1;
while (buttonGetButton(btn, NULL) != NULL) {
btn++;
}
return btn;
}
// 0x4D9474
int buttonEnable(int btn)
{

View File

@ -908,6 +908,7 @@ static int gEncounterTablesLength;
static bool gTownMapHotkeysFix;
static double gGameTimeIncRemainder = 0.0;
static void wmSetFlags(int* flagsPtr, int flag, int value);
static int _wmGenDataInit();
static int _wmGenDataReset();
static int _wmWorldMapSaveTempData();
@ -950,6 +951,7 @@ static int _wmMatchEntranceElevFromMap(int cityIndex, int map, int elevation, in
static int _wmMatchAreaFromMap(int a1, int* out_a2);
static int _wmWorldMapFunc(int a1);
static int _wmInterfaceCenterOnParty();
static void wmCheckGameEvents();
static int _wmRndEncounterOccurred();
static int _wmPartyFindCurSubTile();
static int _wmFindCurSubTileFromPos(int x, int y, SubtileInfo** subtile);
@ -967,11 +969,15 @@ static void _wmPartyInitWalking(int x, int y);
static void worldmapPerformTravel();
static void _wmInterfaceScrollTabsStart(int a1);
static void _wmInterfaceScrollTabsStop();
static void wmInterfaceScrollTabsUpdate();
static int worldmapWindowInit();
static int worldmapWindowFree();
static int wmInterfaceScroll(int dx, int dy, bool* successPtr);
static int worldmapWindowScroll(int a1, int a2, int a3, int a4, bool* a5, bool a6);
static void worldmapWindowHandleMouseScrolling();
static int _wmMarkSubTileOffsetVisitedFunc(int a1, int a2, int a3, int a4, int a5, int a6);
static int wmMarkSubTileOffsetVisited(int tile, int subtileX, int subtileY, int offsetX, int offsetY);
static int wmMarkSubTileOffsetKnown(int tile, int subtileX, int subtileY, int offsetX, int offsetY);
static int wmMarkSubTileOffsetVisitedFunc(int tile, int subtileX, int subtileY, int offsetX, int offsetY, int subtileState);
static void _wmMarkSubTileRadiusVisited(int x, int y);
static int _wmTileGrabArt(int tile_index);
static int worldmapWindowRefresh();
@ -982,6 +988,8 @@ static void worldmapWindowDimRect(unsigned char* dest, int width, int height, in
static int worldmapWindowDimSubtile(TileInfo* tileInfo, int a2, int a3, int a4, int a5, int a6);
static int _wmDrawCursorStopped();
static bool _wmCursorIsVisible();
static int wmGetAreaName(CityInfo* city, char* name);
static int wmAreaMarkVisited(int cityIndex);
static void _wmMarkAllSubTiles(int a1);
static int worldmapCityMapViewSelect(int* mapIndexPtr);
static int worldmapCityMapViewInit();
@ -993,7 +1001,9 @@ static void worldmapWindowRenderCarFuelBar();
static int worldmapRenderQuickDestinations();
static int _wmMakeTabsLabelList(int** out_cities, int* out_len);
static int worldmapCompareCitiesByName(const void* a1, const void* a2);
static int wmFreeTabsLabelList(int** quickDestinationsListPtr, int* quickDestinationsLengthPtr);
static void worldmapWindowRenderDial(bool shouldRefreshWindow);
static void wmInterfaceDialSyncTime(bool shouldRefreshWindow);
static int _wmAreaFindFirstValidMap(int* out_a1);
static inline bool cityIsValid(int city)
@ -1001,6 +1011,16 @@ static inline bool cityIsValid(int city)
return city >= 0 && city < gCitiesLength;
}
// 0x4BC890
static void wmSetFlags(int* flagsPtr, int flag, int value)
{
if (value) {
*flagsPtr |= flag;
} else {
*flagsPtr &= ~flag;
}
}
// wmWorldMap_init
// 0x4BC89C
int worldmapInit()
@ -2906,11 +2926,8 @@ int _wmMapInit()
return -1;
}
if (num) {
map->flags |= MAP_SAVED;
} else {
map->flags &= ~MAP_SAVED;
}
// NOTE: Uninline.
wmSetFlags(&(map->flags), MAP_SAVED, num);
}
if (configGetString(&config, section, "dead_bodies_age", &str)) {
@ -2918,11 +2935,8 @@ int _wmMapInit()
return -1;
}
if (num) {
map->flags |= MAP_DEAD_BODIES_AGE;
} else {
map->flags &= ~MAP_DEAD_BODIES_AGE;
}
// NOTE: Uninline.
wmSetFlags(&(map->flags), MAP_DEAD_BODIES_AGE, num);
}
if (configGetString(&config, section, "can_rest_here", &str)) {
@ -2930,31 +2944,22 @@ int _wmMapInit()
return -1;
}
if (num) {
map->flags |= MAP_CAN_REST_ELEVATION_0;
} else {
map->flags &= ~MAP_CAN_REST_ELEVATION_0;
}
// NOTE: Uninline.
wmSetFlags(&(map->flags), MAP_CAN_REST_ELEVATION_0, num);
if (strParseStrFromList(&str, &num, _wmYesNoStrs, 2) == -1) {
return -1;
}
if (num) {
map->flags |= MAP_CAN_REST_ELEVATION_1;
} else {
map->flags &= ~MAP_CAN_REST_ELEVATION_1;
}
// NOTE: Uninline.
wmSetFlags(&(map->flags), MAP_CAN_REST_ELEVATION_1, num);
if (strParseStrFromList(&str, &num, _wmYesNoStrs, 2) == -1) {
return -1;
}
if (num) {
map->flags |= MAP_CAN_REST_ELEVATION_2;
} else {
map->flags &= ~MAP_CAN_REST_ELEVATION_2;
}
// NOTE: Uninline.
wmSetFlags(&(map->flags), MAP_CAN_REST_ELEVATION_2, num);
}
if (configGetString(&config, section, "pipboy_active", &str)) {
@ -2962,11 +2967,8 @@ int _wmMapInit()
return -1;
}
if (num) {
map->flags |= MAP_PIPBOY_ACTIVE;
} else {
map->flags &= ~MAP_PIPBOY_ACTIVE;
}
// NOTE: Uninline.
wmSetFlags(&(map->flags), MAP_PIPBOY_ACTIVE, num);
}
// SFALL: Pip-boy automaps patch.
@ -3129,7 +3131,8 @@ int _wmMapMarkVisited(int mapIndex)
return -1;
}
_wmAreaMarkVisitedState(cityIndex, 2);
// NOTE: Uninline.
wmAreaMarkVisited(cityIndex);
return 0;
}
@ -3257,7 +3260,8 @@ int _wmWorldMapFunc(int a1)
showQuitConfirmationDialog();
}
_scriptsCheckGameEvents(NULL, gWorldmapWindow);
// NOTE: Uninline.
wmCheckGameEvents();
if (_game_user_wants_to_quit != 0) {
break;
@ -3420,20 +3424,8 @@ int _wmWorldMapFunc(int a1)
}
}
if (_tabsOffset) {
_LastTabsYOffset += _tabsOffset;
worldmapWindowRenderChrome(true);
if (_tabsOffset > -1) {
if (dword_672F54 <= _LastTabsYOffset) {
_wmInterfaceScrollTabsStop();
}
} else {
if (dword_672F54 >= _LastTabsYOffset) {
_wmInterfaceScrollTabsStop();
}
}
}
// NOTE: Uninline.
wmInterfaceScrollTabsUpdate();
if (keyCode == KEY_UPPERCASE_T || keyCode == KEY_LOWERCASE_T) {
if (!gWorldmapIsTravelling && _WorldMapCurrArea != -1) {
@ -3455,13 +3447,17 @@ int _wmWorldMapFunc(int a1)
} else if (keyCode == KEY_HOME) {
_wmInterfaceCenterOnParty();
} else if (keyCode == KEY_ARROW_UP) {
worldmapWindowScroll(20, 20, 0, -1, 0, 1);
// NOTE: Uninline.
wmInterfaceScroll(0, -1, NULL);
} else if (keyCode == KEY_ARROW_LEFT) {
worldmapWindowScroll(20, 20, -1, 0, 0, 1);
// NOTE: Uninline.
wmInterfaceScroll(-1, 0, NULL);
} else if (keyCode == KEY_ARROW_DOWN) {
worldmapWindowScroll(20, 20, 0, 1, 0, 1);
// NOTE: Uninline.
wmInterfaceScroll(0, 1, NULL);
} else if (keyCode == KEY_ARROW_RIGHT) {
worldmapWindowScroll(20, 20, 1, 0, 0, 1);
// NOTE: Uninline.
wmInterfaceScroll(1, 0, NULL);
} else if (keyCode == KEY_CTRL_ARROW_UP) {
_wmInterfaceScrollTabsStart(-27);
} else if (keyCode == KEY_CTRL_ARROW_DOWN) {
@ -3564,6 +3560,14 @@ int _wmInterfaceCenterOnParty()
return 0;
}
// NOTE: Inlined.
//
// 0x4C0624
static void wmCheckGameEvents()
{
_scriptsCheckGameEvents(NULL, gWorldmapWindow);
}
// 0x4C0634
int _wmRndEncounterOccurred()
{
@ -4442,14 +4446,8 @@ bool _wmGameTimeIncrement(int ticksToAdd)
gameTimeAddTicks(v1);
int hour = gameTimeGetHour() / 100;
int frameCount = artGetFrameCount(gWorldmapDialFrm);
int frame = (hour + 12) % frameCount;
if (gWorldmapDialFrmCurrentFrame != frame) {
gWorldmapDialFrmCurrentFrame = frame;
worldmapWindowRenderDial(true);
}
// NOTE: Uninline.
wmInterfaceDialSyncTime(true);
worldmapWindowRenderDate(true);
@ -4672,23 +4670,8 @@ void _wmInterfaceScrollTabsStart(int a1)
L11:
if (!_tabsOffset) {
return;
}
_LastTabsYOffset += _tabsOffset;
worldmapWindowRenderChrome(true);
if (_tabsOffset > -1) {
if (dword_672F54 > _LastTabsYOffset) {
return;
}
} else if (dword_672F54 < _LastTabsYOffset) {
return;
}
_wmInterfaceScrollTabsStop();
// NOTE: Uninline.
wmInterfaceScrollTabsUpdate();
}
// 0x4C2270
@ -4703,6 +4686,29 @@ void _wmInterfaceScrollTabsStop()
}
}
// NOTE: Inlined.
//
// 0x4C2290
static void wmInterfaceScrollTabsUpdate()
{
if (_tabsOffset != 0) {
_LastTabsYOffset += _tabsOffset;
worldmapWindowRenderChrome(1);
if (_tabsOffset >= 0) {
if (dword_672F54 <= _LastTabsYOffset) {
// NOTE: Uninline.
_wmInterfaceScrollTabsStop();
}
} else {
if (dword_672F54 >= _LastTabsYOffset) {
// NOTE: Uninline.
_wmInterfaceScrollTabsStop();
}
}
}
}
// 0x4C2324
int worldmapWindowInit()
{
@ -5265,12 +5271,8 @@ int worldmapWindowFree()
fontSetCurrent(_fontnum);
if (gQuickDestinations != NULL) {
internal_free(gQuickDestinations);
gQuickDestinations = NULL;
}
gQuickDestinationsLength = 0;
// NOTE: Uninline.
wmFreeTabsLabelList(&gQuickDestinations, &gQuickDestinationsLength);
_wmInterfaceWasInitialized = 0;
@ -5279,6 +5281,14 @@ int worldmapWindowFree()
return 0;
}
// NOTE: Inlined.
//
// 0x4C31E8
static int wmInterfaceScroll(int dx, int dy, bool* successPtr)
{
return worldmapWindowScroll(20, 20, dx, dy, successPtr, 1);
}
// FIXME: There is small bug in this function. There is [success] flag returned
// by reference so that calling code can update scrolling mouse cursor to invalid
// range. It works OK on straight directions. But in diagonals when scrolling in
@ -5407,7 +5417,8 @@ void worldmapWindowHandleMouseScrolling()
unsigned int tick = _get_bk_time();
if (getTicksBetween(tick, _lastTime_2) > 50) {
_lastTime_2 = _get_bk_time();
worldmapWindowScroll(20, 20, dx, dy, &_couldScroll, true);
// NOTE: Uninline.
wmInterfaceScroll(dx, dy, &_couldScroll);
}
if (!_couldScroll) {
@ -5424,59 +5435,75 @@ void worldmapWindowHandleMouseScrolling()
}
}
// 0x4C3434
int _wmMarkSubTileOffsetVisitedFunc(int a1, int a2, int a3, int a4, int a5, int a6)
// NOTE: Inlined.
//
// 0x4C340C
static int wmMarkSubTileOffsetVisited(int tile, int subtileX, int subtileY, int offsetX, int offsetY)
{
int v7;
int v8;
int v9;
int* v;
return wmMarkSubTileOffsetVisitedFunc(tile, subtileX, subtileY, offsetX, offsetY, SUBTILE_STATE_VISITED);
}
v7 = a2 + a4;
v8 = a1;
v9 = a3 + a5;
// NOTE: Inlined.
//
// 0x4C3420
static int wmMarkSubTileOffsetKnown(int tile, int subtileX, int subtileY, int offsetX, int offsetY)
{
return wmMarkSubTileOffsetVisitedFunc(tile, subtileX, subtileY, offsetX, offsetY, SUBTILE_STATE_KNOWN);
}
if (v7 >= 0) {
if (v7 >= 7) {
if (a1 % gWorldmapGridWidth == gWorldmapGridWidth - 1) {
// 0x4C3434
static int wmMarkSubTileOffsetVisitedFunc(int tile, int subtileX, int subtileY, int offsetX, int offsetY, int subtileState)
{
int actualTile;
int actualSubtileX;
int actualSubtileY;
TileInfo* tileInfo;
SubtileInfo* subtileInfo;
actualSubtileX = subtileX + offsetX;
actualTile = tile;
actualSubtileY = subtileY + offsetY;
if (actualSubtileX >= 0) {
if (actualSubtileX >= SUBTILE_GRID_WIDTH) {
if (tile % gWorldmapGridWidth == gWorldmapGridWidth - 1) {
return -1;
}
v8 = a1 + 1;
v7 %= 7;
actualTile = tile + 1;
actualSubtileX %= SUBTILE_GRID_WIDTH;
}
} else {
if (!(a1 % gWorldmapGridWidth)) {
if (!(tile % gWorldmapGridWidth)) {
return -1;
}
v7 += 7;
v8 = a1 - 1;
actualSubtileX += SUBTILE_GRID_WIDTH;
actualTile = tile - 1;
}
if (v9 >= 0) {
if (v9 >= 6) {
if (v8 > gWorldmapTilesLength - gWorldmapGridWidth - 1) {
if (actualSubtileY >= 0) {
if (actualSubtileY >= SUBTILE_GRID_HEIGHT) {
if (actualTile > gWorldmapTilesLength - gWorldmapGridWidth - 1) {
return -1;
}
v8 += gWorldmapGridWidth;
v9 %= 6;
actualTile += gWorldmapGridWidth;
actualSubtileY %= SUBTILE_GRID_HEIGHT;
}
} else {
if (v8 < gWorldmapGridWidth) {
if (actualTile < gWorldmapGridWidth) {
return -1;
}
v9 += 6;
v8 -= gWorldmapGridWidth;
actualSubtileY += SUBTILE_GRID_HEIGHT;
actualTile -= gWorldmapGridWidth;
}
TileInfo* tile = &(gWorldmapTiles[v8]);
SubtileInfo* subtile = &(tile->subtiles[v9][v7]);
v = &(subtile->state);
if (a6 != 1 || *v == 0) {
*v = a6;
tileInfo = &(gWorldmapTiles[actualTile]);
subtileInfo = &(tileInfo->subtiles[actualSubtileY][actualSubtileX]);
if (subtileState != SUBTILE_STATE_KNOWN || subtileInfo->state == SUBTILE_STATE_UNKNOWN) {
subtileInfo->state = subtileState;
}
return 0;
@ -5491,43 +5518,50 @@ void _wmMarkSubTileRadiusVisited(int x, int y)
radius = 2;
}
_wmSubTileMarkRadiusVisited(x, y, radius);
wmSubTileMarkRadiusVisited(x, y, radius);
}
// Mark worldmap tile as visible?/visited?
//
// 0x4C35A8
int _wmSubTileMarkRadiusVisited(int x, int y, int radius)
int wmSubTileMarkRadiusVisited(int x, int y, int radius)
{
int v4, v5;
int tile;
int subtileX;
int subtileY;
int offsetX;
int offsetY;
SubtileInfo* subtile;
int tile = x / WM_TILE_WIDTH % gWorldmapGridWidth + y / WM_TILE_HEIGHT * gWorldmapGridWidth;
v4 = x % WM_TILE_WIDTH / WM_SUBTILE_SIZE;
v5 = y % WM_TILE_HEIGHT / WM_SUBTILE_SIZE;
tile = x / WM_TILE_WIDTH % gWorldmapGridWidth + y / WM_TILE_HEIGHT * gWorldmapGridWidth;
subtileX = x % WM_TILE_WIDTH / WM_SUBTILE_SIZE;
subtileY = y % WM_TILE_HEIGHT / WM_SUBTILE_SIZE;
for (int i = -radius; i <= radius; i++) {
for (int v6 = -radius; v6 <= radius; v6++) {
_wmMarkSubTileOffsetVisitedFunc(tile, v4, v5, v6, i, SUBTILE_STATE_KNOWN);
for (offsetY = -radius; offsetY <= radius; offsetY++) {
for (offsetX = -radius; offsetX <= radius; offsetX++) {
// NOTE: Uninline.
wmMarkSubTileOffsetKnown(tile, subtileX, subtileY, offsetX, offsetY);
}
}
SubtileInfo* subtile = &(gWorldmapTiles[tile].subtiles[v5][v4]);
subtile = &(gWorldmapTiles[tile].subtiles[subtileY][subtileX]);
subtile->state = SUBTILE_STATE_VISITED;
switch (subtile->field_4) {
case 2:
while (v5-- > 0) {
_wmMarkSubTileOffsetVisitedFunc(tile, v4, 0, v5, 0, SUBTILE_STATE_VISITED);
while (subtileY-- > 0) {
// NOTE: Uninline.
wmMarkSubTileOffsetVisited(tile, subtileX, subtileY, 0, 0);
}
break;
case 4:
while (v4-- > -1) {
_wmMarkSubTileOffsetVisitedFunc(tile, v4, 0, v5, 0, SUBTILE_STATE_VISITED);
while (subtileX-- >= 0) {
// NOTE: Uninline.
wmMarkSubTileOffsetVisited(tile, subtileX, subtileY, 0, 0);
}
if (tile % gWorldmapGridWidth > 0) {
for (int i = 0; i < 7; i++) {
_wmMarkSubTileOffsetVisitedFunc(tile - 1, i + 1, v5, 0, 0, SUBTILE_STATE_VISITED);
for (subtileX = 0; subtileX < SUBTILE_GRID_WIDTH; subtileX++) {
// NOTE: Uninline.
wmMarkSubTileOffsetVisited(tile - 1, subtileX, subtileY, 0, 0);
}
}
break;
@ -5818,18 +5852,20 @@ int worldmapWindowRenderCity(CityInfo* city, CitySizeDescription* citySizeDescri
int maxY = 464 - fontGetLineHeight();
if (nameY < maxY) {
MessageListItem messageListItem;
const char* name;
char name[40];
if (_wmAreaIsKnown(city->field_28)) {
name = getmsg(&gMapMessageList, &messageListItem, 1500 + city->field_28);
// NOTE: Uninline.
wmGetAreaName(city, name);
} else {
name = getmsg(&gWorldmapMessageList, &messageListItem, 1004);
strncpy(name, getmsg(&gWorldmapMessageList, &messageListItem, 1004), 40);
}
char text[40];
strncpy(text, name, 40);
int width = fontGetStringWidth(text);
fontDrawText(dest + WM_WINDOW_WIDTH * nameY + x + citySizeDescription->width / 2 - width / 2, text, width, WM_WINDOW_WIDTH, _colorTable[992]);
int width = fontGetStringWidth(name);
fontDrawText(dest + WM_WINDOW_WIDTH * nameY + x + citySizeDescription->width / 2 - width / 2,
name,
width,
WM_WINDOW_WIDTH,
_colorTable[992]);
}
return 0;
@ -5957,6 +5993,19 @@ bool _wmCursorIsVisible()
&& _world_ypos < gWorldmapOffsetY + WM_VIEW_HEIGHT;
}
// NOTE: Inlined.
//
// 0x4C44D8
static int wmGetAreaName(CityInfo* city, char* name)
{
MessageListItem messageListItem;
getmsg(&gMapMessageList, &messageListItem, city->field_28 + 1500);
strncpy(name, messageListItem.text, 40);
return 0;
}
// Copy city short name.
//
// 0x4C450C
@ -6027,6 +6076,12 @@ bool _wmMapIsKnown(int mapIndex)
return true;
}
// 0x4C4624
static int wmAreaMarkVisited(int cityIndex)
{
return _wmAreaMarkVisitedState(cityIndex, CITY_STATE_VISITED);
}
// 0x4C4634
bool _wmAreaMarkVisitedState(int cityIndex, int a2)
{
@ -6569,15 +6624,8 @@ int worldmapWindowRenderChrome(bool shouldRefreshWindow)
worldmapRenderQuickDestinations();
int v1 = gameTimeGetHour();
v1 /= 100;
int frameCount = artGetFrameCount(gWorldmapDialFrm);
int newFrame = (v1 + 12) % frameCount;
if (gWorldmapDialFrmCurrentFrame != newFrame) {
gWorldmapDialFrmCurrentFrame = newFrame;
worldmapWindowRenderDial(false);
}
// NOTE: Uninline.
wmInterfaceDialSyncTime(false);
worldmapWindowRenderDial(false);
@ -6761,13 +6809,8 @@ int _wmMakeTabsLabelList(int** quickDestinationsPtr, int* quickDestinationsLengt
{
int* quickDestinations = *quickDestinationsPtr;
if (quickDestinations != NULL) {
internal_free(quickDestinations);
quickDestinations = NULL;
}
*quickDestinationsPtr = NULL;
*quickDestinationsLengthPtr = 0;
// NOTE: Uninline.
wmFreeTabsLabelList(quickDestinationsPtr, quickDestinationsLengthPtr);
int capacity = 10;
@ -6816,6 +6859,21 @@ int worldmapCompareCitiesByName(const void* a1, const void* a2)
return compat_stricmp(city1->name, city2->name);
}
// NOTE: Inlined.
//
// 0x4C5710
static int wmFreeTabsLabelList(int** quickDestinationsListPtr, int* quickDestinationsLengthPtr)
{
if (*quickDestinationsListPtr != NULL) {
internal_free(*quickDestinationsListPtr);
*quickDestinationsListPtr = NULL;
}
*quickDestinationsLengthPtr = 0;
return 0;
}
// 0x4C5734
void worldmapWindowRenderDial(bool shouldRefreshWindow)
{
@ -6837,6 +6895,22 @@ void worldmapWindowRenderDial(bool shouldRefreshWindow)
}
}
// NOTE: Inlined.
//
// 0x4C57BC
static void wmInterfaceDialSyncTime(bool shouldRefreshWindow)
{
int gameHour;
int frame;
gameHour = gameTimeGetHour();
frame = (gameHour / 100 + 12) % artGetFrameCount(gWorldmapDialFrm);
if (frame != gWorldmapDialFrmCurrentFrame) {
gWorldmapDialFrmCurrentFrame = frame;
worldmapWindowRenderDial(shouldRefreshWindow);
}
}
// 0x4C5804
int _wmAreaFindFirstValidMap(int* out_a1)
{

View File

@ -246,7 +246,7 @@ void _wmWorldMap();
int _wmCheckGameAreaEvents();
int worldmapSetupRandomEncounter();
bool _wmEvalTileNumForPlacement(int tile);
int _wmSubTileMarkRadiusVisited(int x, int y, int radius);
int wmSubTileMarkRadiusVisited(int x, int y, int radius);
int _wmSubTileGetVisitedState(int a1, int a2, int* a3);
int _wmGetAreaIdxName(int index, char* name);
bool _wmAreaIsKnown(int city_index);