cellGcm HLE: Add error_code

This commit is contained in:
Eladash 2020-01-16 23:31:58 +02:00 committed by Ani
parent 3f076d63e3
commit 95ed2ef62e
2 changed files with 112 additions and 113 deletions

View file

@ -16,6 +16,25 @@
LOG_CHANNEL(cellGcmSys); LOG_CHANNEL(cellGcmSys);
template<>
void fmt_class_string<CellGcmError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(CELL_GCM_ERROR_FAILURE);
STR_CASE(CELL_GCM_ERROR_NO_IO_PAGE_TABLE);
STR_CASE(CELL_GCM_ERROR_INVALID_ENUM);
STR_CASE(CELL_GCM_ERROR_INVALID_VALUE);
STR_CASE(CELL_GCM_ERROR_INVALID_ALIGNMENT);
STR_CASE(CELL_GCM_ERROR_ADDRESS_OVERWRAP);
}
return unknown;
});
}
extern s32 cellGcmCallback(ppu_thread& ppu, vm::ptr<CellGcmContextData> context, u32 count); extern s32 cellGcmCallback(ppu_thread& ppu, vm::ptr<CellGcmContextData> context, u32 count);
const u32 tiled_pitches[] = { const u32 tiled_pitches[] = {
@ -77,6 +96,8 @@ u32 gcmGetLocalMemorySize(u32 sdk_version)
CellGcmOffsetTable offsetTable; CellGcmOffsetTable offsetTable;
atomic_t<u16> IoMapTable[0xC00]{}; atomic_t<u16> IoMapTable[0xC00]{};
error_code gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict);
void InitOffsetTable() void InitOffsetTable()
{ {
offsetTable.ioAddress.set(vm::alloc(3072 * sizeof(u16), vm::main)); offsetTable.ioAddress.set(vm::alloc(3072 * sizeof(u16), vm::main));
@ -246,13 +267,13 @@ u32 cellGcmGetDefaultSegmentWordSize()
return g_fxo->get<gcm_config>()->gcm_info.segment_size; return g_fxo->get<gcm_config>()->gcm_info.segment_size;
} }
s32 cellGcmInitDefaultFifoMode(s32 mode) error_code cellGcmInitDefaultFifoMode(s32 mode)
{ {
cellGcmSys.warning("cellGcmInitDefaultFifoMode(mode=%d)", mode); cellGcmSys.warning("cellGcmInitDefaultFifoMode(mode=%d)", mode);
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize) error_code cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize)
{ {
cellGcmSys.warning("cellGcmSetDefaultFifoSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize); cellGcmSys.warning("cellGcmSetDefaultFifoSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize);
return CELL_OK; return CELL_OK;
@ -262,13 +283,12 @@ s32 cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize)
// Hardware Resource Management // Hardware Resource Management
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
s32 cellGcmBindTile(u8 index) error_code cellGcmBindTile(u8 index)
{ {
cellGcmSys.warning("cellGcmBindTile(index=%d)", index); cellGcmSys.warning("cellGcmBindTile(index=%d)", index);
if (index >= rsx::limits::tiles_count) if (index >= rsx::limits::tiles_count)
{ {
cellGcmSys.error("cellGcmBindTile: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
@ -277,14 +297,13 @@ s32 cellGcmBindTile(u8 index)
return CELL_OK; return CELL_OK;
} }
s32 cellGcmBindZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask) error_code cellGcmBindZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask)
{ {
cellGcmSys.warning("cellGcmBindZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)", cellGcmSys.warning("cellGcmBindZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask); index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
if (index >= rsx::limits::zculls_count) if (index >= rsx::limits::zculls_count)
{ {
cellGcmSys.error("cellGcmBindZcull: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
@ -308,7 +327,7 @@ u32 cellGcmGetFlipStatus()
return status; return status;
} }
s32 cellGcmGetFlipStatus2() error_code cellGcmGetFlipStatus2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
@ -341,7 +360,7 @@ void _cellGcmFunc15(vm::ptr<CellGcmContextData> context)
u32 g_defaultCommandBufferBegin, g_defaultCommandBufferFragmentCount; u32 g_defaultCommandBufferBegin, g_defaultCommandBufferFragmentCount;
// Called by cellGcmInit // Called by cellGcmInit
s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSize, u32 ioAddress) error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSize, u32 ioAddress)
{ {
cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress); cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
@ -377,7 +396,6 @@ s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32
if (gcmMapEaIoAddress(ioAddress, 0, ioSize, false) != CELL_OK) if (gcmMapEaIoAddress(ioAddress, 0, ioSize, false) != CELL_OK)
{ {
cellGcmSys.error("cellGcmInit: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
@ -441,7 +459,7 @@ void cellGcmResetFlipStatus()
rsx::get_current_renderer()->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_WAITING; rsx::get_current_renderer()->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_WAITING;
} }
s32 cellGcmResetFlipStatus2() error_code cellGcmResetFlipStatus2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
@ -464,7 +482,7 @@ void cellGcmSetDebugOutputLevel(s32 level)
} }
} }
s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height) error_code cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
{ {
cellGcmSys.trace("cellGcmSetDisplayBuffer(id=0x%x, offset=0x%x, pitch=%d, width=%d, height=%d)", id, offset, width ? pitch / width : pitch, width, height); cellGcmSys.trace("cellGcmSetDisplayBuffer(id=0x%x, offset=0x%x, pitch=%d, width=%d, height=%d)", id, offset, width ? pitch / width : pitch, width, height);
@ -472,7 +490,6 @@ s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
if (id > 7) if (id > 7)
{ {
cellGcmSys.error("cellGcmSetDisplayBuffer: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
@ -505,7 +522,7 @@ void cellGcmSetFlipHandler(vm::ptr<void(u32)> handler)
rsx::get_current_renderer()->flip_handler = handler; rsx::get_current_renderer()->flip_handler = handler;
} }
s32 cellGcmSetFlipHandler2() error_code cellGcmSetFlipHandler2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
@ -518,7 +535,7 @@ void cellGcmSetFlipMode(u32 mode)
rsx::get_current_renderer()->requested_vsync.store(mode == CELL_GCM_DISPLAY_VSYNC); rsx::get_current_renderer()->requested_vsync.store(mode == CELL_GCM_DISPLAY_VSYNC);
} }
s32 cellGcmSetFlipMode2() error_code cellGcmSetFlipMode2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
@ -531,50 +548,55 @@ void cellGcmSetFlipStatus()
rsx::get_current_renderer()->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE; rsx::get_current_renderer()->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
} }
s32 cellGcmSetFlipStatus2() error_code cellGcmSetFlipStatus2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id) template <bool old_api = false, typename ret_type = std::conditional_t<old_api, s32, error_code>>
ret_type gcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
{ {
cellGcmSys.trace("cellGcmSetPrepareFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
const auto gcm_cfg = g_fxo->get<gcm_config>(); const auto gcm_cfg = g_fxo->get<gcm_config>();
if (id > 7) if (id > 7)
{ {
cellGcmSys.error("cellGcmSetPrepareFlip: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
if (ctxt->current + 2 >= ctxt->end) if (!old_api && ctxt->current + 2 >= ctxt->end)
{ {
if (s32 res = ctxt->callback(ppu, ctxt, 8 /* ??? */)) if (s32 res = ctxt->callback(ppu, ctxt, 8 /* ??? */))
{ {
cellGcmSys.error("cellGcmSetPrepareFlip: callback failed (0x%08x)", res); cellGcmSys.error("cellGcmSetPrepareFlip: callback failed (0x%08x)", res);
return res; return static_cast<ret_type>(not_an_error(res));
} }
} }
const u32 cmd_size = rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id }); const u32 cmd_size = rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id });
if (ctxt.addr() == gcm_cfg->gcm_info.context_addr) if (!old_api && ctxt.addr() == gcm_cfg->gcm_info.context_addr)
{ {
vm::_ref<CellGcmControl>(gcm_cfg->gcm_info.control_addr).put += cmd_size; vm::_ref<CellGcmControl>(gcm_cfg->gcm_info.control_addr).put += cmd_size;
} }
return id; return static_cast<ret_type>(not_an_error(id));
} }
s32 cellGcmSetFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id) error_code cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
{
cellGcmSys.trace("cellGcmSetPrepareFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
return gcmSetPrepareFlip(ppu, ctxt, id);
}
error_code cellGcmSetFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
{ {
cellGcmSys.trace("cellGcmSetFlip(ctxt=*0x%x, id=0x%x)", ctxt, id); cellGcmSys.trace("cellGcmSetFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
if (s32 res = cellGcmSetPrepareFlip(ppu, ctxt, id)) if (auto res = gcmSetPrepareFlip(ppu, ctxt, id); res < 0)
{ {
if (res < 0) return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
return CELL_OK; return CELL_OK;
@ -603,7 +625,7 @@ void cellGcmSetSecondVFrequency(u32 freq)
} }
} }
s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank) error_code cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank)
{ {
cellGcmSys.warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)", cellGcmSys.warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank); index, location, offset, size, pitch, comp, base, bank);
@ -612,19 +634,16 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4) if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4)
{ {
cellGcmSys.error("cellGcmSetTileInfo: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
if (offset & 0xffff || size & 0xffff || pitch & 0xff) if (offset & 0xffff || size & 0xffff || pitch & 0xff)
{ {
cellGcmSys.error("cellGcmSetTileInfo: CELL_GCM_ERROR_INVALID_ALIGNMENT");
return CELL_GCM_ERROR_INVALID_ALIGNMENT; return CELL_GCM_ERROR_INVALID_ALIGNMENT;
} }
if (location >= 2 || (comp != 0 && (comp < 7 || comp > 12))) if (location >= 2 || (comp != 0 && (comp < 7 || comp > 12)))
{ {
cellGcmSys.error("cellGcmSetTileInfo: CELL_GCM_ERROR_INVALID_ENUM");
return CELL_GCM_ERROR_INVALID_ENUM; return CELL_GCM_ERROR_INVALID_ENUM;
} }
@ -674,7 +693,7 @@ void cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)
// TODO: emit RSX command for "wait flip" operation // TODO: emit RSX command for "wait flip" operation
} }
s32 cellGcmSetWaitFlipUnsafe() error_code cellGcmSetWaitFlipUnsafe()
{ {
cellGcmSys.todo("cellGcmSetWaitFlipUnsafe()"); cellGcmSys.todo("cellGcmSetWaitFlipUnsafe()");
@ -713,13 +732,12 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
vm::_ptr<CellGcmZcullInfo>(gcm_cfg->zculls_addr)[index] = zcull.pack(); vm::_ptr<CellGcmZcullInfo>(gcm_cfg->zculls_addr)[index] = zcull.pack();
} }
s32 cellGcmUnbindTile(u8 index) error_code cellGcmUnbindTile(u8 index)
{ {
cellGcmSys.warning("cellGcmUnbindTile(index=%d)", index); cellGcmSys.warning("cellGcmUnbindTile(index=%d)", index);
if (index >= rsx::limits::tiles_count) if (index >= rsx::limits::tiles_count)
{ {
cellGcmSys.error("cellGcmUnbindTile: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
@ -728,13 +746,12 @@ s32 cellGcmUnbindTile(u8 index)
return CELL_OK; return CELL_OK;
} }
s32 cellGcmUnbindZcull(u8 index) error_code cellGcmUnbindZcull(u8 index)
{ {
cellGcmSys.warning("cellGcmUnbindZcull(index=%d)", index); cellGcmSys.warning("cellGcmUnbindZcull(index=%d)", index);
if (index >= 8) if (index >= 8)
{ {
cellGcmSys.error("cellGcmUnbindZcull: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
@ -761,7 +778,7 @@ u32 cellGcmGetDisplayInfo()
return g_fxo->get<gcm_config>()->gcm_buffers.addr(); return g_fxo->get<gcm_config>()->gcm_buffers.addr();
} }
s32 cellGcmGetCurrentDisplayBufferId(vm::ptr<u8> id) error_code cellGcmGetCurrentDisplayBufferId(vm::ptr<u8> id)
{ {
cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id); cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id);
@ -778,13 +795,13 @@ void cellGcmSetInvalidateTile(u8 index)
cellGcmSys.todo("cellGcmSetInvalidateTile(index=%d)", index); cellGcmSys.todo("cellGcmSetInvalidateTile(index=%d)", index);
} }
s32 cellGcmTerminate() error_code cellGcmTerminate()
{ {
// The firmware just return CELL_OK as well // The firmware just return CELL_OK as well
return CELL_OK; return CELL_OK;
} }
s32 cellGcmDumpGraphicsError() error_code cellGcmDumpGraphicsError()
{ {
cellGcmSys.todo("cellGcmDumpGraphicsError()"); cellGcmSys.todo("cellGcmDumpGraphicsError()");
return CELL_OK; return CELL_OK;
@ -793,7 +810,7 @@ s32 cellGcmDumpGraphicsError()
s32 cellGcmGetDisplayBufferByFlipIndex(u32 qid) s32 cellGcmGetDisplayBufferByFlipIndex(u32 qid)
{ {
cellGcmSys.todo("cellGcmGetDisplayBufferByFlipIndex(qid=%d)", qid); cellGcmSys.todo("cellGcmGetDisplayBufferByFlipIndex(qid=%d)", qid);
return -1; return -1; // Invalid id, todo
} }
u64 cellGcmGetLastFlipTime() u64 cellGcmGetLastFlipTime()
@ -803,7 +820,7 @@ u64 cellGcmGetLastFlipTime()
return rsx::get_current_renderer()->last_flip_time; return rsx::get_current_renderer()->last_flip_time;
} }
s32 cellGcmGetLastFlipTime2() error_code cellGcmGetLastFlipTime2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
@ -822,19 +839,19 @@ u64 cellGcmGetVBlankCount()
return rsx::get_current_renderer()->vblank_count; return rsx::get_current_renderer()->vblank_count;
} }
s32 cellGcmGetVBlankCount2() error_code cellGcmGetVBlankCount2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSysGetLastVBlankTime() error_code cellGcmSysGetLastVBlankTime()
{ {
cellGcmSys.todo("cellGcmSysGetLastVBlankTime()"); cellGcmSys.todo("cellGcmSysGetLastVBlankTime()");
return CELL_OK; return CELL_OK;
} }
s32 cellGcmInitSystemMode(u64 mode) error_code cellGcmInitSystemMode(u64 mode)
{ {
cellGcmSys.trace("cellGcmInitSystemMode(mode=0x%x)", mode); cellGcmSys.trace("cellGcmInitSystemMode(mode=0x%x)", mode);
@ -843,13 +860,12 @@ s32 cellGcmInitSystemMode(u64 mode)
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetFlipImmediate(u8 id) error_code cellGcmSetFlipImmediate(u8 id)
{ {
cellGcmSys.todo("cellGcmSetFlipImmediate(id=0x%x)", id); cellGcmSys.todo("cellGcmSetFlipImmediate(id=0x%x)", id);
if (id > 7) if (id > 7)
{ {
cellGcmSys.error("cellGcmSetFlipImmediate: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
@ -858,7 +874,7 @@ s32 cellGcmSetFlipImmediate(u8 id)
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetFlipImmediate2() error_code cellGcmSetFlipImmediate2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
@ -874,7 +890,7 @@ void cellGcmSetQueueHandler(vm::ptr<void(u32)> handler)
cellGcmSys.todo("cellGcmSetQueueHandler(handler=*0x%x)", handler); cellGcmSys.todo("cellGcmSetQueueHandler(handler=*0x%x)", handler);
} }
s32 cellGcmSetSecondVHandler(vm::ptr<void(u32)> handler) error_code cellGcmSetSecondVHandler(vm::ptr<void(u32)> handler)
{ {
cellGcmSys.todo("cellGcmSetSecondVHandler(handler=0x%x)", handler); cellGcmSys.todo("cellGcmSetSecondVHandler(handler=0x%x)", handler);
return CELL_OK; return CELL_OK;
@ -885,7 +901,7 @@ void cellGcmSetVBlankFrequency(u32 freq)
cellGcmSys.todo("cellGcmSetVBlankFrequency(freq=%d)", freq); cellGcmSys.todo("cellGcmSetVBlankFrequency(freq=%d)", freq);
} }
s32 cellGcmSortRemapEaIoAddress() error_code cellGcmSortRemapEaIoAddress()
{ {
cellGcmSys.todo("cellGcmSortRemapEaIoAddress()"); cellGcmSys.todo("cellGcmSortRemapEaIoAddress()");
return CELL_OK; return CELL_OK;
@ -894,7 +910,7 @@ s32 cellGcmSortRemapEaIoAddress()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Memory Mapping // Memory Mapping
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
s32 cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset) error_code cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset)
{ {
cellGcmSys.trace("cellGcmAddressToOffset(address=0x%x, offset=*0x%x)", address, offset); cellGcmSys.trace("cellGcmAddressToOffset(address=0x%x, offset=*0x%x)", address, offset);
@ -946,7 +962,7 @@ void cellGcmGetOffsetTable(vm::ptr<CellGcmOffsetTable> table)
table->eaAddress = offsetTable.eaAddress; table->eaAddress = offsetTable.eaAddress;
} }
s32 cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address) error_code cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
{ {
cellGcmSys.trace("cellGcmIoOffsetToAddress(ioOffset=0x%x, address=*0x%x)", ioOffset, address); cellGcmSys.trace("cellGcmIoOffsetToAddress(ioOffset=0x%x, address=*0x%x)", ioOffset, address);
@ -954,7 +970,6 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
if (static_cast<s16>(upper12Bits) < 0) if (static_cast<s16>(upper12Bits) < 0)
{ {
cellGcmSys.error("cellGcmIoOffsetToAddress: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
@ -963,14 +978,14 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
return CELL_OK; return CELL_OK;
} }
s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict) error_code gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
{ {
if (!size || (ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF)) if (!size || (ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF))
{ {
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
if (s32 error = sys_rsx_context_iomap(0x55555555, io, ea, size, 0xe000000000000800ull | (u64{is_strict} << 60))) if (auto error = sys_rsx_context_iomap(0x55555555, io, ea, size, 0xe000000000000800ull | (u64{is_strict} << 60)))
{ {
return error; return error;
} }
@ -988,14 +1003,14 @@ s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
return CELL_OK; return CELL_OK;
} }
s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size) error_code cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
{ {
cellGcmSys.warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); cellGcmSys.warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
return gcmMapEaIoAddress(ea, io, size, false); return gcmMapEaIoAddress(ea, io, size, false);
} }
s32 cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags) error_code cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags)
{ {
cellGcmSys.warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags); cellGcmSys.warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags);
@ -1004,7 +1019,7 @@ s32 cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags)
return gcmMapEaIoAddress(ea, io, size, true); return gcmMapEaIoAddress(ea, io, size, true);
} }
s32 cellGcmMapLocalMemory(vm::ptr<u32> address, vm::ptr<u32> size) error_code cellGcmMapLocalMemory(vm::ptr<u32> address, vm::ptr<u32> size)
{ {
cellGcmSys.warning("cellGcmMapLocalMemory(address=*0x%x, size=*0x%x)", address, size); cellGcmSys.warning("cellGcmMapLocalMemory(address=*0x%x, size=*0x%x)", address, size);
@ -1015,14 +1030,13 @@ s32 cellGcmMapLocalMemory(vm::ptr<u32> address, vm::ptr<u32> size)
} }
else else
{ {
cellGcmSys.error("RSX local memory already mapped");
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
return CELL_OK; return CELL_OK;
} }
s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset) error_code cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{ {
cellGcmSys.warning("cellGcmMapMainMemory(ea=0x%x, size=0x%x, offset=*0x%x)", ea, size, offset); cellGcmSys.warning("cellGcmMapMainMemory(ea=0x%x, size=0x%x, offset=*0x%x)", ea, size, offset);
@ -1035,22 +1049,11 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{ {
if (unmap_count >= (size >> 20)) if (unmap_count >= (size >> 20))
{ {
if (s32 error = sys_rsx_context_iomap(0x55555555, io << 20, ea, size, 0xe000000000000800ull)) if (auto error = gcmMapEaIoAddress(io << 20, ea, size, false))
{ {
return error; return error;
} }
ea >>= 20, size >>= 20;
// Fill the offset table
for (u32 i = 0; i < size; i++)
{
offsetTable.ioAddress[ea + i] = io + i;
offsetTable.eaAddress[io + i] = ea + i;
}
IoMapTable[ea] = size;
*offset = io << 20; *offset = io << 20;
return CELL_OK; return CELL_OK;
} }
@ -1062,23 +1065,20 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
} }
} }
cellGcmSys.error("cellGcmMapMainMemory: CELL_GCM_ERROR_NO_IO_PAGE_TABLE");
return CELL_GCM_ERROR_NO_IO_PAGE_TABLE; return CELL_GCM_ERROR_NO_IO_PAGE_TABLE;
} }
s32 cellGcmReserveIoMapSize(u32 size) error_code cellGcmReserveIoMapSize(u32 size)
{ {
cellGcmSys.trace("cellGcmReserveIoMapSize(size=0x%x)", size); cellGcmSys.trace("cellGcmReserveIoMapSize(size=0x%x)", size);
if (size & 0xFFFFF) if (size & 0xFFFFF)
{ {
cellGcmSys.error("cellGcmReserveIoMapSize: CELL_GCM_ERROR_INVALID_ALIGNMENT");
return CELL_GCM_ERROR_INVALID_ALIGNMENT; return CELL_GCM_ERROR_INVALID_ALIGNMENT;
} }
if (size > cellGcmGetMaxIoMapSize()) if (size > cellGcmGetMaxIoMapSize())
{ {
cellGcmSys.error("cellGcmReserveIoMapSize: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
@ -1086,9 +1086,9 @@ s32 cellGcmReserveIoMapSize(u32 size)
return CELL_OK; return CELL_OK;
} }
s32 cellGcmUnmapEaIoAddress(u32 ea) error_code cellGcmUnmapEaIoAddress(u32 ea)
{ {
cellGcmSys.trace("cellGcmUnmapEaIoAddress(ea=0x%x)", ea); cellGcmSys.warning("cellGcmUnmapEaIoAddress(ea=0x%x)", ea);
if (const u32 size = IoMapTable[ea >>= 20].exchange(0)) if (const u32 size = IoMapTable[ea >>= 20].exchange(0))
{ {
@ -1104,16 +1104,15 @@ s32 cellGcmUnmapEaIoAddress(u32 ea)
} }
else else
{ {
cellGcmSys.error("cellGcmUnmapEaIoAddress(ea=0x%x): UnmapRealAddress() failed", ea);
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
return CELL_OK; return CELL_OK;
} }
s32 cellGcmUnmapIoAddress(u32 io) error_code cellGcmUnmapIoAddress(u32 io)
{ {
cellGcmSys.trace("cellGcmUnmapIoAddress(io=0x%x)", io); cellGcmSys.warning("cellGcmUnmapIoAddress(io=0x%x)", io);
if (u32 size = IoMapTable[RSXIOMem.ea[io >>= 20]].exchange(0)) if (u32 size = IoMapTable[RSXIOMem.ea[io >>= 20]].exchange(0))
{ {
@ -1129,26 +1128,23 @@ s32 cellGcmUnmapIoAddress(u32 io)
} }
else else
{ {
cellGcmSys.error("cellGcmUnmapIoAddress(io=0x%x): UnmapAddress() failed", io);
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
return CELL_OK; return CELL_OK;
} }
s32 cellGcmUnreserveIoMapSize(u32 size) error_code cellGcmUnreserveIoMapSize(u32 size)
{ {
cellGcmSys.trace("cellGcmUnreserveIoMapSize(size=0x%x)", size); cellGcmSys.trace("cellGcmUnreserveIoMapSize(size=0x%x)", size);
if (size & 0xFFFFF) if (size & 0xFFFFF)
{ {
cellGcmSys.error("cellGcmUnreserveIoMapSize: CELL_GCM_ERROR_INVALID_ALIGNMENT");
return CELL_GCM_ERROR_INVALID_ALIGNMENT; return CELL_GCM_ERROR_INVALID_ALIGNMENT;
} }
if (size > reserved_size) if (size > reserved_size)
{ {
cellGcmSys.error("cellGcmUnreserveIoMapSize: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
@ -1160,37 +1156,37 @@ s32 cellGcmUnreserveIoMapSize(u32 size)
// Cursor Functions // Cursor Functions
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
s32 cellGcmInitCursor() error_code cellGcmInitCursor()
{ {
cellGcmSys.todo("cellGcmInitCursor()"); cellGcmSys.todo("cellGcmInitCursor()");
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetCursorPosition(s32 x, s32 y) error_code cellGcmSetCursorPosition(s32 x, s32 y)
{ {
cellGcmSys.todo("cellGcmSetCursorPosition(x=%d, y=%d)", x, y); cellGcmSys.todo("cellGcmSetCursorPosition(x=%d, y=%d)", x, y);
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetCursorDisable() error_code cellGcmSetCursorDisable()
{ {
cellGcmSys.todo("cellGcmSetCursorDisable()"); cellGcmSys.todo("cellGcmSetCursorDisable()");
return CELL_OK; return CELL_OK;
} }
s32 cellGcmUpdateCursor() error_code cellGcmUpdateCursor()
{ {
cellGcmSys.todo("cellGcmUpdateCursor()"); cellGcmSys.todo("cellGcmUpdateCursor()");
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetCursorEnable() error_code cellGcmSetCursorEnable()
{ {
cellGcmSys.todo("cellGcmSetCursorEnable()"); cellGcmSys.todo("cellGcmSetCursorEnable()");
return CELL_OK; return CELL_OK;
} }
s32 cellGcmSetCursorImageOffset(u32 offset) error_code cellGcmSetCursorImageOffset(u32 offset)
{ {
cellGcmSys.todo("cellGcmSetCursorImageOffset(offset=0x%x)", offset); cellGcmSys.todo("cellGcmSetCursorImageOffset(offset=0x%x)", offset);
return CELL_OK; return CELL_OK;
@ -1209,7 +1205,7 @@ void cellGcmSetDefaultCommandBuffer()
vm::write32(gcm_cfg->ctxt_addr, gcm_cfg->gcm_info.context_addr); vm::write32(gcm_cfg->ctxt_addr, gcm_cfg->gcm_info.context_addr);
} }
s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize(u32 bufferSize, u32 segmentSize) error_code cellGcmSetDefaultCommandBufferAndSegmentWordSize(u32 bufferSize, u32 segmentSize)
{ {
cellGcmSys.warning("cellGcmSetDefaultCommandBufferAndSegmentWordSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize); cellGcmSys.warning("cellGcmSetDefaultCommandBufferAndSegmentWordSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize);
@ -1233,31 +1229,40 @@ s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize(u32 bufferSize, u32 segment
// Other // Other
//------------------------------------------------------------------------ //------------------------------------------------------------------------
s32 _cellGcmSetFlipCommand(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id) void _cellGcmSetFlipCommand(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id)
{ {
cellGcmSys.trace("cellGcmSetFlipCommand(ctx=*0x%x, id=0x%x)", ctx, id); cellGcmSys.trace("cellGcmSetFlipCommand(ctx=*0x%x, id=0x%x)", ctx, id);
return cellGcmSetPrepareFlip(ppu, ctx, id); if (auto error = gcmSetPrepareFlip<true>(ppu, ctx, id); error < 0)
{
// TODO: On actual fw this function doesn't have error checks at all
cellGcmSys.error("cellGcmSetFlipCommand(): gcmSetPrepareFlip failed with %s", CellGcmError{error + 0u});
}
} }
s32 _cellGcmSetFlipCommand2() error_code _cellGcmSetFlipCommand2()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK; return CELL_OK;
} }
s32 _cellGcmSetFlipCommandWithWaitLabel(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value) void _cellGcmSetFlipCommandWithWaitLabel(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
{ {
cellGcmSys.trace("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value); cellGcmSys.todo("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
const auto gcm_cfg = g_fxo->get<gcm_config>(); const auto gcm_cfg = g_fxo->get<gcm_config>();
s32 res = cellGcmSetPrepareFlip(ppu, ctx, id); if (auto error = gcmSetPrepareFlip<true>(ppu, ctx, id); error < 0)
vm::write32(gcm_cfg->gcm_info.label_addr + 0x10 * label_index, label_value); {
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; // TODO: On actual fw this function doesn't have error checks at all
cellGcmSys.error("cellGcmSetFlipCommandWithWaitLabel(): gcmSetPrepareFlip failed with %s", CellGcmError{error + 0u});
} }
s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank) // TODO: Fix this (must enqueue WaitLabel command instead)
vm::write32(gcm_cfg->gcm_info.label_addr + 0x10 * label_index, label_value);
}
error_code cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank)
{ {
cellGcmSys.warning("cellGcmSetTile(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)", cellGcmSys.warning("cellGcmSetTile(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank); index, location, offset, size, pitch, comp, base, bank);
@ -1267,19 +1272,16 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
// Copied form cellGcmSetTileInfo // Copied form cellGcmSetTileInfo
if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4) if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4)
{ {
cellGcmSys.error("cellGcmSetTile: CELL_GCM_ERROR_INVALID_VALUE");
return CELL_GCM_ERROR_INVALID_VALUE; return CELL_GCM_ERROR_INVALID_VALUE;
} }
if (offset & 0xffff || size & 0xffff || pitch & 0xff) if (offset & 0xffff || size & 0xffff || pitch & 0xff)
{ {
cellGcmSys.error("cellGcmSetTile: CELL_GCM_ERROR_INVALID_ALIGNMENT");
return CELL_GCM_ERROR_INVALID_ALIGNMENT; return CELL_GCM_ERROR_INVALID_ALIGNMENT;
} }
if (location >= 2 || (comp != 0 && (comp < 7 || comp > 12))) if (location >= 2 || (comp != 0 && (comp < 7 || comp > 12)))
{ {
cellGcmSys.error("cellGcmSetTile: CELL_GCM_ERROR_INVALID_ENUM");
return CELL_GCM_ERROR_INVALID_ENUM; return CELL_GCM_ERROR_INVALID_ENUM;
} }
@ -1304,49 +1306,49 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
return CELL_OK; return CELL_OK;
} }
s32 _cellGcmFunc2() error_code _cellGcmFunc2()
{ {
cellGcmSys.todo("_cellGcmFunc2()"); cellGcmSys.todo("_cellGcmFunc2()");
return CELL_OK; return CELL_OK;
} }
s32 _cellGcmFunc3() error_code _cellGcmFunc3()
{ {
cellGcmSys.todo("_cellGcmFunc3()"); cellGcmSys.todo("_cellGcmFunc3()");
return CELL_OK; return CELL_OK;
} }
s32 _cellGcmFunc4() error_code _cellGcmFunc4()
{ {
cellGcmSys.todo("_cellGcmFunc4()"); cellGcmSys.todo("_cellGcmFunc4()");
return CELL_OK; return CELL_OK;
} }
s32 _cellGcmFunc13() error_code _cellGcmFunc13()
{ {
cellGcmSys.todo("_cellGcmFunc13()"); cellGcmSys.todo("_cellGcmFunc13()");
return CELL_OK; return CELL_OK;
} }
s32 _cellGcmFunc38() error_code _cellGcmFunc38()
{ {
cellGcmSys.todo("_cellGcmFunc38()"); cellGcmSys.todo("_cellGcmFunc38()");
return CELL_OK; return CELL_OK;
} }
s32 cellGcmGpadGetStatus(vm::ptr<u32> status) error_code cellGcmGpadGetStatus(vm::ptr<u32> status)
{ {
cellGcmSys.todo("cellGcmGpadGetStatus(status=*0x%x)", status); cellGcmSys.todo("cellGcmGpadGetStatus(status=*0x%x)", status);
return CELL_OK; return CELL_OK;
} }
s32 cellGcmGpadNotifyCaptureSurface(vm::ptr<CellGcmSurface> surface) error_code cellGcmGpadNotifyCaptureSurface(vm::ptr<CellGcmSurface> surface)
{ {
cellGcmSys.todo("cellGcmGpadNotifyCaptureSurface(surface=*0x%x)", surface); cellGcmSys.todo("cellGcmGpadNotifyCaptureSurface(surface=*0x%x)", surface);
return CELL_OK; return CELL_OK;
} }
s32 cellGcmGpadCaptureSnapshot(u32 num) error_code cellGcmGpadCaptureSnapshot(u32 num)
{ {
cellGcmSys.todo("cellGcmGpadCaptureSnapshot(num=%d)", num); cellGcmSys.todo("cellGcmGpadCaptureSnapshot(num=%d)", num);
return CELL_OK; return CELL_OK;

View file

@ -3,7 +3,7 @@
#include "Emu/RSX/GCM.h" #include "Emu/RSX/GCM.h"
#include "Emu/Memory/vm_ptr.h" #include "Emu/Memory/vm_ptr.h"
enum enum CellGcmError : u32
{ {
CELL_GCM_ERROR_FAILURE = 0x802100ff, CELL_GCM_ERROR_FAILURE = 0x802100ff,
CELL_GCM_ERROR_NO_IO_PAGE_TABLE = 0x80210001, CELL_GCM_ERROR_NO_IO_PAGE_TABLE = 0x80210001,
@ -20,6 +20,3 @@ struct CellGcmOffsetTable
}; };
void InitOffsetTable(); void InitOffsetTable();
// Auxiliary functions
s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict);