diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index ead6f487a5..b778a3af00 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2330,7 +2330,7 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, case 0x01020004: // TODO: Should not work for umd0:/, ms0:/, etc. // TODO: Should probably move this to something common between ISOFileSystem and VirtualDiscSystem. - INFO_LOG(SCEIO, "sceIoIoctl: Asked for file offset of file %i", id); + DEBUG_LOG(SCEIO, "sceIoIoctl: Asked for file offset of file %d", id); if (Memory::IsValidAddress(outdataPtr) && outlen >= 4) { u32 offset = (u32)pspFileSystem.GetSeekPos(f->handle); Memory::Write_U32(offset, outdataPtr); diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index 9e85693f67..8204a51c58 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -431,7 +431,7 @@ static u32 scePowerSetBusClockFrequency(u32 busfreq) { static u32 scePowerGetCpuClockFrequencyInt() { int cpuFreq = CoreTiming::GetClockFrequencyMHz(); - INFO_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", cpuFreq); + DEBUG_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", cpuFreq); return cpuFreq; } @@ -447,7 +447,7 @@ static u32 scePowerGetBusClockFrequencyInt() { static float scePowerGetCpuClockFrequencyFloat() { int cpuFreq = CoreTiming::GetClockFrequencyMHz(); - INFO_LOG(HLE, "%f=scePowerGetCpuClockFrequencyFloat()", (float)cpuFreq); + DEBUG_LOG(HLE, "%f=scePowerGetCpuClockFrequencyFloat()", (float)cpuFreq); return (float) cpuFreq; } diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index fbe60c1756..2066defced 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -26,6 +26,8 @@ #include "Core/Reporting.h" #include "GPU/ge_constants.h" #include "GPU/Common/ShaderCommon.h" +#include "GPU/GPUCommon.h" + #if PPSSPP_ARCH(ARM) #include "Common/ArmEmitter.h" #elif PPSSPP_ARCH(ARM64) @@ -78,30 +80,6 @@ struct DecVtxFormat { void ComputeID(); }; -struct TransformedVertex -{ - union { - struct { - float x, y, z, fog; // in case of morph, preblend during decode - }; - float pos[4]; - }; - union { - struct { - float u; float v; float w; // scaled by uscale, vscale, if there - }; - float uv[3]; - }; - union { - u8 color0[4]; // prelit - u32 color0_32; - }; - union { - u8 color1[4]; // prelit - u32 color1_32; - }; -}; - void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); inline int RoundUp4(int x) { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 4a836550f1..3e37f99075 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -303,16 +303,16 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_BONEMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoneMtxData }, // Vertex Screen/Texture/Color - { GE_CMD_VSCX, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VSCY, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VSCZ, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VTCS, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VTCT, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VTCQ, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VCV, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VAP, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VFC, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_VSCV, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_VSCX }, + { GE_CMD_VSCY }, + { GE_CMD_VSCZ }, + { GE_CMD_VTCS }, + { GE_CMD_VTCT }, + { GE_CMD_VTCQ }, + { GE_CMD_VCV }, + { GE_CMD_VAP, FLAG_EXECUTE, 0, &GPUCommon::Execute_ImmVertexAlphaPrim }, + { GE_CMD_VFC }, + { GE_CMD_VSCV }, // "Missing" commands (gaps in the sequence) { GE_CMD_UNKNOWN_03, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, @@ -1808,6 +1808,79 @@ void GPUCommon::Execute_MorphWeight(u32 op, u32 diff) { gstate_c.morphWeights[(op >> 24) - GE_CMD_MORPHWEIGHT0] = getFloat24(op); } +void GPUCommon::Execute_ImmVertexAlphaPrim(u32 op, u32 diff) { + // Safety check. + if (immCount_ >= MAX_IMMBUFFER_SIZE) { + // Only print once for each overrun. + if (immCount_ == MAX_IMMBUFFER_SIZE) { + ERROR_LOG_REPORT_ONCE(exceed_imm_buffer, G3D, "Exceeded immediate draw buffer size"); + } + if (immCount_ < 0x7fffffff) // Paranoia :) + immCount_++; + return; + } + + uint32_t data = op & 0xFFFFFF; + TransformedVertex &v = immBuffer_[immCount_++]; + + // Formula deduced from ThrillVille's clear. + int offsetX = gstate.getOffsetX16(); + int offsetY = gstate.getOffsetY16(); + v.x = ((gstate.imm_vscx & 0xFFFFFF) - offsetX) / 16.0f; + v.y = ((gstate.imm_vscy & 0xFFFFFF) - offsetY) / 16.0f; + v.z = gstate.imm_vscz & 0xFFFF; + v.u = getFloat24(gstate.imm_vtcs); + v.v = getFloat24(gstate.imm_vtct); + v.w = getFloat24(gstate.imm_vtcq); + v.color0_32 = (gstate.imm_cv & 0xFFFFFF) | (gstate.imm_ap << 24); + v.fog = 0.0f; // we have no information about the scale here + v.color1_32 = gstate.imm_scv & 0xFFFFFF; + int prim = (op >> 8) & 0x7; + if (prim != GE_PRIM_KEEP_PREVIOUS) { + immPrim_ = (GEPrimitiveType)prim; + } else if (prim == GE_PRIM_KEEP_PREVIOUS && immCount_ == 2) { + // Instead of finding a proper point to flush, we just emit a full rectangle every time one + // is finished. + FlushImm(); + } else { + ERROR_LOG_REPORT_ONCE(imm_draw_prim, G3D, "Immediate draw: Unexpected primitive %d at count %d", prim, immCount_); + } +} + +void GPUCommon::FlushImm() { + SetDrawType(DRAW_PRIM, immPrim_); + framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); + if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { + // No idea how many cycles to skip, heh. + return; + } + UpdateUVScaleOffset(); + + // Instead of plumbing through properly (we'd need to inject these pretransformed vertices in the middle + // of SoftwareTransform(), which would take a lot of refactoring), we'll cheat and just turn these into + // through vertices. + // Since the only known use is Thrillville and it only uses it to clear, we just use color and pos. + struct ImmVertex { + uint32_t color; + float xyz[3]; + }; + ImmVertex temp[MAX_IMMBUFFER_SIZE]; + for (int i = 0; i < immCount_; i++) { + temp[i].color = immBuffer_[i].color0_32; + temp[i].xyz[0] = immBuffer_[i].pos[0]; + temp[i].xyz[1] = immBuffer_[i].pos[1]; + temp[i].xyz[2] = immBuffer_[i].pos[2]; + } + int vtype = GE_VTYPE_POS_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_THROUGH; + + int bytesRead; + drawEngineCommon_->DispatchSubmitPrim(temp, nullptr, immPrim_, immCount_, vtype, &bytesRead); + drawEngineCommon_->DispatchFlush(); + // TOOD: In the future, make a special path for these. + // drawEngineCommon_->DispatchSubmitImm(immBuffer_, immCount_); + immCount_ = 0; +} + void GPUCommon::ExecuteOp(u32 op, u32 diff) { const u32 cmd = op >> 24; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index c4d22dc904..784293578c 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -39,6 +39,29 @@ enum { FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both! }; +struct TransformedVertex { + union { + struct { + float x, y, z, fog; // in case of morph, preblend during decode + }; + float pos[4]; + }; + union { + struct { + float u; float v; float w; // scaled by uscale, vscale, if there + }; + float uv[3]; + }; + union { + u8 color0[4]; // prelit + u32 color0_32; + }; + union { + u8 color1[4]; // prelit + u32 color1_32; + }; +}; + class GPUCommon : public GPUInterface, public GPUDebugInterface { public: GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); @@ -124,6 +147,8 @@ public: void Execute_MorphWeight(u32 op, u32 diff); + void Execute_ImmVertexAlphaPrim(u32 op, u32 diff); + void Execute_Unknown(u32 op, u32 diff); int EstimatePerVertexCost(); @@ -291,7 +316,17 @@ protected: DrawType lastDraw_; GEPrimitiveType lastPrim_; + // No idea how big this buffer needs to be. + enum { + MAX_IMMBUFFER_SIZE = 32, + }; + + TransformedVertex immBuffer_[MAX_IMMBUFFER_SIZE]; + int immCount_ = 0; + GEPrimitiveType immPrim_; + private: + void FlushImm(); // Debug stats. double timeSteppingStarted_; double timeSpentStepping_; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index a78aa10307..c67db91dfe 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -185,9 +185,20 @@ struct GPUgstate { transfersrcpos, transferdstpos, pad99, - transfersize; // 0xEE - - u32 pad05[0xFF- 0xEE]; + transfersize, // 0xEE + pad100, // 0xEF + imm_vscx, // 0xF0 + imm_vscy, + imm_vscz, + imm_vtcs, + imm_vtct, + imm_vtcq, + imm_cv, + imm_ap, + imm_fc, + imm_scv; // 0xF9 + // In the unlikely case we ever add anything else here, don't forget to update the padding on the next line! + u32 pad05[0xFF- 0xF9]; }; };