#1 19-11-2013 17:29

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

[C++] Загрузка и отрисовка текстур на экран.

Привет, народ! Сколько лет тут не был, но как симэн взялся за санник, решил заглянуть снова smile.
К делу. Пытаюсь своими силами через c++ вывести текстуру на экран из определённого TXD файла.
За основу взял небезызвестный gta_dll, к процессу игры подключаюсь путём подмены vorbisFile. Всё стандартно, вобщем.
Чудеса начинаются, когда я пытаюсь загрузить текстуру и попытаться отрисовать её по нажатию кнопки.

В самом верху:

CTexture* achievementGetTexture;

Далее, три процедуры отвечающие за загрузку, освобождение и отрисовку текстуры:

void LoadTextures()
{
	int slot = txdStore.AddTxdSlot("achiv");
	txdStore.LoadTxd(slot, "MODELS\\ACHIEV.TXD");
	txdStore.AddRef(slot);
	txdStore.PushCurrentTxd();
	txdStore.SetCurrentTxd(slot);
	achievementGetTexture->Load("ac_box", NULL);
	txdStore.PopCurrentTxd();

	debug("TEXTURE: %x", achievementGetTexture);
	debug("Textures loaded");
}

void ReleaseTextures()
{
	if ( achievementGetTexture ) {
		achievementGetTexture->Clean();
		achievementGetTexture = NULL;
	}
	
	int achievementGetTextureSlotIndex = CTxdStore::FindTxdSlot("achiv");
	txdStore.RemoveTxdSlot(achievementGetTextureSlotIndex);

	debug("Textures released");
}

void Update_Hook()
{
	// Draw texture on demand.
	while ( GetAsyncKeyState(0x09) )
		achievementGetTexture->DrawTexturedRect(&RwRect2D(_width(0), _height(448), _width(280), _height(188)), &RwRGBA(255, 255, 255, 255));
}

Где-то в DllMain:

call(0x5BD765, &LoadTextures, PATCH_CALL);
call(0x53BBCB, &ReleaseTextures, PATCH_CALL);
call(0x53BFAE, &Update_Hook, PATCH_CALL);

Собственно, проблема: при нажатии 0x09 (Tab) игра вылетает. Вылетает из-за того, что почему-то текстура не грузится в мой achievementGetTexture. Вот лог:

20:27:17.680 CTXDSTORE::ADDTXDSLOT([achiv])
20:27:17.681 CTXDSTORE::LOADTXD([4], [MODELS\ACHIEV.TXD])
20:27:17.697 CTXDSTORE::ADDREF([4])
20:27:17.697 CTXDSTORE::PUSHCURRENTTXD
20:27:17.697 CTXDSTORE::SETCURRENTTXD([4])
20:27:17.697 CTEXTURE::LOAD([ac_box], [(null)])
20:27:17.697 CTXDSTORE::POPCURRENTTXD
20:27:17.697 TEXTURE: 0 <-- sic!
20:27:17.697 Textures loaded
20:27:25.692 CTXDSTORE::FINDTXDSLOT([achiv])
20:27:25.692 CTXDSTORE::REMOVETXDSLOT([4])
20:27:25.692 Textures released
20:27:26.092 Log closed

Теперь самое главное: CTexture.h/.cpp, CTxdStore.h.cpp и RW.h/.cpp с определениями текстур и TxdStore.

#define FUNC_CTexture__DrawTexturedRect                        0x728350
#define FUNC_CTexture__Load                                    0x7272B0
#define FUNC_CTexture__Reload                                0x727270
#define FUNC_CTexture__Clean                                0x727240

class CTexture
{
private:
    RwTexture*        texture;

public:
    CTexture()
        : texture(NULL)
    {
    };

    void                DrawTexturedRect(RwRect2D* pos, RwRGBA* color);
    void                Load(const char* name, const char* maskName);    
    void                Clean();

    void                Reload(const char* name);
    void                Reload(const char* name, const char* maskName);

    RwTexture*            GetTexture() { return texture; };
};
#include "StdAfx.h"

