~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to GPU/Software/SoftGpu.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2012- PPSSPP Project.
 
2
 
 
3
// This program is free software: you can redistribute it and/or modify
 
4
// it under the terms of the GNU General Public License as published by
 
5
// the Free Software Foundation, version 2.0 or later versions.
 
6
 
 
7
// This program is distributed in the hope that it will be useful,
 
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
// GNU General Public License 2.0 for more details.
 
11
 
 
12
// A copy of the GPL 2.0 should have been included with the program.
 
13
// If not, see http://www.gnu.org/licenses/
 
14
 
 
15
// Official git repository and contact information can be found at
 
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
 
17
 
 
18
#include "GPU/GPUState.h"
 
19
#include "GPU/ge_constants.h"
 
20
#include "GPU/Common/TextureDecoder.h"
 
21
#include "Common/ColorConv.h"
 
22
#include "Common/GraphicsContext.h"
 
23
#include "Core/Config.h"
 
24
#include "Core/Debugger/Breakpoints.h"
 
25
#include "Core/Host.h"
 
26
#include "Core/MemMap.h"
 
27
#include "Core/HLE/sceKernelInterrupt.h"
 
28
#include "Core/HLE/sceGe.h"
 
29
#include "Core/MIPS/MIPS.h"
 
30
#include "Core/Reporting.h"
 
31
#include "profiler/profiler.h"
 
32
#include "thin3d/thin3d.h"
 
33
 
 
34
#include "GPU/Software/SoftGpu.h"
 
35
#include "GPU/Software/TransformUnit.h"
 
36
#include "GPU/Software/Rasterizer.h"
 
37
#include "GPU/Common/FramebufferCommon.h"
 
38
 
 
39
const int FB_WIDTH = 480;
 
40
const int FB_HEIGHT = 272;
 
41
FormatBuffer fb;
 
42
FormatBuffer depthbuf;
 
43
u32 clut[4096];
 
44
 
 
45
static Thin3DVertexFormat *vformat = nullptr;
 
46
static Thin3DDepthStencilState *depth = nullptr;
 
47
static Thin3DBuffer *vdata = nullptr;
 
48
static Thin3DBuffer *idata = nullptr;
 
49
 
 
50
SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Thin3DContext *_thin3D)
 
51
        : gfxCtx_(gfxCtx), thin3d(_thin3D)
 
52
{
 
53
        fbTex = thin3d->CreateTexture(LINEAR2D, RGBA8888, 480, 272, 1, 1);
 
54
 
 
55
        std::vector<Thin3DVertexComponent> components;
 
56
        components.push_back(Thin3DVertexComponent("Position", SEM_POSITION, FLOATx3, 0));
 
57
        components.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12));
 
58
        components.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20));
 
59
 
 
60
        Thin3DShader *vshader = thin3d->GetVshaderPreset(VS_TEXTURE_COLOR_2D);
 
61
        vformat = thin3d->CreateVertexFormat(components, 24, vshader);
 
62
 
 
63
        vdata = thin3d->CreateBuffer(24 * 4, T3DBufferUsage::DYNAMIC | T3DBufferUsage::VERTEXDATA);
 
64
        idata = thin3d->CreateBuffer(sizeof(int) * 6, T3DBufferUsage::DYNAMIC | T3DBufferUsage::INDEXDATA);
 
65
        depth = thin3d->CreateDepthStencilState(false, false, T3DComparison::LESS);
 
66
 
 
67
        fb.data = Memory::GetPointer(0x44000000); // TODO: correct default address?
 
68
        depthbuf.data = Memory::GetPointer(0x44000000); // TODO: correct default address?
 
69
 
 
70
        framebufferDirty_ = true;
 
71
        // TODO: Is there a default?
 
72
        displayFramebuf_ = 0;
 
73
        displayStride_ = 512;
 
74
        displayFormat_ = GE_FORMAT_8888;
 
75
}
 
76
 
 
77
void SoftGPU::DeviceLost() {
 
78
        // Handled by thin3d.
 
79
}
 
80
 
 
81
void SoftGPU::DeviceRestore() {
 
82
        // Handled by thin3d.
 
83
}
 
84
 
 
85
SoftGPU::~SoftGPU() {
 
86
        vformat->Release();
 
87
        vformat = nullptr;
 
88
        fbTex->Release();
 
89
        fbTex = nullptr;
 
90
 
 
91
        vdata->Release();
 
92
        vdata = nullptr;
 
93
        idata->Release();
 
94
        idata = nullptr;
 
95
        depth->Release();
 
96
        depth = nullptr;
 
97
}
 
98
 
 
99
void SoftGPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
 
100
        // Seems like this can point into RAM, but should be VRAM if not in RAM.
 
101
        displayFramebuf_ = (framebuf & 0xFF000000) == 0 ? 0x44000000 | framebuf : framebuf;
 
102
        displayStride_ = stride;
 
103
        displayFormat_ = format;
 
104
        host->GPUNotifyDisplay(framebuf, stride, format);
 
105
}
 
106
 
 
107
// Copies RGBA8 data from RAM to the currently bound render target.
 
108
void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
 
109
{
 
110
        if (!thin3d)
 
111
                return;
 
112
        float dstwidth = (float)PSP_CoreParameter().pixelWidth;
 
113
        float dstheight = (float)PSP_CoreParameter().pixelHeight;
 
114
 
 
115
        T3DViewport viewport = {0.0f, 0.0f, dstwidth, dstheight, 0.0f, 1.0f};
 
116
        thin3d->SetViewports(1, &viewport);
 
117
 
 
118
        thin3d->SetBlendState(thin3d->GetBlendStatePreset(BS_OFF));
 
119
        Thin3DSamplerState *sampler;
 
120
        if (g_Config.iBufFilter == SCALE_NEAREST) {
 
121
                sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_NEAREST);
 
122
        } else {
 
123
                sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_LINEAR);
 
124
        }
 
125
        thin3d->SetSamplerStates(0, 1, &sampler);
 
126
        thin3d->SetDepthStencilState(depth);
 
127
        thin3d->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
 
128
        thin3d->SetScissorEnabled(false);
 
129
 
 
130
        float u0 = 0.0f;
 
131
        float u1;
 
132
        if (!Memory::IsValidAddress(displayFramebuf_)) {
 
133
                u8 data[] = {0, 0, 0, 0};
 
134
                fbTex->SetImageData(0, 0, 0, 1, 1, 1, 0, 4, data);
 
135
                u1 = 1.0f;
 
136
        } else if (displayFormat_ == GE_FORMAT_8888) {
 
137
                u8 *data = Memory::GetPointer(displayFramebuf_);
 
138
                fbTex->SetImageData(0, 0, 0, displayStride_, srcheight, 1, 0, displayStride_ * 4, data);
 
139
                u1 = (float)srcwidth / displayStride_;
 
140
        } else {
 
141
                // TODO: This should probably be converted in a shader instead..
 
142
                fbTexBuffer.resize(srcwidth * srcheight);
 
143
                FormatBuffer displayBuffer;
 
144
                displayBuffer.data = Memory::GetPointer(displayFramebuf_);
 
145
                for (int y = 0; y < srcheight; ++y) {
 
146
                        u32 *buf_line = &fbTexBuffer[y * srcwidth];
 
147
                        const u16 *fb_line = &displayBuffer.as16[y * displayStride_];
 
148
 
 
149
                        switch (displayFormat_) {
 
150
                        case GE_FORMAT_565:
 
151
                                ConvertRGBA565ToRGBA8888(buf_line, fb_line, srcwidth);
 
152
                                break;
 
153
 
 
154
                        case GE_FORMAT_5551:
 
155
                                ConvertRGBA5551ToRGBA8888(buf_line, fb_line, srcwidth);
 
156
                                break;
 
157
 
 
158
                        case GE_FORMAT_4444:
 
159
                                ConvertRGBA4444ToRGBA8888(buf_line, fb_line, srcwidth);
 
160
                                break;
 
161
 
 
162
                        default:
 
163
                                ERROR_LOG_REPORT(G3D, "Software: Unexpected framebuffer format: %d", displayFormat_);
 
164
                        }
 
165
                }
 
166
 
 
167
                fbTex->SetImageData(0, 0, 0, srcwidth, srcheight, 1, 0, srcwidth * 4, (const uint8_t *)&fbTexBuffer[0]);
 
168
                u1 = 1.0f;
 
169
        }
 
170
        fbTex->Finalize(0);
 
171
 
 
172
        float x, y, w, h;
 
173
        CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);
 
174
 
 
175
        if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
 
176
                x += 0.5f;
 
177
                y += 0.5f;
 
178
        }
 
179
 
 
180
        x /= 0.5f * dstwidth;
 
181
        y /= 0.5f * dstheight;
 
182
        w /= 0.5f * dstwidth;
 
183
        h /= 0.5f * dstheight;
 
184
        float x2 = x + w;
 
185
        float y2 = y + h;
 
186
        x -= 1.0f;
 
187
        y -= 1.0f;
 
188
        x2 -= 1.0f;
 
189
        y2 -= 1.0f;
 
190
 
 
191
        struct Vertex {
 
192
                float x, y, z;
 
193
                float u, v;
 
194
                uint32_t rgba;
 
195
        };
 
196
 
 
197
        float v0 = 1.0f;
 
198
        float v1 = 0.0f;
 
199
 
 
200
        if (GetGPUBackend() == GPUBackend::VULKAN) {
 
201
                std::swap(v0, v1);
 
202
        }
 
