2013-11-09 02:05:58 +01:00
# include "stdafx.h"
2018-07-27 21:07:34 +02:00
# include "Emu/Memory/vm.h"
2014-06-02 19:27:24 +02:00
# include "Emu/System.h"
2017-07-26 04:57:43 +02:00
# include "Emu/Cell/PPUModule.h"
# include "Emu/RSX/GSRender.h"
# include "Emu/IdManager.h"
2016-04-14 00:23:53 +02:00
# include "Emu/Cell/ErrorCodes.h"
2014-06-25 00:38:34 +02:00
# include "sys_rsx.h"
2017-07-26 04:57:43 +02:00
# include "sys_event.h"
2013-11-09 02:05:58 +01:00
2018-02-09 15:49:37 +01:00
2018-08-25 14:39:00 +02:00
LOG_CHANNEL ( sys_rsx ) ;
2013-11-09 02:05:58 +01:00
2017-07-26 04:57:43 +02:00
extern u64 get_timebased_time ( ) ;
u64 rsxTimeStamp ( ) {
return get_timebased_time ( ) ;
}
2014-06-25 00:38:34 +02:00
s32 sys_rsx_device_open ( )
2013-11-09 02:05:58 +01:00
{
2016-01-12 22:57:16 +01:00
sys_rsx . todo ( " sys_rsx_device_open() " ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-06-25 00:38:34 +02:00
s32 sys_rsx_device_close ( )
2013-11-09 02:05:58 +01:00
{
2016-01-12 22:57:16 +01:00
sys_rsx . todo ( " sys_rsx_device_close() " ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 668 ( 0x29C ) : sys_rsx_memory_allocate
* @ param mem_handle ( OUT ) : Context / ID , which is used by sys_rsx_memory_free to free allocated memory .
* @ param mem_addr ( OUT ) : Returns the local memory base address , usually 0xC0000000 .
* @ param size ( IN ) : Local memory size . E . g . 0x0F900000 ( 249 MB ) .
* @ param flags ( IN ) : E . g . Immediate value passed in cellGcmSys is 8.
* @ param a5 ( IN ) : E . g . Immediate value passed in cellGcmSys is 0x00300000 ( 3 MB ? ) .
2018-02-09 15:49:37 +01:00
* @ param a6 ( IN ) : E . g . Immediate value passed in cellGcmSys is 16.
2014-08-16 23:45:56 +02:00
* @ param a7 ( IN ) : E . g . Immediate value passed in cellGcmSys is 8.
*/
2015-07-11 01:38:40 +02:00
s32 sys_rsx_memory_allocate ( vm : : ptr < u32 > mem_handle , vm : : ptr < u64 > mem_addr , u32 size , u64 flags , u64 a5 , u64 a6 , u64 a7 )
2013-11-09 02:05:58 +01:00
{
2017-07-26 04:57:43 +02:00
sys_rsx . warning ( " sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx) " , mem_handle , mem_addr , size , flags , a5 , a6 , a7 ) ;
2018-05-19 12:07:59 +02:00
* mem_handle = 0x5a5a5a5b ;
2017-07-26 04:57:43 +02:00
* mem_addr = vm : : falloc ( 0xC0000000 , size , vm : : video ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 669 ( 0x29D ) : sys_rsx_memory_free
* @ param mem_handle ( OUT ) : Context / ID , for allocated local memory generated by sys_rsx_memory_allocate
*/
s32 sys_rsx_memory_free ( u32 mem_handle )
2013-11-09 02:05:58 +01:00
{
2016-01-12 22:57:16 +01:00
sys_rsx . todo ( " sys_rsx_memory_free(mem_handle=0x%x) " , mem_handle ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 670 ( 0x29E ) : sys_rsx_context_allocate
2014-08-25 23:17:51 +02:00
* @ param context_id ( OUT ) : RSX context , E . g . 0x55555555 ( in vsh . self )
2014-08-16 23:45:56 +02:00
* @ param lpar_dma_control ( OUT ) : Control register area . E . g . 0x60100000 ( in vsh . self )
* @ param lpar_driver_info ( OUT ) : RSX data like frequencies , sizes , version . . . E . g . 0x60200000 ( in vsh . self )
* @ param lpar_reports ( OUT ) : Report data area . E . g . 0x60300000 ( in vsh . self )
* @ param mem_ctx ( IN ) : mem_ctx given by sys_rsx_memory_allocate
* @ param system_mode ( IN ) :
*/
2017-07-26 04:57:43 +02:00
s32 sys_rsx_context_allocate ( vm : : ptr < u32 > context_id , vm : : ptr < u64 > lpar_dma_control , vm : : ptr < u64 > lpar_driver_info , vm : : ptr < u64 > lpar_reports , u64 mem_ctx , u64 system_mode )
2013-11-09 02:05:58 +01:00
{
2017-07-26 04:57:43 +02:00
sys_rsx . warning ( " sys_rsx_context_allocate(context_id=*0x%x, lpar_dma_control=*0x%x, lpar_driver_info=*0x%x, lpar_reports=*0x%x, mem_ctx=0x%llx, system_mode=0x%llx) " ,
2015-07-11 01:38:40 +02:00
context_id , lpar_dma_control , lpar_driver_info , lpar_reports , mem_ctx , system_mode ) ;
2014-08-16 23:45:56 +02:00
2018-06-02 17:59:52 +02:00
auto m_sysrsx = fxm : : get < SysRsxConfig > ( ) ;
2017-07-26 04:57:43 +02:00
2018-06-02 17:59:52 +02:00
if ( ! m_sysrsx ) // TODO: check if called twice
return CELL_EINVAL ;
2017-07-26 04:57:43 +02:00
* context_id = 0x55555555 ;
2018-06-02 17:59:52 +02:00
* lpar_dma_control = m_sysrsx - > rsx_context_addr + 0x100000 ;
* lpar_driver_info = m_sysrsx - > rsx_context_addr + 0x200000 ;
* lpar_reports = m_sysrsx - > rsx_context_addr + 0x300000 ;
2017-07-26 04:57:43 +02:00
auto & reports = vm : : _ref < RsxReports > ( * lpar_reports ) ;
std : : memset ( & reports , 0 , sizeof ( RsxReports ) ) ;
for ( int i = 0 ; i < 64 ; + + i )
reports . notify [ i ] . timestamp = ( u64 ) - 1 ;
for ( int i = 0 ; i < 256 ; + + i ) {
reports . semaphore [ i ] . val = 0x1337C0D3 ;
reports . semaphore [ i ] . pad = 0x1337BABE ;
reports . semaphore [ i ] . timestamp = ( u64 ) - 1 ; // technically different but should be fine
}
for ( int i = 0 ; i < 2048 ; + + i )
reports . report [ i ] . timestamp = ( u64 ) - 1 ;
auto & driverInfo = vm : : _ref < RsxDriverInfo > ( * lpar_driver_info ) ;
std : : memset ( & driverInfo , 0 , sizeof ( RsxDriverInfo ) ) ;
driverInfo . version_driver = 0x211 ;
driverInfo . version_gpu = 0x5c ;
driverInfo . memory_size = 0xFE00000 ;
driverInfo . nvcore_frequency = 500000000 ; // 0x1DCD6500
driverInfo . memory_frequency = 650000000 ; // 0x26BE3680
driverInfo . reportsNotifyOffset = 0x1000 ;
driverInfo . reportsOffset = 0 ;
driverInfo . reportsReportOffset = 0x1400 ;
driverInfo . systemModeFlags = system_mode ;
driverInfo . hardware_channel = 1 ; // * i think* this 1 for games, 0 for vsh
m_sysrsx - > driverInfo = * lpar_driver_info ;
auto & dmaControl = vm : : _ref < RsxDmaControl > ( * lpar_dma_control ) ;
dmaControl . get = 0 ;
dmaControl . put = 0 ;
dmaControl . ref = 0xFFFFFFFF ;
2018-08-20 12:44:37 +02:00
memset ( & RSXIOMem , 0xFF , sizeof ( RSXIOMem ) ) ;
2018-07-27 21:07:34 +02:00
2017-07-26 04:57:43 +02:00
if ( false /*system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB*/ )
2018-07-27 21:07:34 +02:00
rsx : : get_current_renderer ( ) - > main_mem_size = 0x20000000 ; //512MB
2017-07-26 04:57:43 +02:00
else
2018-07-27 21:07:34 +02:00
rsx : : get_current_renderer ( ) - > main_mem_size = 0x10000000 ; //256MB
2017-07-26 04:57:43 +02:00
2018-09-03 14:09:09 +02:00
vm : : var < sys_event_queue_attribute_t > attr ;
attr - > protocol = SYS_SYNC_PRIORITY ;
attr - > type = SYS_PPU_QUEUE ;
attr - > name_u64 = 0 ;
vm : : var < u32 > queueId ( 0 ) ;
sys_event_queue_create ( queueId , attr , 0 , 0x20 ) ;
2017-07-26 04:57:43 +02:00
driverInfo . handler_queue = queueId - > value ( ) ;
sys_event_port_create ( queueId , SYS_EVENT_PORT_LOCAL , 0 ) ;
sys_event_port_connect_local ( queueId - > value ( ) , driverInfo . handler_queue ) ;
m_sysrsx - > rsx_event_port = queueId - > value ( ) ;
2018-05-10 13:50:32 +02:00
const auto render = rsx : : get_current_renderer ( ) ;
2017-07-26 04:57:43 +02:00
render - > display_buffers_count = 0 ;
render - > current_display_buffer = 0 ;
render - > main_mem_addr = 0 ;
render - > label_addr = * lpar_reports ;
2018-06-02 17:59:52 +02:00
render - > ctxt_addr = m_sysrsx - > rsx_context_addr ;
2017-07-26 04:57:43 +02:00
render - > init ( 0 , 0 , * lpar_dma_control , 0xC0000000 ) ;
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 671 ( 0x29F ) : sys_rsx_context_free
2014-08-25 23:17:51 +02:00
* @ param context_id ( IN ) : RSX context generated by sys_rsx_context_allocate to free the context .
2014-08-16 23:45:56 +02:00
*/
s32 sys_rsx_context_free ( u32 context_id )
2013-11-09 02:05:58 +01:00
{
2016-01-12 22:57:16 +01:00
sys_rsx . todo ( " sys_rsx_context_free(context_id=0x%x) " , context_id ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-08-25 23:17:51 +02:00
/*
* lv2 SysCall 672 ( 0x2A0 ) : sys_rsx_context_iomap
* @ param context_id ( IN ) : RSX context , E . g . 0x55555555 ( in vsh . self )
* @ param io ( IN ) : IO offset mapping area . E . g . 0x00600000
* @ param ea ( IN ) : Start address of mapping area . E . g . 0x20400000
* @ param size ( IN ) : Size of mapping area in bytes . E . g . 0x00200000
* @ param flags ( IN ) :
*/
s32 sys_rsx_context_iomap ( u32 context_id , u32 io , u32 ea , u32 size , u64 flags )
2013-11-09 02:05:58 +01:00
{
2017-07-26 04:57:43 +02:00
sys_rsx . warning ( " sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx) " , context_id , io , ea , size , flags ) ;
2018-05-19 14:46:29 +02:00
2018-07-27 21:07:34 +02:00
if ( ! size | | io & 0xFFFFF | | ea & 0xFFFFF | | size & 0xFFFFF
| | rsx : : get_current_renderer ( ) - > main_mem_size < io + size )
2018-05-19 14:46:29 +02:00
{
return CELL_EINVAL ;
}
2018-07-27 21:07:34 +02:00
io > > = 20 , ea > > = 20 , size > > = 20 ;
for ( u32 i = 0 ; i < size ; i + + )
{
RSXIOMem . io [ ea + i ] = io + i ;
RSXIOMem . ea [ io + i ] = ea + i ;
}
2018-05-19 14:46:29 +02:00
return CELL_OK ;
2013-11-09 02:05:58 +01:00
}
2014-08-25 23:17:51 +02:00
/*
* lv2 SysCall 673 ( 0x2A1 ) : sys_rsx_context_iounmap
* @ param context_id ( IN ) : RSX context , E . g . 0x55555555 ( in vsh . self )
2018-07-27 21:07:34 +02:00
* @ param io ( IN ) : IO address . E . g . 0x00600000 ( Start page 6 )
2014-08-25 23:17:51 +02:00
* @ param size ( IN ) : Size to unmap in byte . E . g . 0x00200000
*/
2018-07-27 21:07:34 +02:00
s32 sys_rsx_context_iounmap ( u32 context_id , u32 io , u32 size )
2013-11-09 02:05:58 +01:00
{
2018-07-27 21:07:34 +02:00
sys_rsx . warning ( " sys_rsx_context_iounmap(context_id=0x%x, io=0x%x, size=0x%x) " , context_id , io , size ) ;
if ( ! size | | rsx : : get_current_renderer ( ) - > main_mem_size < io + size )
{
return CELL_EINVAL ;
}
const u32 end = ( io > > = 20 ) + ( size > > = 20 ) ;
2018-08-13 18:15:56 +02:00
for ( u32 ea = RSXIOMem . ea [ io ] ; io < end ; )
2018-07-27 21:07:34 +02:00
{
RSXIOMem . io [ ea + + ] = 0xFFFF ;
RSXIOMem . ea [ io + + ] = 0xFFFF ;
}
return CELL_OK ;
2013-11-09 02:05:58 +01:00
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 674 ( 0x2A2 ) : sys_rsx_context_attribute
* @ param context_id ( IN ) : RSX context , e . g . 0x55555555
2017-07-26 04:57:43 +02:00
* @ param package_id ( IN ) :
* @ param a3 ( IN ) :
* @ param a4 ( IN ) :
* @ param a5 ( IN ) :
* @ param a6 ( IN ) :
2014-08-16 23:45:56 +02:00
*/
s32 sys_rsx_context_attribute ( s32 context_id , u32 package_id , u64 a3 , u64 a4 , u64 a5 , u64 a6 )
2013-11-09 02:05:58 +01:00
{
2017-07-26 04:57:43 +02:00
// Flip/queue/user command/vblank as trace to help with log spam
if ( package_id = = 0x102 | | package_id = = 0x103 | | package_id = = 0xFED | | package_id = = 0xFEF )
sys_rsx . trace ( " sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx) " , context_id , package_id , a3 , a4 , a5 , a6 ) ;
else
sys_rsx . warning ( " sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx) " , context_id , package_id , a3 , a4 , a5 , a6 ) ;
// todo: these event ports probly 'shouldnt' be here as i think its supposed to be interrupts that are sent from rsx somewhere in lv1
2018-05-10 13:50:32 +02:00
const auto render = rsx : : get_current_renderer ( ) ;
2017-07-26 04:57:43 +02:00
//hle protection
if ( render - > isHLE )
return 0 ;
2014-08-16 23:45:56 +02:00
2017-07-26 04:57:43 +02:00
auto m_sysrsx = fxm : : get < SysRsxConfig > ( ) ;
2017-09-10 20:05:39 +02:00
if ( ! m_sysrsx )
{
sys_rsx . error ( " sys_rsx_context_attribute called before sys_rsx_context_allocate: context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx) " , context_id , package_id , a3 , a4 , a5 , a6 ) ;
return CELL_EINVAL ;
}
2017-07-26 04:57:43 +02:00
auto & driverInfo = vm : : _ref < RsxDriverInfo > ( m_sysrsx - > driverInfo ) ;
switch ( package_id )
2014-08-16 23:45:56 +02:00
{
2014-08-18 16:37:23 +02:00
case 0x001 : // FIFO
2017-12-09 11:14:00 +01:00
render - > pause ( ) ;
2017-07-26 04:57:43 +02:00
render - > ctrl - > get = a3 ;
render - > ctrl - > put = a4 ;
2017-09-15 00:59:00 +02:00
render - > internal_get = a3 ;
2018-01-01 09:43:06 +01:00
render - > restore_point = a3 ;
2017-12-09 11:14:00 +01:00
render - > unpause ( ) ;
2014-08-18 16:37:23 +02:00
break ;
2017-07-26 04:57:43 +02:00
2014-08-18 16:37:23 +02:00
case 0x100 : // Display mode set
break ;
2017-07-26 04:57:43 +02:00
case 0x101 : // Display sync set, cellGcmSetFlipMode
// a4 == 2 is vsync, a4 == 1 is hsync
render - > requested_vsync . store ( a4 = = 2 ) ;
2014-08-18 16:37:23 +02:00
break ;
case 0x102 : // Display flip
2017-07-26 04:57:43 +02:00
driverInfo . head [ a3 ] . flipFlags | = 0x80000000 ;
driverInfo . head [ a3 ] . lastFlipTime = rsxTimeStamp ( ) ; // should rsxthread set this?
// lets give this a shot for giving bufferid back to gcm
driverInfo . head [ a3 ] . flipBufferId = driverInfo . head [ a3 ] . queuedBufferId ;
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
2018-06-02 17:59:52 +02:00
vm : : _ref < u32 > ( render - > label_addr + 0x10 ) = 0 ;
2017-07-26 04:57:43 +02:00
if ( a3 = = 0 )
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 3 ) , 0 ) ;
if ( a3 = = 1 )
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 4 ) , 0 ) ;
2014-08-16 23:45:56 +02:00
break ;
2017-07-26 04:57:43 +02:00
case 0x103 : // Display Queue
driverInfo . head [ a3 ] . queuedBufferId = a4 ;
driverInfo . head [ a3 ] . flipFlags | = 0x40000000 | ( 1 < < a4 ) ;
if ( a3 = = 0 )
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 5 ) , 0 ) ;
if ( a3 = = 1 )
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 6 ) , 0 ) ;
2014-08-16 23:45:56 +02:00
break ;
case 0x104 : // Display buffer
2017-07-26 04:57:43 +02:00
{
u8 id = a3 & 0xFF ;
u32 width = ( a4 > > 32 ) & 0xFFFFFFFF ;
u32 height = a4 & 0xFFFFFFFF ;
u32 pitch = ( a5 > > 32 ) & 0xFFFFFFFF ;
u32 offset = a5 & 0xFFFFFFFF ;
if ( id > 7 )
return - 17 ;
render - > display_buffers [ id ] . width = width ;
render - > display_buffers [ id ] . height = height ;
render - > display_buffers [ id ] . pitch = pitch ;
render - > display_buffers [ id ] . offset = offset ;
render - > display_buffers_count = std : : max ( ( u32 ) id + 1 , render - > display_buffers_count ) ;
}
break ;
case 0x105 : // destroy buffer?
2014-08-16 23:45:56 +02:00
break ;
2014-08-18 16:37:23 +02:00
case 0x106 : // ? (Used by cellGcmInitPerfMon)
break ;
2017-07-26 04:57:43 +02:00
case 0x108 : // cellGcmSetSecondVFrequency
// a4 == 3, CELL_GCM_DISPLAY_FREQUENCY_59_94HZ
// a4 == 2, CELL_GCM_DISPLAY_FREQUENCY_SCANOUT
// a4 == 4, CELL_GCM_DISPLAY_FREQUENCY_DISABLE
// Note: Scanout/59_94 is ignored currently as we report refresh rate of 59_94hz as it is, so the difference doesnt matter
render - > enable_second_vhandler . store ( a4 ! = 4 ) ;
break ;
case 0x10a : // ? Involved in managing flip status through cellGcmResetFlipStatus
{
if ( a3 > 7 )
return - 17 ;
u32 flipStatus = driverInfo . head [ a3 ] . flipFlags ;
flipStatus = ( flipStatus & a4 ) | a5 ;
driverInfo . head [ a3 ] . flipFlags = flipStatus ;
}
break ;
2014-08-18 16:37:23 +02:00
2017-07-26 04:57:43 +02:00
case 0x10D : // Called by cellGcmInitCursor
2014-08-16 23:45:56 +02:00
break ;
case 0x300 : // Tiles
2017-07-26 04:57:43 +02:00
{
//a4 high bits = ret.tile = (location + 1) | (bank << 4) | ((offset / 0x10000) << 16) | (location << 31);
//a4 low bits = ret.limit = ((offset + size - 1) / 0x10000) << 16 | (location << 31);
//a5 high bits = ret.pitch = (pitch / 0x100) << 8;
//a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30);
auto & tile = render - > tiles [ a3 ] ;
2018-02-09 15:49:37 +01:00
// When tile is going to be unbinded, we can use it as a hint that the address will no longer be used as a surface and can be removed/invalidated
2017-10-26 05:01:10 +02:00
// Todo: There may be more checks such as format/size/width can could be done
if ( tile . binded & & a5 = = 0 )
render - > notify_tile_unbound ( a3 ) ;
2017-07-26 04:57:43 +02:00
tile . location = ( ( a4 > > 32 ) & 0xF ) - 1 ;
tile . offset = ( ( ( ( a4 > > 32 ) & 0xFFFFFFFF ) > > 16 ) * 0x10000 ) ;
tile . size = ( ( ( ( a4 & 0x7FFFFFFF ) > > 16 ) + 1 ) * 0x10000 ) - tile . offset ;
tile . pitch = ( ( ( a5 > > 32 ) & 0xFFFFFFFF ) > > 8 ) * 0x100 ;
tile . comp = ( ( a5 & 0xFFFFFFFF ) > > 26 ) & 0xF ;
tile . base = ( a5 & 0xFFFFFFFF ) & 0x7FF ;
tile . bank = ( ( ( a4 > > 32 ) & 0xFFFFFFFF ) > > 4 ) & 0xF ;
tile . binded = a5 ! = 0 ;
}
break ;
2014-08-16 23:45:56 +02:00
case 0x301 : // Depth-buffer (Z-cull)
2017-07-27 18:04:55 +02:00
{
//a4 high = region = (1 << 0) | (zFormat << 4) | (aaFormat << 8);
//a4 low = size = ((width >> 6) << 22) | ((height >> 6) << 6);
//a5 high = start = cullStart&(~0xFFF);
//a5 low = offset = offset;
//a6 high = status0 = (zcullDir << 1) | (zcullFormat << 2) | ((sFunc & 0xF) << 12) | (sRef << 16) | (sMask << 24);
//a6 low = status1 = (0x2000 << 0) | (0x20 << 16);
auto & zcull = render - > zculls [ a3 ] ;
zcull . zFormat = ( ( a4 > > 32 ) > > 4 ) & 0xF ;
zcull . aaFormat = ( ( a4 > > 32 ) > > 8 ) & 0xF ;
zcull . width = ( ( a4 & 0xFFFFFFFF ) > > 22 ) < < 6 ;
zcull . height = ( ( ( a4 & 0xFFFFFFFF ) > > 6 ) & 0xFF ) < < 6 ;
zcull . cullStart = ( a5 > > 32 ) ;
zcull . offset = ( a5 & 0xFFFFFFFF ) ;
2017-08-18 20:10:21 +02:00
zcull . zcullDir = ( ( a6 > > 32 ) > > 1 ) & 0x1 ;
zcull . zcullFormat = ( ( a6 > > 32 ) > > 2 ) & 0x3FF ;
zcull . sFunc = ( ( a6 > > 32 ) > > 12 ) & 0xF ;
zcull . sRef = ( ( a6 > > 32 ) > > 16 ) & 0xFF ;
zcull . sMask = ( ( a6 > > 32 ) > > 24 ) & 0xFF ;
2017-07-27 18:04:55 +02:00
zcull . binded = ( a6 & 0xFFFFFFFF ) ! = 0 ;
}
break ;
2017-07-26 04:57:43 +02:00
case 0x302 : // something with zcull
break ;
2014-08-18 16:37:23 +02:00
case 0x600 : // Framebuffer setup
2014-08-17 11:22:36 +02:00
break ;
2014-08-18 16:37:23 +02:00
case 0x601 : // Framebuffer blit
break ;
case 0x602 : // Framebuffer blit sync
break ;
2017-07-26 04:57:43 +02:00
case 0x603 : // Framebuffer close
break ;
case 0xFED : // hack: vblank command
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
driverInfo . head [ a3 ] . vBlankCount + + ;
driverInfo . head [ a3 ] . lastSecondVTime = rsxTimeStamp ( ) ;
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 1 ) , 0 ) ;
if ( render - > enable_second_vhandler )
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 11 ) , 0 ) ; // second vhandler
break ;
case 0xFEF : // hack: user command
2018-02-09 15:49:37 +01:00
// 'custom' invalid package id for now
2017-07-26 04:57:43 +02:00
// as i think we need custom lv1 interrupts to handle this accurately
// this also should probly be set by rsxthread
driverInfo . userCmdParam = a4 ;
sys_event_port_send ( m_sysrsx - > rsx_event_port , 0 , ( 1 < < 7 ) , 0 ) ;
break ;
2014-08-18 16:37:23 +02:00
default :
return CELL_EINVAL ;
2014-08-16 23:45:56 +02:00
}
2014-08-18 16:37:23 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 675 ( 0x2A3 ) : sys_rsx_device_map
2018-06-02 17:59:52 +02:00
* @ param a1 ( OUT ) : rsx device map address : 0x40000000 , 0x50000000 . . 0xB0000000
2014-08-16 23:45:56 +02:00
* @ param a2 ( OUT ) : Unused ?
2014-08-18 16:37:23 +02:00
* @ param dev_id ( IN ) : An immediate value and always 8. ( cellGcmInitPerfMon uses 11 , 10 , 9 , 7 , 12 successively ) .
2014-08-16 23:45:56 +02:00
*/
2018-06-02 17:59:52 +02:00
s32 sys_rsx_device_map ( vm : : ptr < u64 > dev_addr , vm : : ptr < u64 > a2 , u32 dev_id )
2013-11-09 02:05:58 +01:00
{
2018-06-02 17:59:52 +02:00
sys_rsx . warning ( " sys_rsx_device_map(dev_addr=*0x%x, a2=*0x%x, dev_id=0x%x) " , dev_addr , a2 , dev_id ) ;
2014-08-16 23:45:56 +02:00
2017-07-26 04:57:43 +02:00
if ( dev_id ! = 8 ) {
2018-02-09 15:49:37 +01:00
// TODO: lv1 related
2017-07-26 04:57:43 +02:00
fmt : : throw_exception ( " sys_rsx_device_map: Invalid dev_id %d " , dev_id ) ;
2014-08-16 23:45:56 +02:00
}
2018-05-19 08:44:06 +02:00
// a2 seems to not be referenced in cellGcmSys, tests show this arg is ignored
//*a2 = 0;
2017-07-26 04:57:43 +02:00
2018-06-02 17:59:52 +02:00
auto m_sysrsx = fxm : : make < SysRsxConfig > ( ) ;
2014-08-16 23:45:56 +02:00
2018-06-02 17:59:52 +02:00
if ( ! m_sysrsx )
{
return CELL_EINVAL ; // sys_rsx_device_map called twice
}
2018-08-13 18:15:56 +02:00
if ( const auto area = vm : : find_map ( 0x10000000 , 0x10000000 , 0x403 ) )
2018-06-02 17:59:52 +02:00
{
2018-08-13 18:15:56 +02:00
vm : : falloc ( area - > addr , 0x400000 ) ;
m_sysrsx - > rsx_context_addr = * dev_addr = area - > addr ;
return CELL_OK ;
2018-06-02 17:59:52 +02:00
}
return CELL_ENOMEM ;
2013-11-09 02:05:58 +01:00
}
2014-08-16 23:45:56 +02:00
/*
* lv2 SysCall 676 ( 0x2A4 ) : sys_rsx_device_unmap
* @ param dev_id ( IN ) : An immediate value and always 8.
*/
s32 sys_rsx_device_unmap ( u32 dev_id )
2013-11-09 02:05:58 +01:00
{
2016-01-12 22:57:16 +01:00
sys_rsx . todo ( " sys_rsx_device_unmap(dev_id=0x%x) " , dev_id ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
}
2017-07-26 04:57:43 +02:00
/*
* lv2 SysCall 677 ( 0x2A5 ) : sys_rsx_attribute
*/
s32 sys_rsx_attribute ( u32 packageId , u32 a2 , u32 a3 , u32 a4 , u32 a5 )
2013-11-09 02:05:58 +01:00
{
2017-07-26 04:57:43 +02:00
sys_rsx . warning ( " sys_rsx_attribute(packageId=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x) " , packageId , a2 , a3 , a4 , a5 ) ;
2015-07-11 01:38:40 +02:00
2013-11-09 02:05:58 +01:00
return CELL_OK ;
2017-07-26 04:57:43 +02:00
}