void CTexture::DrawTexturedRect(RwRect2D* pos, RwRGBA* color)
{
    debug("CTEXTURE::DRAWTEXTUREDRECT([%.3f %.3f %.3f %.3f], [%i %i %i %i])", pos->x1, pos->y1, pos->x2, pos->y2, color->r, color->g, color->b, color->a);

    DWORD dwFunc = FUNC_CTexture__DrawTexturedRect;
    RwTexture* tex = GetTexture();
    _asm
    {
        push    color
        push    pos
        mov        ecx, tex
        call    dwFunc
    }
}

void CTexture::Load(const char* name, const char* maskName)
{
    debug("CTEXTURE::LOAD([%s], [%s])", name, maskName);

    DWORD dwFunc = FUNC_CTexture__Load;
    _asm
    {
        push    maskName
        push    name
        mov        ecx, this
        call    dwFunc
        mov        [this], eax
        add        esp, 8
    }
}

void CTexture::Clean()
{
    debug("CTEXTURE::CLEAN()");

    DWORD dwFunc = FUNC_CTexture__Clean;
    _asm
    {
        mov        ecx, this
        call    dwFunc
    }
}

void CTexture::Reload(const char* name)
{
    debug("CTEXTURE::RELOAD([%s])", name);

    if ( name ) {
        if ( texture ) {
            RwTexture::Destroy(texture);
            texture = NULL;
        }
        texture = RwTexture::Read(name, NULL);
    }
}

void CTexture::Reload(const char* name, const char* maskName)
{
    debug("CTEXTURE::RELOAD([%s], [%s])", name, maskName);

    if ( name && maskName ) {
        if ( texture ) {
            RwTexture::Destroy(texture);
            texture = NULL;
        }
        texture = RwTexture::Read(name, maskName);
    }
}
#define FUNC_CTxdStore__PushCurrentTxd                        0x7316A0
#define FUNC_CTxdStore__PopCurrentTxd                        0x7316B0
#define FUNC_CTxdStore__FindTxdSlot                            0x731850
#define FUNC_CTxdStore__SetCurrentTxd                        0x7319C0
#define FUNC_CTxdStore__AddTxdRef                            0x731A00
#define FUNC_CTxdStore__AddTxdSlot                            0x731C80
#define FUNC_CTxdStore__RemoveTxdSlot                        0x731CD0
#define FUNC_CTxdStore__LoadTxd                                0x7320B0

class CTxdStore
{
public:
    static void            PushCurrentTxd();
    static void            PopCurrentTxd();
    static int            FindTxdSlot(const char *name);
    static void            SetCurrentTxd(int slot);
    static void            AddRef(int index);
    static int            AddTxdSlot(const char* slotName);
    static void            RemoveTxdSlot(int slot);
    static void            LoadTxd(int slot, const char* fp);
};

static CTxdStore txdStore;
#include "stdafx.h"

void CTxdStore::PushCurrentTxd()
{
    debug("CTXDSTORE::PUSHCURRENTTXD");

    DWORD dwFunc = FUNC_CTxdStore__PushCurrentTxd;
    _asm call dwFunc
}

void CTxdStore::PopCurrentTxd()
{
    debug("CTXDSTORE::POPCURRENTTXD");

    DWORD dwFunc = FUNC_CTxdStore__PopCurrentTxd;
    _asm call dwFunc
}

int CTxdStore::FindTxdSlot(const char *name)
{
    debug("CTXDSTORE::FINDTXDSLOT([%s])", name);

    DWORD dwFunc = FUNC_CTxdStore__FindTxdSlot;
    int result = 0;
    _asm
    {
        push    name
        call    dwFunc
        mov        result, eax
        add        esp, 4
    }
}

void CTxdStore::SetCurrentTxd(int slot)
{
    debug("CTXDSTORE::SETCURRENTTXD([%i])", slot);

    DWORD dwFunc = FUNC_CTxdStore__SetCurrentTxd;
    _asm
    {
        push    slot
        call    dwFunc
    }
}

void CTxdStore::AddRef(int index)
{
    debug("CTXDSTORE::ADDREF([%i])", index);

    DWORD dwFunc = FUNC_CTxdStore__AddTxdRef;
    _asm
    {
        push    index
        call    dwFunc
    }
}