203
 
 
204
        const Vertex verts[4] = {
 
205
                {x, y, 0,    u0, v0,  0xFFFFFFFF}, // TL
 
206
                {x, y2, 0,   u0, v1,  0xFFFFFFFF}, // BL
 
207
                {x2, y2, 0,  u1, v1,  0xFFFFFFFF}, // BR
 
208
                {x2, y, 0,   u1, v0,  0xFFFFFFFF}, // TR
 
209
        };
 
210
        vdata->SetData((const uint8_t *)verts, sizeof(verts));
 
211
 
 
212
        int indexes[] = {0, 1, 2, 0, 2, 3};
 
213
        idata->SetData((const uint8_t *)indexes, sizeof(indexes));
 
214
 
 
215
        thin3d->SetTexture(0, fbTex);
 
216
        Thin3DShaderSet *texColor = thin3d->GetShaderSetPreset(SS_TEXTURE_COLOR_2D);
 
217
 
 
218
        static const float identity4x4[16] = {
 
219
                1.0f, 0.0f, 0.0f, 0.0f,
 
220
                0.0f, 1.0f, 0.0f, 0.0f,
 
221
                0.0f, 0.0f, 1.0f, 0.0f,
 
222
                0.0f, 0.0f, 0.0f, 1.0f,
 
223
        };
 
224
 
 
225
        texColor->SetMatrix4x4("WorldViewProj", identity4x4);
 
226
        thin3d->DrawIndexed(T3DPrimitive::PRIM_TRIANGLES, texColor, vformat, vdata, idata, 6, 0);
 
227
}
 
228
 
 
229
void SoftGPU::CopyDisplayToOutput()
 
230
{
 
231
        ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
 
232
}
 
233
 
 
234
void SoftGPU::CopyDisplayToOutputInternal()
 
235
{
 
236
        // The display always shows 480x272.
 
237
        CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT);
 
238
        framebufferDirty_ = false;
 
239
}
 
240
 
 
241
void SoftGPU::ProcessEvent(GPUEvent ev) {
 
242
        switch (ev.type) {
 
243
        case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
 
244
                CopyDisplayToOutputInternal();
 
245
                break;
 
246
 
 
247
        default:
 
248
                GPUCommon::ProcessEvent(ev);
 
249
        }
 
250
}
 
251
 
 
252
void SoftGPU::FastRunLoop(DisplayList &list) {
 
253
        PROFILE_THIS_SCOPE("soft_runloop");
 
254
        for (; downcount > 0; --downcount) {
 
255
                u32 op = Memory::ReadUnchecked_U32(list.pc);
 
256
                u32 cmd = op >> 24;
 
257
 
 
258
                u32 diff = op ^ gstate.cmdmem[cmd];
 
259
                gstate.cmdmem[cmd] = op;
 
260
                ExecuteOp(op, diff);
 
261
 
 
262
                list.pc += 4;
 
263
        }
 
264
}
 
265
 
 
266
int EstimatePerVertexCost() {
 
267
        // TODO: This is transform cost, also account for rasterization cost somehow... although it probably
 
268
        // runs in parallel with transform.
 
269
 
 
270
        // Also, this is all pure guesswork. If we can find a way to do measurements, that would be great.
 
271
 
 
272
        // GTA wants a low value to run smooth, GoW wants a high value (otherwise it thinks things
 
273
        // went too fast and starts doing all the work over again).
 
274
 
 
275
        int cost = 20;
 
276
        if (gstate.isLightingEnabled()) {
 
277
                cost += 10;
 
278
        }
 
279
 
 
280
        for (int i = 0; i < 4; i++) {
 
281
                if (gstate.isLightChanEnabled(i))
 
282
                        cost += 10;
 
283
        }
 
284
        if (gstate.getUVGenMode() != GE_TEXMAP_TEXTURE_COORDS) {
 
285
                cost += 20;
 
286
        }
 
287
        // TODO: morphcount
 
288
 
 
289
        return cost;
 
290
}
 
291
 
 
292
void SoftGPU::ExecuteOp(u32 op, u32 diff)
 
293
{
 
294
        u32 cmd = op >> 24;
 
295
        u32 data = op & 0xFFFFFF;
 
296
 
 
297
        // Handle control and drawing commands here directly. The others we delegate.
 
298
        switch (cmd)
 
299
        {
 
300
        case GE_CMD_BASE:
 
301
                break;
 
302
 
 
303
        case GE_CMD_VADDR:
 
304
                gstate_c.vertexAddr = gstate_c.getRelativeAddress(data);
 
305
                break;
 
306
 
 
307
        case GE_CMD_IADDR:
 
308
                gstate_c.indexAddr      = gstate_c.getRelativeAddress(data);
 
309
                break;
 
310
 
 
311
        case GE_CMD_PRIM:
 
312
                {
 
313
                        u32 count = data & 0xFFFF;
 
314
                        u32 type = data >> 16;
 
315
 
 
316
                        if (!Memory::IsValidAddress(gstate_c.vertexAddr)) {
 
317
                                ERROR_LOG_REPORT(G3D, "Software: Bad vertex address %08x!", gstate_c.vertexAddr);
 
318
                                break;
 
319
                        }
 
320
 
 
321
                        void *verts = Memory::GetPointer(gstate_c.vertexAddr);
 
322
                        void *indices = NULL;
 
323
                        if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
 
324
                                if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
 
325
                                        ERROR_LOG_REPORT(G3D, "Software: Bad index address %08x!", gstate_c.indexAddr);
 
326
                                        break;
 
327
                                }
 
328
                                indices = Memory::GetPointer(gstate_c.indexAddr);
 
329
                        }
 
330
 
 
331
                        cyclesExecuted += EstimatePerVertexCost() * count;
 
332
                        int bytesRead;
 
333
                        TransformUnit::SubmitPrimitive(verts, indices, type, count, gstate.vertType, &bytesRead);
 
334
                        framebufferDirty_ = true;
 
335
 
 
336
                        // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
 
337
                        // Some games rely on this, they don't bother reloading VADDR and IADDR.
 
338
                        // The VADDR/IADDR registers are NOT updated.
 
339
                        AdvanceVerts(gstate.vertType, count, bytesRead);
 
340
                }
 
341
                break;
 
342
 
 
343
        case GE_CMD_BEZIER:
 
344
                {
 
345
                        int bz_ucount = data & 0xFF;
 
346
                        int bz_vcount = (data >> 8) & 0xFF;
 
347
                        DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount);
 
348
                }
 
349
                break;
 
350
 
 
351
        case GE_CMD_SPLINE:
 
352
                {
 
353
                        int sp_ucount = data & 0xFF;
 
354
                        int sp_vcount = (data >> 8) & 0xFF;
 
355
                        int sp_utype = (data >> 16) & 0x3;
 
356
                        int sp_vtype = (data >> 18) & 0x3;
 
357
 
 
358
                        if (!Memory::IsValidAddress(gstate_c.vertexAddr)) {
 
359
                                ERROR_LOG_REPORT(G3D, "Software: Bad vertex address %08x!", gstate_c.vertexAddr);
 
360
                                break;
 
361
                        }
 
362
 
 
363
                        void *control_points = Memory::GetPointer(gstate_c.vertexAddr);
 
364
                        // void *indices = NULL;
 
365
                        if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
 
366
                                if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
 
367
                                        ERROR_LOG_REPORT(G3D, "Software: Bad index address %08x!", gstate_c.indexAddr);
 
368
                                        break;
 
369
                                }
 
370
                                // indices = Memory::GetPointer(gstate_c.indexAddr);
 
371
                        }
 
372
 
 
373
                        if (gstate.getPatchPrimitiveType() != GE_PATCHPRIM_TRIANGLES) {
 
374
                                ERROR_LOG_REPORT(G3D, "Software: Unsupported patch primitive %x", gstate.patchprimitive&3);
 
375
                                break;
 
376
                        }
 
377
 
 
378
                        if (!(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME)) {
 
379
                                //TransformUnit::SubmitSpline(control_points, indices, sp_ucount, sp_vcount, sp_utype, sp_vtype, gstate.getPatchPrimitiveType(), gstate.vertType);
 
380
                        }
 
381
                        framebufferDirty_ = true;
 
382
                        DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype);
 
383
                }
 
384
                break;
 
385
 
 
386
        case GE_CMD_BOUNDINGBOX:
 
387
                if (data != 0)
 
388
                        DEBUG_LOG(G3D, "Unsupported bounding box: %06x", data);
 
389
                // bounding box test. Let's assume the box was within the drawing region.
 
390
                currentList->bboxResult = true;
 
391
                break;
 
392
 
 
393
        case GE_CMD_VERTEXTYPE:
 
394
                break;
 
395
 
 
396
        case GE_CMD_REGION1:
 
397
        case GE_CMD_REGION2:
 
398
                break;
 
399
 
 
400
        case GE_CMD_CLIPENABLE:
 
401
                break;
 
402
 
 
403
        case GE_CMD_CULLFACEENABLE:
 
404
        case GE_CMD_CULL:
 
405
                break;
 
406
 
 
407
        case GE_CMD_TEXTUREMAPENABLE: 
 
408
                break;
 
409
 
 
410
        case GE_CMD_LIGHTINGENABLE:
 
411
                break;
 
412
 
 
413
        case GE_CMD_FOGCOLOR:
 
414
        case GE_CMD_FOG1:
 
415
        case GE_CMD_FOG2:
 
416
        case GE_CMD_FOGENABLE:
 
417
                break;
 
418
 
 
419
        case GE_CMD_DITHERENABLE:
 
420
                break;
 
