mirror of
https://github.com/GTAmodding/re3.git
synced 2024-11-15 05:29:01 +00:00
Merge pull request #23 from Fire-Head/master
CdSteam, RwFreeAlign/RwMallocAlign
This commit is contained in:
commit
900f3d9783
7 changed files with 613 additions and 7 deletions
529
src/CdStream.cpp
Normal file
529
src/CdStream.cpp
Normal file
|
@ -0,0 +1,529 @@
|
|||
#include <Windows.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "CdStream.h"
|
||||
#include "rwcore.h"
|
||||
#include "RwHelper.h"
|
||||
|
||||
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", __VA_ARGS__)
|
||||
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", __VA_ARGS__)
|
||||
|
||||
struct CdReadInfo
|
||||
{
|
||||
uint32 nSectorOffset;
|
||||
uint32 nSectorsToRead;
|
||||
void *pBuffer;
|
||||
char field_C;
|
||||
bool bLocked;
|
||||
bool bInUse;
|
||||
char _pad0;
|
||||
int32 nStatus;
|
||||
HANDLE hSemaphore;
|
||||
HANDLE hFile;
|
||||
OVERLAPPED Overlapped;
|
||||
};
|
||||
VALIDATE_SIZE(CdReadInfo, 0x30);
|
||||
|
||||
char gCdImageNames[MAX_CDIMAGES+1][64];
|
||||
int32 gNumImages;
|
||||
int32 gNumChannels;
|
||||
|
||||
HANDLE gImgFiles[MAX_CDIMAGES];
|
||||
|
||||
HANDLE _gCdStreamThread;
|
||||
HANDLE gCdStreamSema;
|
||||
DWORD _gCdStreamThreadId;
|
||||
|
||||
CdReadInfo *gpReadInfo;
|
||||
Queue gChannelRequestQ;
|
||||
|
||||
int32 lastPosnRead;
|
||||
|
||||
BOOL _gbCdStreamOverlapped;
|
||||
BOOL _gbCdStreamAsync;
|
||||
DWORD _gdwCdStreamFlags;
|
||||
|
||||
|
||||
void
|
||||
CdStreamInitThread(void)
|
||||
{
|
||||
SetLastError(0);
|
||||
|
||||
if ( gNumChannels > 0 )
|
||||
{
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
{
|
||||
gpReadInfo[i].hSemaphore = CreateSemaphore(NULL, 0, 2, NULL);
|
||||
|
||||
if ( gpReadInfo[i].hSemaphore == NULL )
|
||||
{
|
||||
CDTRACE("failed to create sync semaphore");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gChannelRequestQ.items = (int32 *)LocalAlloc(LMEM_ZEROINIT, sizeof(int32) * (gNumChannels + 1));
|
||||
gChannelRequestQ.head = 0;
|
||||
gChannelRequestQ.tail = 0;
|
||||
gChannelRequestQ.size = gNumChannels + 1;
|
||||
ASSERT(gChannelRequestQ.items != NULL );
|
||||
|
||||
gCdStreamSema = CreateSemaphore(NULL, 0, 5, "CdStream");
|
||||
|
||||
if ( gCdStreamSema == NULL )
|
||||
{
|
||||
CDTRACE("failed to create stream semaphore");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
_gCdStreamThread = CreateThread(NULL, 64*1024/*64KB*/, CdStreamThread, NULL, CREATE_SUSPENDED, &_gCdStreamThreadId);
|
||||
|
||||
if ( _gCdStreamThread == NULL )
|
||||
{
|
||||
CDTRACE("failed to create streaming thread");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
SetThreadPriority(_gCdStreamThread, GetThreadPriority(GetCurrentThread()) - 1);
|
||||
|
||||
ResumeThread(_gCdStreamThread);
|
||||
}
|
||||
|
||||
void
|
||||
CdStreamInit(int32 numChannels)
|
||||
{
|
||||
DWORD SectorsPerCluster;
|
||||
DWORD BytesPerSector;
|
||||
DWORD NumberOfFreeClusters;
|
||||
DWORD TotalNumberOfClusters;
|
||||
|
||||
GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters);
|
||||
|
||||
_gdwCdStreamFlags = 0;
|
||||
|
||||
if ( BytesPerSector <= CDSTREAM_SECTOR_SIZE )
|
||||
{
|
||||
_gdwCdStreamFlags |= FILE_FLAG_NO_BUFFERING;
|
||||
debug("Using no buffered loading for streaming\n");
|
||||
}
|
||||
|
||||
_gbCdStreamOverlapped = TRUE;
|
||||
|
||||
_gdwCdStreamFlags |= FILE_FLAG_OVERLAPPED;
|
||||
|
||||
_gbCdStreamAsync = FALSE;
|
||||
|
||||
void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, BytesPerSector);
|
||||
ASSERT( pBuffer != NULL );
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
gNumImages = 0;
|
||||
|
||||
gNumChannels = numChannels;
|
||||
|
||||
gpReadInfo = (CdReadInfo *)LocalAlloc(LMEM_ZEROINIT, sizeof(CdReadInfo) * numChannels);
|
||||
ASSERT( gpReadInfo != NULL );
|
||||
|
||||
CDDEBUG("read info %p", gpReadInfo);
|
||||
|
||||
CdStreamAddImage("MODELS\\GTA3.IMG");
|
||||
|
||||
int32 nStatus = CdStreamRead(0, pBuffer, 0, 1);
|
||||
|
||||
CdStreamRemoveImages();
|
||||
|
||||
if ( nStatus == STREAM_SUCCESS )
|
||||
{
|
||||
_gbCdStreamAsync = TRUE;
|
||||
|
||||
debug("Using async loading for streaming\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdwCdStreamFlags &= ~FILE_FLAG_OVERLAPPED;
|
||||
|
||||
_gbCdStreamOverlapped = FALSE;
|
||||
|
||||
_gbCdStreamAsync = TRUE;
|
||||
|
||||
debug("Using sync loading for streaming\n");
|
||||
}
|
||||
|
||||
CdStreamInitThread();
|
||||
|
||||
ASSERT( pBuffer != NULL );
|
||||
RwFreeAlign(pBuffer);
|
||||
}
|
||||
|
||||
uint32
|
||||
GetGTA3ImgSize(void)
|
||||
{
|
||||
ASSERT( gImgFiles[0] != NULL );
|
||||
return (uint32)GetFileSize(gImgFiles[0], NULL);
|
||||
}
|
||||
|
||||
void
|
||||
CdStreamShutdown(void)
|
||||
{
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
LocalFree(gChannelRequestQ.items);
|
||||
CloseHandle(gCdStreamSema);
|
||||
CloseHandle(_gCdStreamThread);
|
||||
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
CloseHandle(gpReadInfo[i].hSemaphore);
|
||||
}
|
||||
|
||||
LocalFree(gpReadInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32
|
||||
CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
ASSERT( buffer != NULL );
|
||||
|
||||
lastPosnRead = size + offset;
|
||||
|
||||
ASSERT( _GET_INDEX(offset) < MAX_CDIMAGES );
|
||||
HANDLE hImage = gImgFiles[_GET_INDEX(offset)];
|
||||
ASSERT( hImage != NULL );
|
||||
|
||||
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != NULL );
|
||||
|
||||
pChannel->hFile = hImage;
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->nSectorsToRead != 0 || pChannel->bInUse )
|
||||
return STREAM_NONE;
|
||||
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
pChannel->nSectorOffset = _GET_OFFSET(offset);
|
||||
pChannel->nSectorsToRead = size;
|
||||
pChannel->pBuffer = buffer;
|
||||
pChannel->bLocked = 0;
|
||||
|
||||
AddToQueue(&gChannelRequestQ, channel);
|
||||
|
||||
if ( !ReleaseSemaphore(gCdStreamSema, 1, NULL) )
|
||||
printf("Signal Sema Error\n");
|
||||
|
||||
return STREAM_SUCCESS;
|
||||
}
|
||||
|
||||
if ( _gbCdStreamOverlapped )
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != NULL );
|
||||
|
||||
pChannel->Overlapped.Offset = _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE;
|
||||
|
||||
if ( !ReadFile(hImage, buffer, size * CDSTREAM_SECTOR_SIZE, NULL, &pChannel->Overlapped)
|
||||
&& GetLastError() != ERROR_IO_PENDING )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_SUCCESS;
|
||||
}
|
||||
|
||||
SetFilePointer(hImage, _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE, NULL, FILE_BEGIN);
|
||||
|
||||
DWORD NumberOfBytesRead;
|
||||
|
||||
if ( !ReadFile(hImage, buffer, size * CDSTREAM_SECTOR_SIZE, &NumberOfBytesRead, NULL) )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_SUCCESS;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamGetStatus(int32 channel)
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != NULL );
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->bInUse )
|
||||
return STREAM_READING;
|
||||
|
||||
if ( pChannel->nSectorsToRead != 0 )
|
||||
return STREAM_WAITING;
|
||||
|
||||
if ( pChannel->nStatus != STREAM_NONE )
|
||||
{
|
||||
int32 status = pChannel->nStatus;
|
||||
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
return STREAM_NONE;
|
||||
}
|
||||
|
||||
if ( _gbCdStreamOverlapped )
|
||||
{
|
||||
ASSERT( pChannel->hFile != NULL );
|
||||
if ( WaitForSingleObjectEx(pChannel->hFile, 0, TRUE) == WAIT_OBJECT_0 )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_READING;
|
||||
}
|
||||
|
||||
return STREAM_NONE;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamGetLastPosn(void)
|
||||
{
|
||||
return lastPosnRead;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamSync(int32 channel)
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != NULL );
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->nSectorsToRead != 0 )
|
||||
{
|
||||
pChannel->bLocked = true;
|
||||
|
||||
ASSERT( pChannel->hSemaphore != NULL );
|
||||
|
||||
WaitForSingleObject(pChannel->hSemaphore, INFINITE);
|
||||
}
|
||||
|
||||
pChannel->bInUse = false;
|
||||
|
||||
return pChannel->nStatus;
|
||||
}
|
||||
|
||||
DWORD NumberOfBytesTransferred;
|
||||
|
||||
if ( _gbCdStreamOverlapped && pChannel->hFile )
|
||||
{
|
||||
ASSERT(pChannel->hFile != NULL );
|
||||
if ( GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_ERROR;
|
||||
}
|
||||
|
||||
return STREAM_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
AddToQueue(Queue *queue, int32 item)
|
||||
{
|
||||
ASSERT( queue != NULL );
|
||||
ASSERT( queue->items != NULL );
|
||||
queue->items[queue->tail] = item;
|
||||
|
||||
queue->tail = (queue->tail + 1) % queue->size;
|
||||
|
||||
if ( queue->head == queue->tail )
|
||||
debug("Queue is full\n");
|
||||
}
|
||||
|
||||
int32
|
||||
GetFirstInQueue(Queue *queue)
|
||||
{
|
||||
ASSERT( queue != NULL );
|
||||
if ( queue->head == queue->tail )
|
||||
return -1;
|
||||
|
||||
ASSERT( queue->items != NULL );
|
||||
return queue->items[queue->head];
|
||||
}
|
||||
|
||||
void
|
||||
RemoveFirstInQueue(Queue *queue)
|
||||
{
|
||||
ASSERT( queue != NULL );
|
||||
if ( queue->head == queue->tail )
|
||||
{
|
||||
debug("Queue is empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
queue->head = (queue->head + 1) % queue->size;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI CdStreamThread(LPVOID lpThreadParameter)
|
||||
{
|
||||
debug("Created cdstream thread\n");
|
||||
|
||||
while ( true )
|
||||
{
|
||||
WaitForSingleObject(gCdStreamSema, INFINITE);
|
||||
|
||||
int32 channel = GetFirstInQueue(&gChannelRequestQ);
|
||||
ASSERT( channel < gNumChannels );
|
||||
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != NULL );
|
||||
|
||||
pChannel->bInUse = true;
|
||||
|
||||
if ( pChannel->nStatus == STREAM_NONE )
|
||||
{
|
||||
if ( _gbCdStreamOverlapped )
|
||||
{
|
||||
pChannel->Overlapped.Offset = pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE;
|
||||
|
||||
ASSERT(pChannel->hFile != NULL );
|
||||
ASSERT(pChannel->pBuffer != NULL );
|
||||
|
||||
DWORD NumberOfBytesTransferred;
|
||||
|
||||
if ( ReadFile(pChannel->hFile,
|
||||
pChannel->pBuffer,
|
||||
pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE,
|
||||
NULL,
|
||||
&pChannel->Overlapped) )
|
||||
{
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
}
|
||||
else if ( GetLastError() == ERROR_IO_PENDING
|
||||
&& GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) )
|
||||
{
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pChannel->nStatus = STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(pChannel->hFile != NULL );
|
||||
ASSERT(pChannel->pBuffer != NULL );
|
||||
|
||||
SetFilePointer(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, NULL, FILE_BEGIN);
|
||||
|
||||
DWORD NumberOfBytesRead;
|
||||
if ( ReadFile(pChannel->hFile,
|
||||
pChannel->pBuffer,
|
||||
pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE,
|
||||
&NumberOfBytesRead,
|
||||
NULL) )
|
||||
{
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoveFirstInQueue(&gChannelRequestQ);
|
||||
|
||||
pChannel->nSectorsToRead = 0;
|
||||
|
||||
if ( pChannel->bLocked )
|
||||
{
|
||||
ASSERT( pChannel->hSemaphore != NULL );
|
||||
ReleaseSemaphore(pChannel->hSemaphore, 1, NULL);
|
||||
}
|
||||
|
||||
pChannel->bInUse = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CdStreamAddImage(char const *path)
|
||||
{
|
||||
ASSERT(path != NULL);
|
||||
ASSERT(gNumImages < MAX_CDIMAGES);
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
gImgFiles[gNumImages] = CreateFile(path,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
_gdwCdStreamFlags | FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_READONLY,
|
||||
NULL);
|
||||
|
||||
ASSERT( gImgFiles[gNumImages] != NULL );
|
||||
if ( gImgFiles[gNumImages] == NULL )
|
||||
return false;
|
||||
|
||||
strcpy(gCdImageNames[gNumImages], path);
|
||||
|
||||
gNumImages++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char *
|
||||
CdStreamGetImageName(int32 cd)
|
||||
{
|
||||
ASSERT(cd < MAX_CDIMAGES);
|
||||
if ( gImgFiles[cd] != NULL )
|
||||
return gCdImageNames[cd];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CdStreamRemoveImages(void)
|
||||
{
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
CdStreamSync(i);
|
||||
|
||||
for ( int32 i = 0; i < gNumImages; i++ )
|
||||
{
|
||||
SetLastError(0);
|
||||
|
||||
CloseHandle(gImgFiles[i]);
|
||||
gImgFiles[i] = NULL;
|
||||
}
|
||||
|
||||
gNumImages = 0;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamGetNumImages(void)
|
||||
{
|
||||
return gNumImages;
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x405B50, CdStreamInitThread, PATCH_JUMP);
|
||||
InjectHook(0x405C80, CdStreamInit, PATCH_JUMP);
|
||||
//InjectHook(0x405DB0, debug, PATCH_JUMP);
|
||||
InjectHook(0x405DC0, GetGTA3ImgSize, PATCH_JUMP);
|
||||
InjectHook(0x405DD0, CdStreamShutdown, PATCH_JUMP);
|
||||
InjectHook(0x405E40, CdStreamRead, PATCH_JUMP);
|
||||
InjectHook(0x405F90, CdStreamGetStatus, PATCH_JUMP);
|
||||
InjectHook(0x406000, CdStreamGetLastPosn, PATCH_JUMP);
|
||||
InjectHook(0x406010, CdStreamSync, PATCH_JUMP);
|
||||
InjectHook(0x4060B0, AddToQueue, PATCH_JUMP);
|
||||
InjectHook(0x4060F0, GetFirstInQueue, PATCH_JUMP);
|
||||
InjectHook(0x406110, RemoveFirstInQueue, PATCH_JUMP);
|
||||
InjectHook(0x406140, CdStreamThread, PATCH_JUMP);
|
||||
InjectHook(0x406270, CdStreamAddImage, PATCH_JUMP);
|
||||
InjectHook(0x4062E0, CdStreamGetImageName, PATCH_JUMP);
|
||||
InjectHook(0x406300, CdStreamRemoveImages, PATCH_JUMP);
|
||||
InjectHook(0x406370, CdStreamGetNumImages, PATCH_JUMP);
|
||||
ENDPATCHES
|
47
src/CdStream.h
Normal file
47
src/CdStream.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#define MAX_CDIMAGES 8
|
||||
#define CDSTREAM_SECTOR_SIZE 2048
|
||||
|
||||
#define _GET_INDEX(a) (a >> 24)
|
||||
#define _GET_OFFSET(a) (a & 0xFFFFFF)
|
||||
|
||||
enum
|
||||
{
|
||||
STREAM_NONE = uint8( 0),
|
||||
STREAM_SUCCESS = uint8( 1),
|
||||
STREAM_READING = uint8(-1), // 0xFF,
|
||||
STREAM_ERROR = uint8(-2), // 0xFE,
|
||||
STREAM_ERROR_NOCD = uint8(-3), // 0xFD,
|
||||
STREAM_ERROR_WRONGCD = uint8(-4), // 0xFC,
|
||||
STREAM_ERROR_OPENCD = uint8(-5), // 0xFB,
|
||||
STREAM_WAITING = uint8(-6) // 0xFA,
|
||||
};
|
||||
|
||||
struct Queue
|
||||
{
|
||||
int32 *items;
|
||||
int32 head;
|
||||
int32 tail;
|
||||
int32 size;
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(Queue, 0x10);
|
||||
|
||||
|
||||
void CdStreamInitThread(void);
|
||||
void CdStreamInit(int32 numChannels);
|
||||
uint32 GetGTA3ImgSize(void);
|
||||
void CdStreamShutdown(void);
|
||||
int32 CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size);
|
||||
int32 CdStreamGetStatus(int32 channel);
|
||||
int32 CdStreamGetLastPosn(void);
|
||||
int32 CdStreamSync(int32 channel);
|
||||
void AddToQueue(Queue *queue, int32 item);
|
||||
int32 GetFirstInQueue(Queue *queue);
|
||||
void RemoveFirstInQueue(Queue *queue);
|
||||
DWORD WINAPI CdStreamThread(LPVOID lpThreadParameter);
|
||||
bool CdStreamAddImage(char const *path);
|
||||
char *CdStreamGetImageName(int32 cd);
|
||||
void CdStreamRemoveImages(void);
|
||||
int32 CdStreamGetNumImages(void);
|
|
@ -1995,7 +1995,10 @@ STARTPATCHES
|
|||
InjectHook(0x492720, CPad::UpdatePads, PATCH_JUMP);
|
||||
InjectHook(0x492C60, &CPad::ProcessPCSpecificStuff, PATCH_JUMP);
|
||||
InjectHook(0x492C70, &CPad::Update, PATCH_JUMP);
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4573)
|
||||
InjectHook(0x492F00, (void (*)())CPad::DoCheats, PATCH_JUMP);
|
||||
#pragma warning( pop )
|
||||
InjectHook(0x492F20, (void (CPad::*)(int16))&CPad::DoCheats, PATCH_JUMP);
|
||||
InjectHook(0x492F30, CPad::StopPadsShaking, PATCH_JUMP);
|
||||
InjectHook(0x492F50, &CPad::StopShaking, PATCH_JUMP);
|
||||
|
|
|
@ -4,6 +4,34 @@
|
|||
#include "TimeCycle.h"
|
||||
#include "skeleton.h"
|
||||
|
||||
void *
|
||||
RwMallocAlign(RwUInt32 size, RwUInt32 align)
|
||||
{
|
||||
void *mem = (void *)malloc(size + align);
|
||||
|
||||
ASSERT(mem != NULL);
|
||||
|
||||
void *addr = (void *)((((RwUInt32)mem) + align) & ~(align - 1));
|
||||
|
||||
ASSERT(addr != NULL);
|
||||
|
||||
*(((void **)addr) - 1) = mem;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
RwFreeAlign(void *mem)
|
||||
{
|
||||
ASSERT(mem != NULL);
|
||||
|
||||
void *addr = *(((void **)mem) - 1);
|
||||
|
||||
ASSERT(addr != NULL);
|
||||
|
||||
free(addr);
|
||||
}
|
||||
|
||||
void
|
||||
DefinedState(void)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
|
||||
void RwFreeAlign(void *mem);
|
||||
|
||||
void DefinedState(void);
|
||||
RwFrame *GetFirstChild(RwFrame *frame);
|
||||
RwObject *GetFirstObject(RwFrame *frame);
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
#include "RpAnimBlend.h"
|
||||
#include "AnimManager.h"
|
||||
#include "AnimBlendAssociation.h"
|
||||
|
||||
// TODO: implement those
|
||||
#define RwFreeAlign RwFree
|
||||
#define RwMallocAlign(sz, algn) RwMalloc(sz)
|
||||
#include "RwHelper.h"
|
||||
|
||||
CAnimBlendAssociation::CAnimBlendAssociation(void)
|
||||
{
|
||||
|
@ -57,6 +54,7 @@ CAnimBlendAssociation::AllocateAnimBlendNodeArray(int n)
|
|||
void
|
||||
CAnimBlendAssociation::FreeAnimBlendNodeArray(void)
|
||||
{
|
||||
ASSERT( nodes != NULL );
|
||||
RwFreeAlign(nodes);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "AnimBlendClumpData.h"
|
||||
#include "RwHelper.h"
|
||||
|
||||
// TODO: implement those
|
||||
#define RwFreeAlign RwFree
|
||||
#define RwMallocAlign(sz, algn) RwMalloc(sz)
|
||||
|
||||
CAnimBlendClumpData::CAnimBlendClumpData(void)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue