Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/FileSystems/BlockDevices.h
3186 views
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
#pragma once
19
20
// Abstractions around read-only blockdevices, such as PSP UMD discs.
21
// CISOFileBlockDevice implements compressed iso images, CISO format.
22
//
23
// The ISOFileSystemReader reads from a BlockDevice, so it automatically works
24
// with CISO images.
25
26
#include <mutex>
27
#include <memory>
28
29
#include "Common/CommonTypes.h"
30
31
#include "ext/libkirk/kirk_engine.h"
32
33
class FileLoader;
34
35
class BlockDevice {
36
public:
37
BlockDevice(FileLoader *fileLoader) : fileLoader_(fileLoader) {}
38
virtual ~BlockDevice() {}
39
virtual bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) = 0;
40
virtual bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
41
for (int b = 0; b < count; ++b) {
42
if (!ReadBlock(minBlock + b, outPtr)) {
43
return false;
44
}
45
outPtr += GetBlockSize();
46
}
47
return true;
48
}
49
int GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses
50
virtual u32 GetNumBlocks() const = 0;
51
virtual u64 GetUncompressedSize() const {
52
return (u64)GetNumBlocks() * (u64)GetBlockSize();
53
}
54
virtual bool IsDisc() const = 0;
55
56
void NotifyReadError();
57
58
bool IsOK() const { return errorString_.empty(); }
59
const std::string &ErrorString() { return errorString_; }
60
61
protected:
62
FileLoader *fileLoader_;
63
bool reportedError_ = false;
64
65
std::string errorString_;
66
};
67
68
class CISOFileBlockDevice : public BlockDevice {
69
public:
70
CISOFileBlockDevice(FileLoader *fileLoader);
71
~CISOFileBlockDevice();
72
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
73
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
74
u32 GetNumBlocks() const override { return numBlocks; }
75
bool IsDisc() const override { return true; }
76
77
private:
78
u32 *index = nullptr;
79
u8 *readBuffer = nullptr;
80
u8 *zlibBuffer = nullptr;
81
u32 zlibBufferFrame = 0;
82
u8 indexShift = 0;
83
u8 blockShift = 0;
84
u32 frameSize = 0;
85
u32 numBlocks = 0;
86
u32 numFrames = 0;
87
int ver_ = 0;
88
};
89
90
91
class FileBlockDevice : public BlockDevice {
92
public:
93
FileBlockDevice(FileLoader *fileLoader);
94
~FileBlockDevice();
95
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
96
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
97
u32 GetNumBlocks() const override {return (u32)(filesize_ / GetBlockSize());}
98
bool IsDisc() const override { return true; }
99
u64 GetUncompressedSize() const override {
100
return filesize_;
101
}
102
private:
103
u64 filesize_;
104
};
105
106
107
// For encrypted ISOs in PBP files.
108
109
struct table_info {
110
u8 mac[16];
111
u32 offset;
112
int size;
113
int flag;
114
int unk_1c;
115
};
116
117
class NPDRMDemoBlockDevice : public BlockDevice {
118
public:
119
NPDRMDemoBlockDevice(FileLoader *fileLoader);
120
~NPDRMDemoBlockDevice();
121
122
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
123
u32 GetNumBlocks() const override {return (u32)lbaSize_;}
124
bool IsDisc() const override { return false; }
125
126
private:
127
// This is in case two threads hit this same block device, which shouldn't really happen.
128
std::mutex mutex_;
129
130
u32 lbaSize_ = 0;
131
132
u32 psarOffset = 0;
133
int blockSize_ = 0;
134
int blockLBAs_ = 0;
135
u32 numBlocks_ = 0;
136
137
u8 vkey[16]{};
138
u8 hkey[16]{};
139
struct table_info *table_ = nullptr;
140
141
int currentBlock_ = 0;
142
u8 *blockBuf_ = nullptr;
143
u8 *tempBuf_ = nullptr;
144
145
// Each block device gets its own private kirk. Multiple ones can be in flight
146
// to load metadata.
147
KirkState kirk_{};
148
};
149
150
struct CHDImpl;
151
152
struct ExtendedCoreFile;
153
154
class CHDFileBlockDevice : public BlockDevice {
155
public:
156
CHDFileBlockDevice(FileLoader *fileLoader);
157
~CHDFileBlockDevice();
158
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
159
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
160
u32 GetNumBlocks() const override { return numBlocks; }
161
bool IsDisc() const override { return true; }
162
private:
163
struct ExtendedCoreFile *core_file_ = nullptr;
164
std::unique_ptr<CHDImpl> impl_;
165
u8 *readBuffer = nullptr;
166
u32 currentHunk = 0;
167
u32 blocksPerHunk = 0;
168
u32 numBlocks = 0;
169
};
170
171
BlockDevice *ConstructBlockDevice(FileLoader *fileLoader, std::string *errorString);
172
173