421
 
 
422
        case GE_CMD_OFFSETX:
 
423
                break;
 
424
 
 
425
        case GE_CMD_OFFSETY:
 
426
                break;
 
427
 
 
428
        case GE_CMD_TEXSCALEU:
 
429
                gstate_c.uv.uScale = getFloat24(data);
 
430
                break;
 
431
 
 
432
        case GE_CMD_TEXSCALEV:
 
433
                gstate_c.uv.vScale = getFloat24(data);
 
434
                break;
 
435
 
 
436
        case GE_CMD_TEXOFFSETU:
 
437
                gstate_c.uv.uOff = getFloat24(data);
 
438
                break;
 
439
 
 
440
        case GE_CMD_TEXOFFSETV:
 
441
                gstate_c.uv.vOff = getFloat24(data);
 
442
                break;
 
443
 
 
444
        case GE_CMD_SCISSOR1:
 
445
        case GE_CMD_SCISSOR2:
 
446
                break;
 
447
 
 
448
        case GE_CMD_MINZ:
 
449
                break;
 
450
 
 
451
        case GE_CMD_FRAMEBUFPTR:
 
452
                fb.data = Memory::GetPointer(gstate.getFrameBufAddress());
 
453
                break;
 
454
 
 
455
        case GE_CMD_FRAMEBUFWIDTH:
 
456
                fb.data = Memory::GetPointer(gstate.getFrameBufAddress());
 
457
                break;
 
458
 
 
459
        case GE_CMD_FRAMEBUFPIXFORMAT:
 
460
                break;
 
461
 
 
462
        case GE_CMD_TEXADDR0:
 
463
        case GE_CMD_TEXADDR1:
 
464
        case GE_CMD_TEXADDR2:
 
465
        case GE_CMD_TEXADDR3:
 
466
        case GE_CMD_TEXADDR4:
 
467
        case GE_CMD_TEXADDR5:
 
468
        case GE_CMD_TEXADDR6:
 
469
        case GE_CMD_TEXADDR7:
 
470
                break;
 
471
 
 
472
        case GE_CMD_TEXBUFWIDTH0:
 
473
        case GE_CMD_TEXBUFWIDTH1:
 
474
        case GE_CMD_TEXBUFWIDTH2:
 
475
        case GE_CMD_TEXBUFWIDTH3:
 
476
        case GE_CMD_TEXBUFWIDTH4:
 
477
        case GE_CMD_TEXBUFWIDTH5:
 
478
        case GE_CMD_TEXBUFWIDTH6:
 
479
        case GE_CMD_TEXBUFWIDTH7:
 
480
                break;
 
481
 
 
482
        case GE_CMD_CLUTADDR:
 
483
        case GE_CMD_CLUTADDRUPPER:
 
484
                break;
 
485
 
 
486
        case GE_CMD_LOADCLUT:
 
487
                {
 
488
                        u32 clutAddr = gstate.getClutAddress();
 
489
                        u32 clutTotalBytes = gstate.getClutLoadBytes();
 
490
 
 
491
                        if (Memory::IsValidAddress(clutAddr)) {
 
492
                                u32 validSize = Memory::ValidSize(clutAddr, clutTotalBytes);
 
493
                                Memory::MemcpyUnchecked(clut, clutAddr, validSize);
 
494
                                if (validSize < clutTotalBytes) {
 
495
                                        // Zero out the parts that were outside valid memory.
 
496
                                        memset((u8 *)clut + validSize, 0x00, clutTotalBytes - validSize);
 
497
                                }
 
498
                        } else if (clutAddr != 0) {
 
499
                                // Some invalid addresses trigger a crash, others fill with zero.  We always fill zero.
 
500
                                DEBUG_LOG(G3D, "Software: Invalid CLUT address, filling with garbage instead of crashing");
 
501
                                memset(clut, 0x00, clutTotalBytes);
 
502
                        }
 
503
                }
 
504
                break;
 
505
 
 
506
        // Don't need to do anything, just state for transferstart.
 
507
        case GE_CMD_TRANSFERSRC:
 
508
        case GE_CMD_TRANSFERSRCW:
 
509
        case GE_CMD_TRANSFERDST:
 
510
        case GE_CMD_TRANSFERDSTW:
 
511
        case GE_CMD_TRANSFERSRCPOS:
 
512
        case GE_CMD_TRANSFERDSTPOS:
 
513
        case GE_CMD_TRANSFERSIZE:
 
514
                break;
 
515
 
 
516
        case GE_CMD_TRANSFERSTART:
 
