mirror of
https://github.com/gligli/nulldc-360.git
synced 2025-04-02 11:11:56 -04:00
234 lines
No EOL
5.2 KiB
C++
234 lines
No EOL
5.2 KiB
C++
/*
|
|
Locking code for pvr plugins
|
|
Was never finished
|
|
Works for 64bit area locks
|
|
*/
|
|
#include "plugins/plugin_manager.h"
|
|
#include "pvrLock.h"
|
|
|
|
using namespace std;
|
|
|
|
vector<vram_block*> VramLocks[VRAM_SIZE/PAGE_SIZE];
|
|
//vram 32-64b
|
|
VArray2 vram;
|
|
|
|
|
|
//Address space convertion functions
|
|
void vramlock_Read32b(u32* pdst,u32 offset,u32 len)
|
|
{
|
|
//TODO:implement .. later
|
|
}
|
|
|
|
//mmx version , 2x64bit at a time
|
|
//pdst needs to be 16 byte aligned
|
|
void vramlock_Read32b_mmx(u32* pdst,u32 offset,u32 len)
|
|
{
|
|
//TODO:implement .. later
|
|
}
|
|
|
|
//sse version , 2x128bit at a time
|
|
//pdst needs to be 16 byte aligned
|
|
void vramlock_Read32b_sse(u32* pdst,u32 offset,u32 len)
|
|
{
|
|
//TODO:implement .. later
|
|
}
|
|
|
|
|
|
|
|
//So, the bytes 0xA4000000-0xA4000003 correspond to 0xA5000000-0xA5000003, 0xA4000004-0xA4000007 to 0xA5400000-0xA5400003,
|
|
//0xA4000008-0xA400000B to 0xA5000004-0xA5000007 and so on.
|
|
//
|
|
//
|
|
//Convert Sh4 address to vram_32 offset
|
|
|
|
//Convert offset32 to offset64
|
|
u32 vramlock_ConvOffset32toOffset64(u32 offset32)
|
|
{
|
|
//64b wide bus is archevied by interleaving the banks every 32 bits
|
|
//so bank is Address<<3
|
|
//bits <4 are <<1 to create space for bank num
|
|
//bank 0 is mapped at 400000 (32b offset) and after
|
|
const u32 bank_bit=VRAM_MASK-(VRAM_MASK/2);
|
|
const u32 static_bits=(VRAM_MASK-(bank_bit*2)+1)|3;
|
|
const u32 moved_bits=VRAM_MASK-static_bits-bank_bit;
|
|
|
|
u32 bank=(offset32&bank_bit)/bank_bit*4;//bank will be used as uper offset too
|
|
u32 lv=offset32&static_bits; //these will survive
|
|
offset32&=moved_bits;
|
|
offset32<<=1;
|
|
// |inbank offset | bank id | lower 2 bits (not changed)
|
|
u32 rv= offset32 + bank + lv;
|
|
|
|
return rv;
|
|
}
|
|
//Convert Sh4 address to vram_64 offset
|
|
u32 vramlock_ConvAddrtoOffset64(u32 Address)
|
|
{
|
|
if (Is_64_Bit(Address))
|
|
{
|
|
return Address & VRAM_MASK;//64 bit offset
|
|
}
|
|
else
|
|
{
|
|
return vramlock_ConvOffset32toOffset64(Address);
|
|
}
|
|
}
|
|
//List functions
|
|
//
|
|
void vramlock_list_remove(vram_block* block)
|
|
{
|
|
u32 base = block->start >> PAGE_SHIFT;
|
|
u32 end = block->end >> PAGE_SHIFT;
|
|
|
|
for (u32 i=base;i<=end;i++)
|
|
{
|
|
vector<vram_block*>* list=&VramLocks[i];
|
|
for (size_t j=0;j<list->size();j++)
|
|
{
|
|
if ((*list)[j]==block)
|
|
{
|
|
(*list)[j]=0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vramlock_list_add(vram_block* block)
|
|
{
|
|
u32 base = block->start >> PAGE_SHIFT;
|
|
u32 end = block->end >> PAGE_SHIFT;
|
|
|
|
|
|
for (u32 i=base;i<=end;i++)
|
|
{
|
|
vector<vram_block*>* list=&VramLocks[i];
|
|
for (u32 j=0;j<list->size();j++)
|
|
{
|
|
if ((*list)[j]==0)
|
|
{
|
|
(*list)[j]=block;
|
|
goto added_it;
|
|
}
|
|
}
|
|
|
|
list->push_back(block);
|
|
added_it:
|
|
__noop;
|
|
}
|
|
}
|
|
|
|
//simple IsInRange test
|
|
inline bool IsInRange(vram_block* block,u32 offset)
|
|
{
|
|
return (block->start<=offset) && (block->end>=offset);
|
|
}
|
|
|
|
//returns block handle
|
|
vram_block* FASTCALL vramlock_Lock_32(u32 start_offset32,u32 end_offset32,void* userdata)
|
|
{
|
|
vram_block* block=(vram_block*)malloc(sizeof(vram_block));
|
|
|
|
block->end=end_offset32;
|
|
block->start=start_offset32;
|
|
block->len=end_offset32-start_offset32+1;
|
|
block->userdata=userdata;
|
|
block->type=32;
|
|
|
|
//okz , new idea
|
|
//asuming locks are 4 byte alligned (textures have to be 4 byte aligned too , dont they ?
|
|
// anyhow , fb is 32b alligned and locks are 4kb aligned
|
|
// so it doesnt matter)
|
|
//32b to 64b maping goes 2:1
|
|
//so we can do
|
|
//lock(bank1,size>>1);lock(bank2,size>>1);
|
|
|
|
/*for (u32 base=start_offset32;base<end_offset32;base+=4)
|
|
{
|
|
SetVramTest_32(vramlock_ConvOffset32toOffset64(base));
|
|
}
|
|
|
|
for (u32 base=block->start;base<block->end;base+=4)
|
|
{
|
|
vramlock_list_add(block,&vram_locks[GetHash(vramlock_ConvOffset32toOffset64(base))]);
|
|
}*/
|
|
|
|
return block;
|
|
}
|
|
|
|
vram_block* FASTCALL vramlock_Lock_64(u32 start_offset64,u32 end_offset64,void* userdata)
|
|
{
|
|
vram_block* block=(vram_block* )malloc(sizeof(vram_block));
|
|
|
|
|
|
if (end_offset64>(VRAM_SIZE-1))
|
|
{
|
|
msgboxf("vramlock_Lock_64: end_offset64>(VRAM_SIZE-1) \n Tried to lock area out of vram , possibly bug on the pvr plugin",MBX_OK);
|
|
end_offset64=(VRAM_SIZE-1);
|
|
}
|
|
|
|
if (start_offset64>end_offset64)
|
|
{
|
|
msgboxf("vramlock_Lock_64: start_offset64>end_offset64 \n Tried to lock negative block , possibly bug on the pvr plugin",MBX_OK);
|
|
start_offset64=0;
|
|
}
|
|
|
|
|
|
|
|
block->end=end_offset64;
|
|
block->start=start_offset64;
|
|
block->len=end_offset64-start_offset64+1;
|
|
block->userdata=userdata;
|
|
block->type=64;
|
|
|
|
vram.LockRegion(block->start,block->len);
|
|
vramlock_list_add(block);
|
|
|
|
return block;
|
|
}
|
|
|
|
bool VramLockedWrite(u8* address)
|
|
{
|
|
size_t offset=address-vram.data;
|
|
|
|
if (offset<VRAM_SIZE)
|
|
{
|
|
size_t addr_hash = offset >> PAGE_SHIFT;
|
|
vector<vram_block*>* list=&VramLocks[addr_hash];
|
|
|
|
for (size_t i=0;i<list->size();i++)
|
|
{
|
|
if ((*list)[i])
|
|
{
|
|
libPvr.LockedBlockWrite((*list)[i],(u32)offset);
|
|
|
|
if ((*list)[i])
|
|
{
|
|
msgboxf("Error , pvr is suposed to remove lock",MBX_OK);
|
|
__debugbreak();
|
|
}
|
|
|
|
}
|
|
}
|
|
list->clear();
|
|
vram.UnLockRegion((u32)offset&(~(PAGE_SIZE-1)),PAGE_SIZE);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
//unlocks mem
|
|
//also frees the handle
|
|
void FASTCALL vramlock_Unlock_block(vram_block* block)
|
|
{
|
|
//VRAM_SIZE/PAGE_SIZE;
|
|
if (block->end>VRAM_SIZE)
|
|
msgboxf("Error : block end is after vram , skiping unlock",MBX_OK);
|
|
else
|
|
{
|
|
vramlock_list_remove(block);
|
|
//more work needed
|
|
free(block);
|
|
}
|
|
} |