int CTxdStore::AddTxdSlot(const char* slotName)
{
    debug("CTXDSTORE::ADDTXDSLOT([%s])", slotName);

    DWORD dwFunc = FUNC_CTxdStore__AddTxdSlot;
    int result = 0;
    _asm
    {
        push    slotName
        call    dwFunc
        mov        result, eax
        add        esp, 4
    }
}

void CTxdStore::RemoveTxdSlot(int slot)
{
    debug("CTXDSTORE::REMOVETXDSLOT([%i])", slot);

    DWORD dwFunc = FUNC_CTxdStore__RemoveTxdSlot;
    _asm
    {
        push    slot
        call    dwFunc
    }
}

void CTxdStore::LoadTxd(int slot, const char* fp)
{
    debug("CTXDSTORE::LOADTXD([%i], [%s])", slot, fp);

    DWORD dwFunc = FUNC_CTxdStore__LoadTxd;
    _asm
    {
        push    fp
        push    slot
        call    dwFunc
    }
}
...

#define FUNC_RwTexture__Destroy                            0x7F3820
#define FUNC_RwTexture__Read                            0x7F3AC0

struct RwTexture
{
    RwRaster            *raster;
    RwTexDictionary        *txd;
    RwListEntry            TXDList;
    char                name[RW_TEXTURE_NAME_LENGTH];
    char                mask[RW_TEXTURE_NAME_LENGTH];
    unsigned int        flags;
    int                    refs;

    static void            Destroy(RwTexture* texture);
    static RwTexture*    Read(const char* name, const char* maskName);

    RwRaster*            GetRaster() { return this->raster; };
};

...
...

void RwTexture::Destroy(RwTexture* texture)
{
    DWORD    dwFunc = FUNC_RwTexture__Destroy;
    _asm
    {
        push    texture
        call    dwFunc
        add        esp, 4
    }
}

RwTexture* RwTexture::Read(const char* name, const char* maskName)
{
    DWORD        dwFunc = FUNC_RwTexture__Read;
    RwTexture*    result;
    _asm
    {
        push    maskName
        push    name
        call    dwFunc
        add        esp, 8
        mov        result, eax
    }

    return result;
}

...

Offline

#2 20-11-2013 00:35

DK22Pac
From: Ukraine
Registered: 26-03-2010
Posts: 447
Website

Re: [C++] Загрузка и отрисовка текстур на экран.

Может стоит попробовать это:
http://ru-script.3dn.ru/publ/sozdanie_d … 18-1-0-206
http://ru-script.3dn.ru/forum/30-105-1
Просто предложение)

Вообще, жаль, что не так много времени нахожу на эту разработку. Но работа с текстурами - это святое, и было сделано в первую очередь. wink

Last edited by DK22Pac (20-11-2013 00:44)


Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Offline

#3 20-11-2013 15:13

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: [C++] Загрузка и отрисовка текстур на экран.

А у меня как-то по-другому это сделано? Где у меня ошибка подскажите.

Last edited by Sw[ee]t (20-11-2013 15:13)

Offline

#4 20-11-2013 18:38

DK22Pac
From: Ukraine
Registered: 26-03-2010
Posts: 447
Website

Re: [C++] Загрузка и отрисовка текстур на экран.

ну это, например:

while ( GetAsyncKeyState(0x09) )

Так нельзя писать. Замени на

if ( GetAsyncKeyState(0x09) )

К предыдущему посту: я просто привел альтернативный вариант gta_dll. Это некая платформа для создания собственных плагинов для игры, которая позволяет абстрагироваться от хуков и замен вызовов дефолтных функций. Представь, что тебе понадобиться ещё в каком-то плагине делать те же хуки (инициализация, отрисовка, удаление), а потом ещё в каком-то. Будешь искать новые адреса для патчинга? Эта платформа позволяет не думать создателю плагина о таких проблемах.

Last edited by DK22Pac (20-11-2013 20:47)


Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Offline

#5 21-11-2013 14:44

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: [C++] Загрузка и отрисовка текстур на экран.

Заменил. Вылет остался. В чём у меня проблема, кто-нибудь может ответить?
Место вылета:
QFEguV40ZQUWsuxFNgqvwH_fvWj9uw6w-UhgDtLd7YU

Last edited by Sw[ee]t (21-11-2013 14:45)

Offline

Board footer

Powered by FluxBB