517
                {
 
518
                        u32 srcBasePtr = gstate.getTransferSrcAddress();
 
519
                        u32 srcStride = gstate.getTransferSrcStride();
 
520
 
 
521
                        u32 dstBasePtr = gstate.getTransferDstAddress();
 
522
                        u32 dstStride = gstate.getTransferDstStride();
 
523
 
 
524
                        int srcX = gstate.getTransferSrcX();
 
525
                        int srcY = gstate.getTransferSrcY();
 
526
 
 
527
                        int dstX = gstate.getTransferDstX();
 
528
                        int dstY = gstate.getTransferDstY();
 
529
 
 
530
                        int width = gstate.getTransferWidth();
 
531
                        int height = gstate.getTransferHeight();
 
532
 
 
533
                        int bpp = gstate.getTransferBpp();
 
534
 
 
535
                        DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY);
 
536
 
 
537
                        for (int y = 0; y < height; y++) {
 
538
                                const u8 *src = Memory::GetPointer(srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp);
 
539
                                u8 *dst = Memory::GetPointer(dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp);
 
540
                                memcpy(dst, src, width * bpp);
 
541
                        }
 
542
 
 
543
#ifndef MOBILE_DEVICE
 
544
                        CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc);
 
545
                        CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc);
 
546
#endif
 
547
 
 
548
                        // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
 
549
                        cyclesExecuted += ((height * width * bpp) * 16) / 10;
 
550
 
 
551
                        // Could theoretically dirty the framebuffer.
 
552
                        framebufferDirty_ = true;
 
553
                        break;
 
554
                }
 
555
 
 
556
        case GE_CMD_TEXSIZE0:
 
557
        case GE_CMD_TEXSIZE1:
 
558
        case GE_CMD_TEXSIZE2:
 
559
        case GE_CMD_TEXSIZE3:
 
560
        case GE_CMD_TEXSIZE4:
 
561
        case GE_CMD_TEXSIZE5:
 
562
        case GE_CMD_TEXSIZE6:
 
563
        case GE_CMD_TEXSIZE7:
 
564
                break;
 
565
 
 
566
        case GE_CMD_ZBUFPTR:
 
567
                depthbuf.data = Memory::GetPointer(gstate.getDepthBufAddress());
 
568
                break;
 
569
 
 
570
        case GE_CMD_ZBUFWIDTH:
 
571
                depthbuf.data = Memory::GetPointer(gstate.getDepthBufAddress());
 
572
                break;
 
573
 
 
574
        case GE_CMD_AMBIENTCOLOR:
 
575
        case GE_CMD_AMBIENTALPHA:
 
576
        case GE_CMD_MATERIALAMBIENT:
 
577
        case GE_CMD_MATERIALDIFFUSE:
 
578
        case GE_CMD_MATERIALEMISSIVE:
 
579
        case GE_CMD_MATERIALSPECULAR:
 
580
        case GE_CMD_MATERIALALPHA:
 
581
        case GE_CMD_MATERIALSPECULARCOEF:
 
582
                break;
 
583
 
 
584
        case GE_CMD_LIGHTTYPE0:
 
585
        case GE_CMD_LIGHTTYPE1:
 
586
        case GE_CMD_LIGHTTYPE2:
 
587
        case GE_CMD_LIGHTTYPE3:
 
588
                break;
 
589
 
 
590
        case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0:
 
591
        case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1:
 
592
        case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2:
 
593
        case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3:
 
594
                break;
 
595
 
 
596
        case GE_CMD_LDX0:case GE_CMD_LDY0:case GE_CMD_LDZ0:
 
597
        case GE_CMD_LDX1:case GE_CMD_LDY1:case GE_CMD_LDZ1:
 
598
        case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2:
 
599
        case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3:
 
600
                break;
 
601
 
 
602
        case GE_CMD_LKA0:case GE_CMD_LKB0:case GE_CMD_LKC0:
 
603
        case GE_CMD_LKA1:case GE_CMD_LKB1:case GE_CMD_LKC1:
 
604
        case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2:
 
605
        case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3:
 
606
                break;
 
607
 
 
608
        case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3:
 
609
        case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3:
 
610
        case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3:
 
611
                break;
 
612
 
 
613
        case GE_CMD_VIEWPORTXSCALE:
 
614
        case GE_CMD_VIEWPORTYSCALE:
 
615
        case GE_CMD_VIEWPORTZSCALE:
 
616
        case GE_CMD_VIEWPORTXCENTER:
 
617
        case GE_CMD_VIEWPORTYCENTER:
 
618
        case GE_CMD_VIEWPORTZCENTER:
 
619
                break;
 
620
 
 
621
        case GE_CMD_LIGHTENABLE0:
 
622
        case GE_CMD_LIGHTENABLE1:
 
623
        case GE_CMD_LIGHTENABLE2:
 
624
        case GE_CMD_LIGHTENABLE3:
 
625
                break;
 
626
 
 
627
        case GE_CMD_LIGHTMODE:
 
628
                break;
 
629
 
 
630
        case GE_CMD_PATCHDIVISION:
 
631
                break;
 
632
 
 
633
        case GE_CMD_MATERIALUPDATE:
 
634
                break;
 
