~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Core/HLE/sceDmac.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 "Common/ChunkFile.h"
 
19
#include "Core/CoreTiming.h"
 
20
#include "Core/MemMapHelpers.h"
 
21
#include "Core/Reporting.h"
 
22
#include "Core/HLE/HLE.h"
 
23
#include "Core/HLE/sceDmac.h"
 
24
#include "Core/HLE/sceKernel.h"
 
25
#include "Core/HLE/FunctionWrappers.h"
 
26
#include "Core/Debugger/Breakpoints.h"
 
27
#include "GPU/GPUInterface.h"
 
28
#include "GPU/GPUState.h"
 
29
 
 
30
u64 dmacMemcpyDeadline;
 
31
 
 
32
void __DmacInit() {
 
33
        dmacMemcpyDeadline = 0;
 
34
}
 
35
 
 
36
void __DmacDoState(PointerWrap &p) {
 
37
        auto s = p.Section("sceDmac", 0, 1);
 
38
        if (s == 0) {
 
39
                dmacMemcpyDeadline = 0;
 
40
                return;
 
41
        }
 
42
 
 
43
        p.Do(dmacMemcpyDeadline);
 
44
}
 
45
 
 
46
static int __DmacMemcpy(u32 dst, u32 src, u32 size) {
 
47
        bool skip = false;
 
48
        if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) {
 
49
                skip = gpu->PerformMemoryCopy(dst, src, size);
 
50
        }
 
51
        if (!skip) {
 
52
                Memory::Memcpy(dst, Memory::GetPointer(src), size);
 
53
                currentMIPS->InvalidateICache(dst, size);
 
54
        }
 
55
 
 
56
        // This number seems strangely reproducible.
 
57
        if (size >= 272) {
 
58
                // Approx. 225 MiB/s or 235929600 B/s, so let's go with 236 B/us.
 
59
                int delayUs = size / 236;
 
60
                dmacMemcpyDeadline = CoreTiming::GetTicks() + usToCycles(delayUs);
 
61
                return hleDelayResult(0, "dmac copy", delayUs);
 
62
        }
 
63
        return 0;
 
64
}
 
65
 
 
66
static u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) {
 
67
        if (size == 0) {
 
68
                // Some games seem to do this frequently.
 
69
                DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size);
 
70
                return SCE_KERNEL_ERROR_INVALID_SIZE;
 
71
        }
 
72
        if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) {
 
73
                ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);
 
74
                return SCE_KERNEL_ERROR_INVALID_POINTER;
 
75
        }
 
76
        if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {
 
77
                ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);
 
78
                return SCE_KERNEL_ERROR_PRIV_REQUIRED;
 
79
        }
 
80
 
 
81
        if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {
 
82
                WARN_LOG_REPORT(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): overlapping read", dst, src, size);
 
83
                // TODO: Should block, seems like copy doesn't start until previous finishes.
 
84
                // Might matter for overlapping copies.
 
85
        } else {
 
86
                DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size);
 
87
        }
 
88
 
 
89
        return __DmacMemcpy(dst, src, size);
 
90
}
 
91
 
 
92
static u32 sceDmacTryMemcpy(u32 dst, u32 src, u32 size) {
 
93
        if (size == 0) {
 
94
                ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size);
 
95
                return SCE_KERNEL_ERROR_INVALID_SIZE;
 
96
        }
 
97
        if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) {
 
98
                ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);
 
99
                return SCE_KERNEL_ERROR_INVALID_POINTER;
 
100
        }
 
101
        if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {
 
102
                ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);
 
103
                return SCE_KERNEL_ERROR_PRIV_REQUIRED;
 
104
        }
 
105
 
 
106
        if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {
 
107
                DEBUG_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): busy", dst, src, size);
 
108
                return SCE_KERNEL_ERROR_BUSY;
 
109
        } else {
 
110
                DEBUG_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size);
 
111
        }
 
112
 
 
113
        return __DmacMemcpy(dst, src, size);
 
114
}
 
115
 
 
116
const HLEFunction sceDmac[] = {
 
117
        {0X617F3FE6, &WrapU_UUU<sceDmacMemcpy>,          "sceDmacMemcpy",    'x', "xxx"},
 
118
        {0XD97F94D8, &WrapU_UUU<sceDmacTryMemcpy>,       "sceDmacTryMemcpy", 'x', "xxx"},
 
119
};
 
120
 
 
121
void Register_sceDmac() {
 
122
        RegisterModule("sceDmac", ARRAY_SIZE(sceDmac), sceDmac);
 
123
}