mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Implemented ExtraArt module from 4.x
Changed ASM code in BugFixes.cpp and Inventory.cpp to match 4.x
This commit is contained in:
@@ -388,7 +388,7 @@ fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long d
|
||||
|
||||
// Returns the terrain type of the sub-tile at the specified coordinates on the world map
|
||||
long wmGetTerrainType(long xPos, long yPos) {
|
||||
long* terrainId;
|
||||
long* terrainId = nullptr;
|
||||
__asm {
|
||||
lea ebx, terrainId;
|
||||
mov edx, yPos;
|
||||
@@ -632,105 +632,5 @@ void RefreshGNW(bool skipOwner) {
|
||||
fo::var::setInt(FO_VAR_doing_refresh_all) = 0;
|
||||
}
|
||||
|
||||
//////////////////////////// UNLISTED FRM FUNCTIONS ////////////////////////////
|
||||
|
||||
static bool LoadFrmHeader(fo::UnlistedFrm *frmHeader, fo::DbFile* frmStream) {
|
||||
if (fo::func::db_freadInt(frmStream, &frmHeader->version) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frmHeader->FPS) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frmHeader->actionFrame) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frmHeader->numFrames) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShortCount(frmStream, frmHeader->xCentreShift, 6) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShortCount(frmStream, frmHeader->yCentreShift, 6) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadIntCount(frmStream, frmHeader->oriOffset, 6) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadInt(frmStream, &frmHeader->frameAreaSize) == -1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool LoadFrmFrame(fo::UnlistedFrm::Frame *frame, fo::DbFile* frmStream) {
|
||||
//FRMframe *frameHeader = (FRMframe*)frameMEM;
|
||||
//BYTE* frameBuff = frame + sizeof(FRMframe);
|
||||
|
||||
if (fo::func::db_freadShort(frmStream, &frame->width) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frame->height) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadInt(frmStream, &frame->size) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frame->x) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frame->y) == -1)
|
||||
return false;
|
||||
|
||||
frame->indexBuff = new BYTE[frame->size];
|
||||
if (fo::func::db_fread(frame->indexBuff, 1, frame->size, frmStream) != frame->size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fo::UnlistedFrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef) {
|
||||
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
||||
|
||||
const char *artfolder = fo::ptr::art[folderRef].path; // address of art type name
|
||||
char frmPath[MAX_PATH];
|
||||
|
||||
if (*fo::ptr::use_language) {
|
||||
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s\\%s", (const char*)fo::ptr::language, artfolder, frmName);
|
||||
} else {
|
||||
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
|
||||
}
|
||||
|
||||
fo::UnlistedFrm *frm = new fo::UnlistedFrm;
|
||||
|
||||
fo::DbFile* frmStream = fo::func::db_fopen(frmPath, "rb");
|
||||
|
||||
if (!frmStream && *fo::ptr::use_language) {
|
||||
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
|
||||
frmStream = fo::func::db_fopen(frmPath, "rb");
|
||||
}
|
||||
|
||||
if (frmStream != nullptr) {
|
||||
if (!LoadFrmHeader(frm, frmStream)) {
|
||||
fo::func::db_fclose(frmStream);
|
||||
delete frm;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DWORD oriOffset_1st = frm->oriOffset[0];
|
||||
DWORD oriOffset_new = 0;
|
||||
frm->frames = new fo::UnlistedFrm::Frame[6 * frm->numFrames];
|
||||
for (int ori = 0; ori < 6; ori++) {
|
||||
if (ori == 0 || frm->oriOffset[ori] != oriOffset_1st) {
|
||||
frm->oriOffset[ori] = oriOffset_new;
|
||||
for (int fNum = 0; fNum < frm->numFrames; fNum++) {
|
||||
if (!LoadFrmFrame(&frm->frames[oriOffset_new + fNum], frmStream)) {
|
||||
fo::func::db_fclose(frmStream);
|
||||
delete frm;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
oriOffset_new += frm->numFrames;
|
||||
} else {
|
||||
frm->oriOffset[ori] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fo::func::db_fclose(frmStream);
|
||||
} else {
|
||||
delete frm;
|
||||
return nullptr;
|
||||
}
|
||||
return frm;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,19 @@ namespace fo
|
||||
namespace util
|
||||
{
|
||||
|
||||
struct ArtCacheLock {
|
||||
DWORD entryPtr;
|
||||
|
||||
ArtCacheLock() :entryPtr(0) {}
|
||||
ArtCacheLock(DWORD _lock) : entryPtr(_lock) {}
|
||||
~ArtCacheLock() {
|
||||
if (entryPtr != 0) {
|
||||
fo::func::art_ptr_unlock(entryPtr);
|
||||
entryPtr = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// rect_free_ function for inline implementation
|
||||
__forceinline void rect_free(fo::RectList* rect) {
|
||||
fo::RectList* front = *fo::ptr::rectList;
|
||||
@@ -179,7 +192,5 @@ void RedrawObject(fo::GameObject* obj);
|
||||
// Redraws all windows
|
||||
void RefreshGNW(bool skipOwner = false);
|
||||
|
||||
fo::UnlistedFrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace sfall
|
||||
struct Rectangle {
|
||||
long x, y, width, height;
|
||||
|
||||
long right() { return x + (width - 1); }
|
||||
long bottom() { return y + (height - 1); }
|
||||
long right() const { return x + (width - 1); }
|
||||
long bottom() const { return y + (height - 1); }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -175,25 +175,25 @@ struct GameObject {
|
||||
long rads;
|
||||
long poison;
|
||||
|
||||
inline bool IsDead() {
|
||||
inline bool IsDead() const {
|
||||
return ((damageFlags & DamageFlag::DAM_DEAD) != 0);
|
||||
}
|
||||
inline bool IsNotDead() {
|
||||
inline bool IsNotDead() const {
|
||||
return ((damageFlags & DamageFlag::DAM_DEAD) == 0);
|
||||
}
|
||||
inline bool IsActive() {
|
||||
inline bool IsActive() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) == 0);
|
||||
}
|
||||
inline bool IsNotActive() {
|
||||
inline bool IsNotActive() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) != 0);
|
||||
}
|
||||
inline bool IsActiveNotDead() {
|
||||
inline bool IsActiveNotDead() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_DEAD | DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) == 0);
|
||||
}
|
||||
inline bool IsNotActiveOrDead() {
|
||||
inline bool IsNotActiveOrDead() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_DEAD | DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) != 0);
|
||||
}
|
||||
inline bool IsFleeing() {
|
||||
inline bool IsFleeing() const {
|
||||
return ((combatState & CombatStateFlag::InFlee) != 0);
|
||||
}
|
||||
|
||||
@@ -222,23 +222,23 @@ struct GameObject {
|
||||
GameObject* owner; // not saved
|
||||
long scriptIndex;
|
||||
|
||||
inline char Type() {
|
||||
inline char Type() const {
|
||||
return (protoId >> 24);
|
||||
}
|
||||
inline char TypeFid() {
|
||||
inline char TypeFid() const {
|
||||
return ((artFid >> 24) & 0x0F);
|
||||
}
|
||||
|
||||
inline bool IsCritter() {
|
||||
inline bool IsCritter() const {
|
||||
return (Type() == fo::ObjType::OBJ_TYPE_CRITTER);
|
||||
}
|
||||
inline bool IsNotCritter() {
|
||||
inline bool IsNotCritter() const {
|
||||
return (Type() != fo::ObjType::OBJ_TYPE_CRITTER);
|
||||
}
|
||||
inline bool IsItem() {
|
||||
inline bool IsItem() const {
|
||||
return (Type() == fo::ObjType::OBJ_TYPE_ITEM);
|
||||
}
|
||||
inline bool IsNotItem() {
|
||||
inline bool IsNotItem() const {
|
||||
return (Type() != fo::ObjType::OBJ_TYPE_ITEM);
|
||||
}
|
||||
};
|
||||
@@ -465,58 +465,6 @@ struct TileFrmFile : public FrmHeaderData {
|
||||
|
||||
static_assert(sizeof(TileFrmFile) == 2954, "Incorrect TileFrmFile definition.");
|
||||
|
||||
// structures for loading unlisted frms
|
||||
struct UnlistedFrm {
|
||||
DWORD version;
|
||||
WORD FPS;
|
||||
WORD actionFrame;
|
||||
WORD numFrames;
|
||||
WORD xCentreShift[6];
|
||||
WORD yCentreShift[6];
|
||||
DWORD oriOffset[6];
|
||||
DWORD frameAreaSize;
|
||||
|
||||
struct Frame {
|
||||
WORD width;
|
||||
WORD height;
|
||||
DWORD size;
|
||||
WORD x;
|
||||
WORD y;
|
||||
BYTE *indexBuff;
|
||||
|
||||
Frame() {
|
||||
width = 0;
|
||||
height = 0;
|
||||
size = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
indexBuff = nullptr;
|
||||
}
|
||||
~Frame() {
|
||||
if (indexBuff != nullptr)
|
||||
delete[] indexBuff;
|
||||
}
|
||||
} *frames;
|
||||
|
||||
UnlistedFrm() {
|
||||
version = 0;
|
||||
FPS = 0;
|
||||
actionFrame = 0;
|
||||
numFrames = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
xCentreShift[i] = 0;
|
||||
yCentreShift[i] = 0;
|
||||
oriOffset[i] = 0;
|
||||
}
|
||||
frameAreaSize = 0;
|
||||
frames = nullptr;
|
||||
}
|
||||
|
||||
~UnlistedFrm() {
|
||||
if (frames != nullptr) delete[] frames;
|
||||
}
|
||||
};
|
||||
|
||||
//for holding a message
|
||||
struct MessageNode {
|
||||
long number;
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
#define FO_VAR_interfaceWindow 0x519024
|
||||
#define FO_VAR_intfaceEnabled 0x518F10
|
||||
#define FO_VAR_intotal 0x43E95C
|
||||
#define FO_VAR_inven_cur_disp 0x519054
|
||||
#define FO_VAR_inven_dude 0x519058
|
||||
#define FO_VAR_inven_pid 0x51905C
|
||||
#define FO_VAR_inven_scroll_dn_bid 0x5190E8
|
||||
|
||||
@@ -851,7 +851,7 @@ next:
|
||||
pop eax;
|
||||
jnz found;
|
||||
inc edx;
|
||||
cmp edx, 6;
|
||||
cmp edx, ds:[FO_VAR_inven_cur_disp];
|
||||
jb next;
|
||||
end:
|
||||
push 0x47125C;
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2024 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
#include "LoadGameHook.h"
|
||||
|
||||
#include "ExtraArt.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
typedef std::unordered_map<std::string, fo::FrmFile*> TFrmCache;
|
||||
typedef std::unordered_map<std::string, PcxFile> TPcxCache;
|
||||
|
||||
static TFrmCache frmFileCache;
|
||||
static TPcxCache pcxFileCache;
|
||||
|
||||
static PcxFile LoadPcxFile(const char* file) {
|
||||
PcxFile pcx;
|
||||
pcx.pixelData = fo::func::loadPCX(file, &pcx.width, &pcx.height, fo::ptr::pal);
|
||||
if (pcx.pixelData == nullptr) return PcxFile();
|
||||
|
||||
fo::func::datafileConvertData(pcx.pixelData, fo::ptr::pal, pcx.width, pcx.height);
|
||||
return pcx;
|
||||
}
|
||||
|
||||
fo::FrmFile* LoadFrmFileCached(const char* file) {
|
||||
fo::FrmFile* frmPtr = nullptr;
|
||||
TFrmCache::iterator cacheHit = frmFileCache.find(file);
|
||||
if (cacheHit != frmFileCache.end()) {
|
||||
frmPtr = cacheHit->second;
|
||||
} else {
|
||||
if (fo::func::load_frame(file, &frmPtr)) {
|
||||
frmPtr = nullptr;
|
||||
}
|
||||
frmFileCache.insert(std::make_pair(file, frmPtr));
|
||||
}
|
||||
return frmPtr;
|
||||
}
|
||||
|
||||
PcxFile LoadPcxFileCached(const char* file) {
|
||||
TPcxCache::iterator cacheHit = pcxFileCache.find(file);
|
||||
if (cacheHit != pcxFileCache.end()) {
|
||||
return cacheHit->second;
|
||||
}
|
||||
return pcxFileCache.insert(std::make_pair(file, LoadPcxFile(file))).first->second;
|
||||
}
|
||||
|
||||
static void GetUnlistedFrmPath(const char* frmName, unsigned int folderRef, bool useLanguage, char* pathBuf) {
|
||||
const char* artfolder = fo::ptr::art[folderRef].path; // address of art type name
|
||||
if (useLanguage) {
|
||||
sprintf_s(pathBuf, MAX_PATH, "art\\%s\\%s\\%s", (const char*)fo::ptr::language, artfolder, frmName);
|
||||
} else {
|
||||
sprintf_s(pathBuf, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
|
||||
}
|
||||
}
|
||||
|
||||
bool UnlistedFrmExists(const char* frmName, unsigned int folderRef) {
|
||||
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
||||
|
||||
char frmPath[MAX_PATH];
|
||||
GetUnlistedFrmPath(frmName, folderRef, *fo::ptr::use_language != 0, frmPath);
|
||||
|
||||
bool exists = fo::func::db_access(frmPath);
|
||||
if (!exists && *fo::ptr::use_language) {
|
||||
GetUnlistedFrmPath(frmName, folderRef, false, frmPath);
|
||||
exists = fo::func::db_access(frmPath);
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
||||
fo::FrmFile* LoadUnlistedFrmCached(const char* frmName, unsigned int folderRef) {
|
||||
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
||||
|
||||
char frmPath[MAX_PATH];
|
||||
GetUnlistedFrmPath(frmName, folderRef, *fo::ptr::use_language != 0, frmPath);
|
||||
|
||||
fo::FrmFile* frm = LoadFrmFileCached(frmPath);
|
||||
if (frm == nullptr && *fo::ptr::use_language) {
|
||||
GetUnlistedFrmPath(frmName, folderRef, false, frmPath);
|
||||
frm = LoadFrmFileCached(frmPath);
|
||||
}
|
||||
return frm;
|
||||
}
|
||||
|
||||
static void ClearInterfaceArtCache() {
|
||||
for (TPcxCache::iterator it = pcxFileCache.begin(); it != pcxFileCache.end(); ++it) {
|
||||
fo::func::freePtr_invoke(it->second.pixelData);
|
||||
}
|
||||
pcxFileCache.clear();
|
||||
|
||||
for (TFrmCache::iterator it = frmFileCache.begin(); it != frmFileCache.end(); ++it) {
|
||||
fo::func::mem_free(it->second);
|
||||
}
|
||||
frmFileCache.clear();
|
||||
}
|
||||
|
||||
void ExtraArt::OnGameReset() {
|
||||
ClearInterfaceArtCache();
|
||||
}
|
||||
|
||||
void ExtraArt::init() {
|
||||
// nothing to initialize
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2024 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
struct PcxFile {
|
||||
BYTE* pixelData;
|
||||
long width;
|
||||
long height;
|
||||
|
||||
PcxFile() : pixelData(nullptr), width(0), height(0) {}
|
||||
};
|
||||
|
||||
class ExtraArt : public Module {
|
||||
public:
|
||||
const char* name() { return "ExtraArt"; }
|
||||
void init();
|
||||
|
||||
static void OnGameReset();
|
||||
};
|
||||
|
||||
fo::FrmFile* LoadFrmFileCached(const char* file);
|
||||
PcxFile LoadPcxFileCached(const char* file);
|
||||
|
||||
bool UnlistedFrmExists(const char* frmName, unsigned int folderRef);
|
||||
fo::FrmFile* LoadUnlistedFrmCached(const char* file, unsigned int folderRef);
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
#include "..\Translate.h"
|
||||
|
||||
#include "ExtraArt.h"
|
||||
#include "Inventory.h"
|
||||
#include "LoadGameHook.h"
|
||||
#include "LoadOrder.h"
|
||||
@@ -585,10 +586,9 @@ static void DrawCharNote(bool style, int winRef, DWORD xPosWin, DWORD yPosWin, B
|
||||
BYTE *PadSurface = new BYTE [280 * 168];
|
||||
surface_draw(280, 168, widthBG, xPosBG, yPosBG, BGSurface, 280, 0, 0, PadSurface);
|
||||
|
||||
fo::UnlistedFrm *frm = fo::util::LoadUnlistedFrm((style) ? "AppStyle.frm" : "AppRace.frm", fo::OBJ_TYPE_SKILLDEX);
|
||||
if (frm) {
|
||||
fo::util::DrawToSurface(frm->frames[0].width, frm->frames[0].height, 0, 0, frm->frames[0].width, frm->frames[0].indexBuff, 136, 37, 280, 168, PadSurface, 0); // cover buttons pics bottom
|
||||
delete frm;
|
||||
fo::FrmFile *frm = LoadUnlistedFrmCached((style) ? "AppStyle.frm" : "AppRace.frm", fo::OBJ_TYPE_SKILLDEX);
|
||||
if (frm != nullptr) {
|
||||
fo::util::DrawToSurface(frm->frameData[0].width, frm->frameData[0].height, 0, 0, frm->frameData[0].width, frm->frameData[0].data, 136, 37, 280, 168, PadSurface, 0); // cover buttons pics bottom
|
||||
}
|
||||
|
||||
int oldFont = GetFont(); // store current font
|
||||
@@ -653,7 +653,7 @@ static void __stdcall DrawCharNoteNewChar(bool type) {
|
||||
void __stdcall HeroSelectWindow(int raceStyleFlag) {
|
||||
if (!HeroAppearance::appModEnabled) return;
|
||||
|
||||
fo::UnlistedFrm *frm = fo::util::LoadUnlistedFrm("AppHeroWin.frm", fo::OBJ_TYPE_INTRFACE);
|
||||
fo::FrmFile *frm = LoadUnlistedFrmCached("AppHeroWin.frm", fo::OBJ_TYPE_INTRFACE);
|
||||
if (frm == nullptr) {
|
||||
fo::func::debug_printf("\nApperanceMod: art\\intrface\\AppHeroWin.frm file not found.");
|
||||
return;
|
||||
@@ -665,7 +665,6 @@ void __stdcall HeroSelectWindow(int raceStyleFlag) {
|
||||
|
||||
int winRef = fo::func::win_add(resWidth / 2 - 242, (resHeight - 100) / 2 - 65, 484, 230, 100, 0x4);
|
||||
if (winRef == -1) {
|
||||
delete frm;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -677,8 +676,7 @@ void __stdcall HeroSelectWindow(int raceStyleFlag) {
|
||||
BYTE *winSurface = fo::func::win_get_buf(winRef);
|
||||
BYTE *mainSurface = new BYTE [484 * 230];
|
||||
|
||||
surface_draw(484, 230, 484, 0, 0, frm->frames[0].indexBuff, 484, 0, 0, mainSurface);
|
||||
delete frm;
|
||||
surface_draw(484, 230, 484, 0, 0, frm->frameData[0].data, 484, 0, 0, mainSurface);
|
||||
|
||||
DWORD MenuUObj, MenuDObj;
|
||||
BYTE *MenuUSurface = fo::func::art_ptr_lock_data(BuildFrmId(6, 299), 0, 0, &MenuUObj); // MENUUP Frm
|
||||
@@ -1149,11 +1147,9 @@ static void __declspec(naked) FixCharScrnBack() {
|
||||
if (charScrnBackSurface == nullptr) {
|
||||
charScrnBackSurface = new BYTE [640 * 480];
|
||||
|
||||
fo::UnlistedFrm *frm = fo::util::LoadUnlistedFrm((*fo::ptr::glblmode) ? "AppChCrt.frm" : "AppChEdt.frm", fo::OBJ_TYPE_INTRFACE);
|
||||
|
||||
fo::FrmFile *frm = LoadUnlistedFrmCached((*fo::ptr::glblmode) ? "AppChCrt.frm" : "AppChEdt.frm", fo::OBJ_TYPE_INTRFACE);
|
||||
if (frm != nullptr) {
|
||||
surface_draw(640, 480, 640, 0, 0, frm->frames[0].indexBuff, 640, 0, 0, charScrnBackSurface);
|
||||
delete frm;
|
||||
surface_draw(640, 480, 640, 0, 0, frm->frameData[0].data, 640, 0, 0, charScrnBackSurface);
|
||||
} else {
|
||||
BYTE* oldCharScrnBackSurface = *fo::ptr::bckgnd; // char screen background frm surface
|
||||
|
||||
|
||||
@@ -414,10 +414,13 @@ scroll:
|
||||
push ebx;
|
||||
mov ebx, [eax + 8 + 0]; // ebx = _i_wid.rect.x
|
||||
mov ecx, [eax + 8 + 4]; // ecx = _i_wid.rect.y
|
||||
mov eax, 48;
|
||||
imul dword ptr ds:[FO_VAR_inven_cur_disp];
|
||||
add ecx, 37;
|
||||
mov edx, ecx; // y_start
|
||||
add ecx, eax; // y_end
|
||||
lea eax, [ebx + 297]; // x_start
|
||||
add ebx, 297 + 64; // x_end
|
||||
lea edx, [ecx + 37]; // y_start
|
||||
add ecx, 37 + 6 * 48; // y_end
|
||||
call fo::funcoffs::mouse_click_in_;
|
||||
pop ebx;
|
||||
pop ecx;
|
||||
@@ -455,10 +458,13 @@ scroll:
|
||||
mov edi, [eax + 8 + 4];
|
||||
mov ebx, ebp; // ebx = _i_wid.rect.x
|
||||
mov ecx, edi; // ecx = _i_wid.rect.y
|
||||
mov eax, 48;
|
||||
imul dword ptr ds:[FO_VAR_inven_cur_disp];
|
||||
add ecx, 35;
|
||||
mov edx, ecx; // y_start
|
||||
add ecx, eax; // y_end
|
||||
lea eax, [ebp + 395]; // x_start
|
||||
add ebx, 395 + 64; // x_end
|
||||
lea edx, [edi + 35]; // y_start
|
||||
add ecx, 35 + 3 * 48; // y_end
|
||||
call fo::funcoffs::mouse_click_in_;
|
||||
test eax, eax;
|
||||
jz notTargetScroll;
|
||||
@@ -472,10 +478,13 @@ targetDown:
|
||||
notTargetScroll:
|
||||
mov ebx, ebp;
|
||||
mov ecx, edi;
|
||||
mov eax, 48;
|
||||
imul dword ptr ds:[FO_VAR_inven_cur_disp];
|
||||
add ecx, 20;
|
||||
mov edx, ecx; // y_start
|
||||
add ecx, eax; // y_end
|
||||
lea eax, [ebp + 250]; // x_start
|
||||
add ebx, 250 + 64; // x_end
|
||||
lea edx, [edi + 20]; // y_start
|
||||
add ecx, 20 + 3 * 48; // y_end
|
||||
call fo::funcoffs::mouse_click_in_;
|
||||
test eax, eax;
|
||||
jz notTargetBarter;
|
||||
@@ -489,10 +498,13 @@ barterTargetDown:
|
||||
notTargetBarter:
|
||||
mov ebx, ebp;
|
||||
mov ecx, edi;
|
||||
mov eax, 48;
|
||||
imul dword ptr ds:[FO_VAR_inven_cur_disp];
|
||||
add ecx, 20;
|
||||
mov edx, ecx; // y_start
|
||||
add ecx, eax; // y_end
|
||||
lea eax, [ebp + 165]; // x_start
|
||||
add ebx, 165 + 64; // x_end
|
||||
lea edx, [edi + 20]; // y_start
|
||||
add ecx, 20 + 3 * 48; // y_end
|
||||
call fo::funcoffs::mouse_click_in_;
|
||||
test eax, eax;
|
||||
jz end;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "Criticals.h"
|
||||
#include "DebugEditor.h"
|
||||
#include "Explosions.h"
|
||||
#include "ExtraArt.h"
|
||||
#include "ExtraSaveSlots.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Graphics.h"
|
||||
@@ -309,6 +310,7 @@ static bool __stdcall GameReset(DWORD isGameLoad) {
|
||||
}
|
||||
FileSystem::OnGameReset();
|
||||
LoadOrder::OnGameReset();
|
||||
ExtraArt::OnGameReset();
|
||||
Animations::OnGameReset();
|
||||
BarBoxes::OnGameReset();
|
||||
Explosions::OnGameReset();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "..\..\..\InputFuncs.h"
|
||||
#include "..\..\BarBoxes.h"
|
||||
#include "..\..\ExtraArt.h"
|
||||
#include "..\..\LoadGameHook.h"
|
||||
#include "..\..\ScriptExtender.h"
|
||||
#include "..\..\Interface.h"
|
||||
@@ -502,70 +503,29 @@ struct FrameData {
|
||||
}
|
||||
|
||||
// Data from PCX file.
|
||||
FrameData(BYTE* data, long w, long h) {
|
||||
pixelData = data;
|
||||
width = (short)w;
|
||||
height = (short)h;
|
||||
FrameData(PcxFile pcx) {
|
||||
pixelData = pcx.pixelData;
|
||||
width = (short)pcx.width;
|
||||
height = (short)pcx.height;
|
||||
}
|
||||
};
|
||||
|
||||
static FrameData LoadPCXFile(const char* file) {
|
||||
long w, h;
|
||||
BYTE* pixelData = fo::func::loadPCX(file, &w, &h, fo::ptr::pal);
|
||||
if (pixelData == nullptr) return FrameData();
|
||||
|
||||
fo::func::datafileConvertData(pixelData, fo::ptr::pal, w, h);
|
||||
return FrameData(pixelData, w, h);
|
||||
}
|
||||
|
||||
static bool IsPCXFile(const char* file) {
|
||||
const char* pos = strrchr(file, '.');
|
||||
return pos && _stricmp(++pos, "PCX") == 0;
|
||||
}
|
||||
|
||||
typedef std::unordered_map<std::string, fo::FrmFile*> TFRMCache;
|
||||
typedef std::unordered_map<std::string, FrameData> TPCXCache;
|
||||
|
||||
static TFRMCache frmFileCache;
|
||||
static TPCXCache pcxFileCache;
|
||||
|
||||
//static fo::FrmFile* LoadArtFileCached(const char* file, long frame, long direction, fo::FrmFrameData* &framePtr, bool checkPCX) {
|
||||
static FrameData LoadFrameDataCached(const char* file, long frame, long direction) {
|
||||
if (IsPCXFile(file)) {
|
||||
TPCXCache::iterator cacheHit = pcxFileCache.find(file);
|
||||
if (cacheHit != pcxFileCache.end()) {
|
||||
return cacheHit->second;
|
||||
}
|
||||
return pcxFileCache.insert(std::make_pair(file, LoadPCXFile(file))).first->second;
|
||||
}
|
||||
|
||||
fo::FrmFile* frmPtr = nullptr;
|
||||
TFRMCache::iterator cacheHit = frmFileCache.find(file);
|
||||
if (cacheHit != frmFileCache.end()) {
|
||||
frmPtr = cacheHit->second;
|
||||
} else {
|
||||
if (fo::func::load_frame(file, &frmPtr)) {
|
||||
frmPtr = nullptr;
|
||||
}
|
||||
frmFileCache.insert(std::make_pair(file, frmPtr));
|
||||
return LoadPcxFileCached(file);
|
||||
}
|
||||
fo::FrmFile* frmPtr = LoadFrmFileCached(file);
|
||||
return (frmPtr != nullptr)
|
||||
? FrameData(frmPtr, direction, frame)
|
||||
: FrameData();
|
||||
}
|
||||
|
||||
void ClearInterfaceArtCache() {
|
||||
for (TPCXCache::iterator it = pcxFileCache.begin(); it != pcxFileCache.end(); ++it) {
|
||||
fo::func::freePtr_invoke(it->second.pixelData);
|
||||
}
|
||||
pcxFileCache.clear();
|
||||
|
||||
for (TFRMCache::iterator it = frmFileCache.begin(); it != frmFileCache.end(); ++it) {
|
||||
fo::func::mem_free(it->second);
|
||||
}
|
||||
frmFileCache.clear();
|
||||
}
|
||||
|
||||
static long GetArtFIDFile(long fid, char* outFilePath) {
|
||||
long direction = 0;
|
||||
long _fid = fid & 0xFFFFFFF;
|
||||
@@ -590,20 +550,7 @@ static long GetArtFIDFile(long fid, char* outFilePath) {
|
||||
return direction;
|
||||
}
|
||||
|
||||
struct ArtCacheLock {
|
||||
DWORD entryPtr;
|
||||
|
||||
ArtCacheLock() :entryPtr(0) {}
|
||||
ArtCacheLock(DWORD _lock) : entryPtr(_lock) {}
|
||||
~ArtCacheLock() {
|
||||
if (entryPtr != 0) {
|
||||
fo::func::art_ptr_unlock(entryPtr);
|
||||
entryPtr = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static FrameData LockFrameData(unsigned long fid, ArtCacheLock& lock, long direction, long frame) {
|
||||
static FrameData LockFrameData(unsigned long fid, fo::util::ArtCacheLock& lock, long direction, long frame) {
|
||||
long objType = (fid >> 24) & 0xF;
|
||||
if (direction < 0) {
|
||||
// If direction is not specified, take it from FID.
|
||||
@@ -623,7 +570,7 @@ static long DrawImage(OpcodeContext& ctx, bool isScaled) {
|
||||
return 0;
|
||||
}
|
||||
FrameData frm;
|
||||
ArtCacheLock cacheLock;
|
||||
fo::util::ArtCacheLock cacheLock;
|
||||
|
||||
bool isID = ctx.arg(0).isInt();
|
||||
long frame = ctx.arg(1).rawValue();
|
||||
@@ -740,7 +687,7 @@ static long InterfaceDrawImage(OpcodeContext& ctx, fo::Window* ifaceWin) {
|
||||
if (size > 2) h = sArray->val[2].intVal;
|
||||
}
|
||||
}
|
||||
ArtCacheLock cacheLock;
|
||||
fo::util::ArtCacheLock cacheLock;
|
||||
FrameData frm;
|
||||
if (isID) { // art id
|
||||
long fid = ctx.arg(1).rawValue();
|
||||
|
||||
@@ -277,7 +277,6 @@ void Opcodes::OnGameReset() {
|
||||
PipboyAvailableRestore();
|
||||
ForceEncounterRestore(); // restore if the encounter did not happen
|
||||
ResetIniCache();
|
||||
ClearInterfaceArtCache();
|
||||
}
|
||||
|
||||
void Opcodes::InitNew() {
|
||||
|
||||
@@ -276,6 +276,7 @@
|
||||
<ClInclude Include="Modules\Elevators.h" />
|
||||
<ClInclude Include="Modules\EngineTweaks.h" />
|
||||
<ClInclude Include="Modules\Explosions.h" />
|
||||
<ClInclude Include="Modules\ExtraArt.h" />
|
||||
<ClInclude Include="Modules\ExtraSaveSlots.h" />
|
||||
<ClInclude Include="Modules\FileSystem.h" />
|
||||
<ClInclude Include="Modules\Graphics.h" />
|
||||
@@ -392,6 +393,7 @@
|
||||
<ClCompile Include="Modules\Elevators.cpp" />
|
||||
<ClCompile Include="Modules\EngineTweaks.cpp" />
|
||||
<ClCompile Include="Modules\Explosions.cpp" />
|
||||
<ClCompile Include="Modules\ExtraArt.cpp" />
|
||||
<ClCompile Include="Modules\ExtraSaveSlots.cpp" />
|
||||
<ClCompile Include="Modules\FileSystem.cpp" />
|
||||
<ClCompile Include="Modules\Graphics.cpp" />
|
||||
|
||||
@@ -368,6 +368,9 @@
|
||||
<Filter>Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ModuleManager.h" />
|
||||
<ClInclude Include="Modules\ExtraArt.h">
|
||||
<Filter>Modules</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
@@ -669,6 +672,9 @@
|
||||
<Filter>Modules\Scripting\Handlers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ModuleManager.cpp" />
|
||||
<ClCompile Include="Modules\ExtraArt.cpp">
|
||||
<Filter>Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="exports.def" />
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "Modules\Elevators.h"
|
||||
#include "Modules\EngineTweaks.h"
|
||||
#include "Modules\Explosions.h"
|
||||
#include "Modules\ExtraArt.h"
|
||||
#include "Modules\ExtraSaveSlots.h"
|
||||
#include "Modules\FileSystem.h"
|
||||
#include "Modules\Graphics.h"
|
||||
@@ -121,6 +122,7 @@ static void InitModules() {
|
||||
manager.add<LoadOrder>();
|
||||
manager.add<LoadGameHook>();
|
||||
manager.add<MainLoopHook>();
|
||||
manager.add<ExtraArt>();
|
||||
|
||||
manager.add<EngineTweaks>();
|
||||
manager.add<Books>();
|
||||
|
||||
Reference in New Issue
Block a user