635
 
 
636
        //////////////////////////////////////////////////////////////////
 
637
        //      CLEARING
 
638
        //////////////////////////////////////////////////////////////////
 
639
        case GE_CMD_CLEARMODE:
 
640
                break;
 
641
 
 
642
        //////////////////////////////////////////////////////////////////
 
643
        //      ALPHA BLENDING
 
644
        //////////////////////////////////////////////////////////////////
 
645
        case GE_CMD_ALPHABLENDENABLE:
 
646
                break;
 
647
 
 
648
        case GE_CMD_BLENDMODE:
 
649
                break;
 
650
 
 
651
        case GE_CMD_BLENDFIXEDA:
 
652
        case GE_CMD_BLENDFIXEDB:
 
653
                break;
 
654
 
 
655
        case GE_CMD_ALPHATESTENABLE:
 
656
        case GE_CMD_ALPHATEST:
 
657
                break;
 
658
 
 
659
        case GE_CMD_TEXFUNC:
 
660
        case GE_CMD_TEXFILTER:
 
661
                break;
 
662
 
 
663
        //////////////////////////////////////////////////////////////////
 
664
        //      Z/STENCIL TESTING
 
665
        //////////////////////////////////////////////////////////////////
 
666
 
 
667
        case GE_CMD_ZTESTENABLE:
 
668
        case GE_CMD_STENCILTESTENABLE:
 
669
        case GE_CMD_ZTEST:
 
670
                break;
 
671
 
 
672
        case GE_CMD_MORPHWEIGHT0:
 
673
        case GE_CMD_MORPHWEIGHT1:
 
674
        case GE_CMD_MORPHWEIGHT2:
 
675
        case GE_CMD_MORPHWEIGHT3:
 
676
        case GE_CMD_MORPHWEIGHT4:
 
677
        case GE_CMD_MORPHWEIGHT5:
 
678
        case GE_CMD_MORPHWEIGHT6:
 
679
        case GE_CMD_MORPHWEIGHT7:
 
680
                gstate_c.morphWeights[cmd - GE_CMD_MORPHWEIGHT0] = getFloat24(data);
 
681
                break;
 
682
 
 
683
        case GE_CMD_DITH0:
 
684
        case GE_CMD_DITH1:
 
685
        case GE_CMD_DITH2:
 
686
        case GE_CMD_DITH3:
 
687
                break;
 
688
 
 
689
        case GE_CMD_WORLDMATRIXNUMBER:
 
690
                gstate.worldmtxnum = data & 0xF;
 
691
                break;
 
692
 
 
693
        case GE_CMD_WORLDMATRIXDATA:
 
694
                {
 
695
                        int num = gstate.worldmtxnum & 0xF;
 
696
                        if (num < 12) {
 
697
                                gstate.worldMatrix[num] = getFloat24(data);
 
698
                        }
 
699
                        gstate.worldmtxnum = (++num) & 0xF;
 
700
                }
 
701
                break;
 
702
 
 
703
        case GE_CMD_VIEWMATRIXNUMBER:
 
704
                gstate.viewmtxnum = data & 0xF;
 
705
                break;
 
706
 
 
707
        case GE_CMD_VIEWMATRIXDATA:
 
708
                {
 
709
                        int num = gstate.viewmtxnum & 0xF;
 
710
                        if (num < 12) {
 
711
                                gstate.viewMatrix[num] = getFloat24(data);
 
712
                        }
 
713
                        gstate.viewmtxnum = (++num) & 0xF;
 
714
                }
 
715
                break;
 
716
 
 
717
        case GE_CMD_PROJMATRIXNUMBER:
 
718
                gstate.projmtxnum = data & 0xF;
 
719
                break;
 
720
 
 
721
        case GE_CMD_PROJMATRIXDATA:
 
722
                {
 
723
                        int num = gstate.projmtxnum & 0xF;
 
724
                        gstate.projMatrix[num] = getFloat24(data);
 
725
                        gstate.projmtxnum = (++num) & 0xF;
 
726
                }
 
727
                break;
 
728
 
 
729
        case GE_CMD_TGENMATRIXNUMBER:
 
730
                gstate.texmtxnum = data&0xF;
 
731
                break;
 
732
 
 
733
        case GE_CMD_TGENMATRIXDATA:
 
734
                {
 
735
                        int num = gstate.texmtxnum & 0xF;
 
736
                        if (num < 12) {
 
737
                                gstate.tgenMatrix[num] = getFloat24(data);
 
738
                        }
 
739
                        gstate.texmtxnum = (++num) & 0xF;
 
740
                }
 
741
                break;
 
742
 
 
743
        case GE_CMD_BONEMATRIXNUMBER:
 
744
                gstate.boneMatrixNumber = data & 0x7F;
 
745
                break;
 
746
 
 
747
        case GE_CMD_BONEMATRIXDATA:
 
