#include "stdafx.h" #include "Emu/IdManager.h" #include "Emu/Cell/PPUModule.h" #include "Emu/RSX/GCM.h" #include "Emu/RSX/gcm_enums.h" #include "cellResc.h" #include "cellVideoOut.h" LOG_CHANNEL(cellResc); template <> void fmt_class_string::format(std::string& out, u64 arg) { format_enum(out, arg, [](CellRescError value) { switch (value) { STR_CASE(CELL_RESC_ERROR_NOT_INITIALIZED); STR_CASE(CELL_RESC_ERROR_REINITIALIZED); STR_CASE(CELL_RESC_ERROR_BAD_ALIGNMENT); STR_CASE(CELL_RESC_ERROR_BAD_ARGUMENT); STR_CASE(CELL_RESC_ERROR_LESS_MEMORY); STR_CASE(CELL_RESC_ERROR_GCM_FLIP_QUE_FULL); STR_CASE(CELL_RESC_ERROR_BAD_COMBINATION); STR_CASE(CELL_RESC_ERROR_x308); } return unknown; }); } error_code cellRescInit(vm::cptr initConfig) { cellResc.todo("cellRescInit(initConfig=*0x%x)", initConfig); auto& resc_manager = g_fxo->get(); if (resc_manager.is_initialized) { return CELL_RESC_ERROR_REINITIALIZED; } if (!initConfig || initConfig->size > 28) // TODO: more checks { return CELL_RESC_ERROR_BAD_ARGUMENT; } resc_manager.config = { initConfig->size, initConfig->resourcePolicy, initConfig->supportModes, initConfig->ratioMode, initConfig->palTemporalMode, initConfig->interlaceMode, initConfig->flipMode}; resc_manager.is_initialized = true; return CELL_OK; } void cellRescExit() { cellResc.todo("cellRescExit()"); auto& resc_manager = g_fxo->get(); resc_manager.is_initialized = false; } error_code cellRescVideoOutResolutionId2RescBufferMode(u32 resolutionId, vm::cptr bufferMode) { cellResc.todo("cellRescVideoOutResolutionId2RescBufferMode(resolutionId=%d, bufferMode=*0x%x)", resolutionId, bufferMode); if (!bufferMode || !resolutionId || resolutionId > CELL_VIDEO_OUT_RESOLUTION_576) { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescSetDsts(u32 bufferMode, vm::cptr dsts) { cellResc.todo("cellRescSetDsts(bufferMode=%d, dsts=*0x%x)", bufferMode, dsts); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (!dsts || !bufferMode || bufferMode > CELL_RESC_1920x1080) // TODO: is the bufferMode check correct? { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescSetDisplayMode(u32 bufferMode) { cellResc.todo("cellRescSetDisplayMode(bufferMode=%d)", bufferMode); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (!bufferMode || bufferMode > CELL_RESC_1920x1080 || !(resc_manager.config.support_modes & bufferMode)) // TODO: is the bufferMode check correct? { return CELL_RESC_ERROR_BAD_ARGUMENT; } if (bufferMode == CELL_RESC_720x576) { const u32 pal_mode = resc_manager.config.pal_temporal_mode; const u32 flip_mode = resc_manager.config.flip_mode; // Check if palTemporalMode is any INTERPOLATE mode or CELL_RESC_PAL_60_DROP if ((pal_mode - CELL_RESC_PAL_60_INTERPOLATE) <= CELL_RESC_PAL_60_INTERPOLATE || pal_mode == CELL_RESC_PAL_60_DROP) { if (flip_mode == CELL_RESC_DISPLAY_HSYNC) { return CELL_RESC_ERROR_BAD_COMBINATION; } } if (pal_mode == CELL_RESC_PAL_60_FOR_HSYNC) { if (flip_mode == CELL_RESC_DISPLAY_VSYNC) { return CELL_RESC_ERROR_BAD_COMBINATION; } } } resc_manager.buffer_mode = bufferMode; return CELL_OK; } error_code cellRescAdjustAspectRatio(f32 horizontal, f32 vertical) { cellResc.todo("cellRescAdjustAspectRatio(horizontal=%f, vertical=%f)", horizontal, vertical); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (horizontal < 0.5f || horizontal > 2.0f || vertical < 0.5f || vertical > 2.0f) { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescSetPalInterpolateDropFlexRatio(f32 ratio) { cellResc.todo("cellRescSetPalInterpolateDropFlexRatio(ratio=%f)", ratio); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (ratio < 0.0f || ratio > 1.0f) { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescGetBufferSize(vm::ptr colorBuffers, vm::ptr vertexArray, vm::ptr fragmentShader) { cellResc.todo("cellRescGetBufferSize(colorBuffers=*0x%x, vertexArray=*0x%x, fragmentShader=*0x%x)", colorBuffers, vertexArray, fragmentShader); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } // if (something) //{ // return CELL_RESC_ERROR_x308; // } // if (colorBuffers) //{ // colorBuffers = something // } // if (vertexArray) //{ // vertexArray = something // } // if (fragmentShader) //{ // fragmentShader = something // } return CELL_OK; } s32 cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, s32 reserved) { cellResc.todo("cellRescGetNumColorBuffers(dstMode=%d, palTemporalMode=%d, reserved=%d)", dstMode, palTemporalMode, reserved); if (reserved != 0) { return CELL_RESC_ERROR_BAD_ARGUMENT; } if (dstMode == CELL_RESC_720x576) { // Check if palTemporalMode is any INTERPOLATE mode if ((palTemporalMode - CELL_RESC_PAL_60_INTERPOLATE) <= CELL_RESC_PAL_60_INTERPOLATE) { return 6; } if (palTemporalMode == CELL_RESC_PAL_60_DROP) { return 3; } } return 2; } error_code cellRescGcmSurface2RescSrc(vm::cptr gcmSurface, vm::cptr rescSrc) { cellResc.todo("cellRescGcmSurface2RescSrc(gcmSurface=*0x%x, rescSrc=*0x%x)", gcmSurface, rescSrc); if (!gcmSurface || !rescSrc) { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescSetSrc(s32 idx, vm::cptr src) { cellResc.todo("cellRescSetSrc(idx=0x%x, src=*0x%x)", idx, src); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (idx >= SRC_BUFFER_NUM || !src || !src->width || !src->height || src->height > 4096) // TODO: is this correct? { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescSetConvertAndFlip(vm::ptr con, s32 idx) { cellResc.todo("cellRescSetConvertAndFlip(con=*0x%x, idx=0x%x)", con, idx); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (idx >= SRC_BUFFER_NUM) { return CELL_RESC_ERROR_BAD_ARGUMENT; } return CELL_OK; } error_code cellRescSetWaitFlip(vm::ptr con) { cellResc.todo("cellRescSetWaitFlip(con=*0x%x)", con); return CELL_OK; } error_code cellRescSetBufferAddress(vm::cptr colorBuffers, vm::cptr vertexArray, vm::cptr fragmentShader) { cellResc.todo("cellRescSetBufferAddress(colorBuffers=*0x%x, vertexArray=*0x%x, fragmentShader=*0x%x)", colorBuffers, vertexArray, fragmentShader); auto& resc_manager = g_fxo->get(); if (!resc_manager.is_initialized) { return CELL_RESC_ERROR_NOT_INITIALIZED; } if (!colorBuffers || !vertexArray || !fragmentShader) { return CELL_RESC_ERROR_BAD_ARGUMENT; } if (!colorBuffers.aligned(128) || !vertexArray.aligned(4) || !fragmentShader.aligned(64)) // clrlwi with 25, 30, 26 { return CELL_RESC_ERROR_BAD_ALIGNMENT; } return CELL_OK; } void cellRescSetFlipHandler(vm::ptr handler) { cellResc.todo("cellRescSetFlipHandler(handler=*0x%x)", handler); } void cellRescResetFlipStatus() { cellResc.todo("cellRescResetFlipStatus()"); } s32 cellRescGetFlipStatus() { cellResc.todo("cellRescGetFlipStatus()"); return 0; } s32 cellRescGetRegisterCount() { cellResc.todo("cellRescGetRegisterCount()"); return 0; } u64 cellRescGetLastFlipTime() { cellResc.todo("cellRescGetLastFlipTime()"); return 0; } void cellRescSetRegisterCount(s32 regCount) { cellResc.todo("cellRescSetRegisterCount(regCount=0x%x)", regCount); } void cellRescSetVBlankHandler(vm::ptr handler) { cellResc.todo("cellRescSetVBlankHandler(handler=*0x%x)", handler); } error_code cellRescCreateInterlaceTable(vm::ptr ea_addr, f32 srcH, CellRescTableElement depth, s32 length) { cellResc.todo("cellRescCreateInterlaceTable(ea_addr=0x%x, srcH=%f, depth=%d, length=%d)", ea_addr, srcH, +depth, length); if (!ea_addr || srcH <= 0.0f || depth > CELL_RESC_ELEMENT_FLOAT || length <= 0) // TODO: srcH check correct? { return CELL_RESC_ERROR_BAD_ARGUMENT; } auto& resc_manager = g_fxo->get(); if (!resc_manager.buffer_mode) { return CELL_RESC_ERROR_BAD_COMBINATION; } return CELL_OK; } DECLARE(ppu_module_manager::cellResc)("cellResc", []() { REG_FUNC(cellResc, cellRescSetConvertAndFlip); REG_FUNC(cellResc, cellRescSetWaitFlip); REG_FUNC(cellResc, cellRescSetFlipHandler); REG_FUNC(cellResc, cellRescGcmSurface2RescSrc); REG_FUNC(cellResc, cellRescGetNumColorBuffers); REG_FUNC(cellResc, cellRescSetDsts); REG_FUNC(cellResc, cellRescResetFlipStatus); REG_FUNC(cellResc, cellRescSetPalInterpolateDropFlexRatio); REG_FUNC(cellResc, cellRescGetRegisterCount); REG_FUNC(cellResc, cellRescAdjustAspectRatio); REG_FUNC(cellResc, cellRescSetDisplayMode); REG_FUNC(cellResc, cellRescExit); REG_FUNC(cellResc, cellRescInit); REG_FUNC(cellResc, cellRescGetBufferSize); REG_FUNC(cellResc, cellRescGetLastFlipTime); REG_FUNC(cellResc, cellRescSetSrc); REG_FUNC(cellResc, cellRescSetRegisterCount); REG_FUNC(cellResc, cellRescSetBufferAddress); REG_FUNC(cellResc, cellRescGetFlipStatus); REG_FUNC(cellResc, cellRescVideoOutResolutionId2RescBufferMode); REG_FUNC(cellResc, cellRescSetVBlankHandler); REG_FUNC(cellResc, cellRescCreateInterlaceTable); });