748
                {
 
749
                        int num = gstate.boneMatrixNumber & 0x7F;
 
750
                        if (num < 96) {
 
751
                                gstate.boneMatrix[num] = getFloat24(data);
 
752
                        }
 
753
                        gstate.boneMatrixNumber = (++num) & 0x7F;
 
754
                }
 
755
                break;
 
756
 
 
757
        default:
 
758
                GPUCommon::ExecuteOp(op, diff);
 
759
                break;
 
760
        }
 
761
}
 
762
 
 
763
void SoftGPU::GetStats(char *buffer, size_t bufsize) {
 
764
        snprintf(buffer, bufsize, "SoftGPU: (N/A)");
 
765
}
 
766
 
 
767
void SoftGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type)
 
768
{
 
769
        // Nothing to invalidate.
 
770
}
 
771
 
 
772
void SoftGPU::NotifyVideoUpload(u32 addr, int size, int width, int format)
 
773
{
 
774
        // Ignore.
 
775
}
 
776
 
 
777
bool SoftGPU::PerformMemoryCopy(u32 dest, u32 src, int size)
 
778
{
 
779
        // Nothing to update.
 
780
        InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
 
781
        // Let's just be safe.
 
782
        framebufferDirty_ = true;
 
783
        return false;
 
784
}
 
785
 
 
786
bool SoftGPU::PerformMemorySet(u32 dest, u8 v, int size)
 
787
{
 
788
        // Nothing to update.
 
789
        InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
 
790
        // Let's just be safe.
 
791
        framebufferDirty_ = true;
 
792
        return false;
 
793
}
 
794
 
 
795
bool SoftGPU::PerformMemoryDownload(u32 dest, int size)
 
796
{
 
797
        // Nothing to update.
 
798
        InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
 
799
        return false;
 
800
}
 
801
 
 
802
bool SoftGPU::PerformMemoryUpload(u32 dest, int size)
 
803
{
 
804
        // Nothing to update.
 
805
        InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
 
806
        return false;
 
807
}
 
808
 
 
809
bool SoftGPU::PerformStencilUpload(u32 dest, int size)
 
810
{
 
811
        return false;
 
812
}
 
813
 
 
814
bool SoftGPU::FramebufferDirty() {
 
815
        if (g_Config.bSeparateCPUThread) {
 
816
                // Allow it to process fully before deciding if it's dirty.
 
817
                SyncThread();
 
818
        }
 
819
 
 
820
        if (g_Config.iFrameSkip != 0) {
 
821
                bool dirty = framebufferDirty_;
 
822
                framebufferDirty_ = false;
 
823
                return dirty;
 
824
        }
 
825
        return true;
 
826
}
 
827
 
 
828
bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes)
 
829
{
 
830
        const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1;
 
831
        const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1;
 
832
        buffer.Allocate(w, h, gstate.FrameBufFormat());
 
833
 
 
834
        const int depth = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2;
 
835
        const u8 *src = fb.data + gstate.FrameBufStride() * depth * gstate.getRegionY1();
 
836
        u8 *dst = buffer.GetData();
 
837
        for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) {
 
838
                memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * depth);
 
839
                dst += w * depth;
 
840
                src += gstate.FrameBufStride() * depth;
 
841
        }
 
842
        return true;
 
843
}
 
844
 
 
845
bool SoftGPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer)
 
846
{
 
847
        const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1;
 
848
        const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1;
 
849
        buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT);
 
850
 
 
851
        const int depth = 2;
 
852
        const u8 *src = depthbuf.data + gstate.DepthBufStride() * depth * gstate.getRegionY1();
 
853
        u8 *dst = buffer.GetData();
 
854
        for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) {
 
855
                memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * depth);
 
856
                dst += w * depth;
 
857
                src += gstate.DepthBufStride() * depth;
 
858
        }
 
859
        return true;
 
860
}
 
861
 
 
862
bool SoftGPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer)
 
863
{
 
864
        return Rasterizer::GetCurrentStencilbuffer(buffer);
 
865
}
 
866
 
 
867
bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer, int level)
 
868
{
 
869
        return Rasterizer::GetCurrentTexture(buffer, level);
 
870
}
 
871
 
 
872
bool SoftGPU::GetCurrentClut(GPUDebugBuffer &buffer)
 
873
{
 
874
        const u32 bpp = gstate.getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 4 : 2;
 
875
        const u32 pixels = 1024 / bpp;
 
876
 
 
877
        buffer.Allocate(pixels, 1, (GEBufferFormat)gstate.getClutPaletteFormat());
 
878
        memcpy(buffer.GetData(), clut, 1024);
 
879
        return true;
 
880
}
 
881
 
 
882
bool SoftGPU::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices)
 
883
{
 
884
        return TransformUnit::GetCurrentSimpleVertices(count, vertices, indices);
 
885
}