Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/FileSystems/BlockDevices.h
5696 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 constexpr GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses. If a subclass uses bigger blocks internally, it must cache and virtualize.
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
class FileBlockDevice : public BlockDevice {
91
public:
92
FileBlockDevice(FileLoader *fileLoader);
93
~FileBlockDevice();
94
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
95
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
96
u32 GetNumBlocks() const override {return (u32)(filesize_ / GetBlockSize());}
97
bool IsDisc() const override { return true; }
98
u64 GetUncompressedSize() const override {
99
return filesize_;
100
}
101
private:
102
u64 filesize_;
103
};
104
105
106
// For encrypted ISOs in PBP files.
107
108
struct table_info {
109
u8 mac[16];
110
u32 offset;
111
int size;
112
int flag;
113
int unk_1c;
114
};
115
116
class NPDRMDemoBlockDevice : public BlockDevice {
117
public:
118
NPDRMDemoBlockDevice(FileLoader *fileLoader);
119
~NPDRMDemoBlockDevice();
120
121
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
122
u32 GetNumBlocks() const override {return (u32)lbaSize_;}
123
bool IsDisc() const override { return false; }
124
125
private:
126
// This is in case two threads hit this same block device, which shouldn't really happen.
127
std::mutex mutex_;
128
129
u32 lbaSize_ = 0;
130
131
u32 psarOffset = 0;
132
int blockSize_ = 0;
133
int blockLBAs_ = 0;
134
u32 numBlocks_ = 0;
135
136
u8 vkey[16]{};
137
u8 hkey[16]{};
138
struct table_info *table_ = nullptr;
139
140
int currentBlock_ = 0;
141
u8 *blockBuf_ = nullptr;
142
u8 *tempBuf_ = nullptr;
143
144
// Each block device gets its own private kirk. Multiple ones can be in flight
145
// to load metadata.
146
KirkState kirk_{};
147
};
148
149
struct CHDImpl;
150
151
struct ExtendedCoreFile;
152
153
class CHDFileBlockDevice : public BlockDevice {
154
public:
155
CHDFileBlockDevice(FileLoader *fileLoader);
156
~CHDFileBlockDevice();
157
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
158
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
159
u32 GetNumBlocks() const override { return numBlocks; }
160
bool IsDisc() const override { return true; }
161
private:
162
struct ExtendedCoreFile *core_file_ = nullptr;
163
std::unique_ptr<CHDImpl> impl_;
164
u8 *readBuffer = nullptr;
165
u32 currentHunk = 0;
166
u32 blocksPerHunk = 0;
167
u32 numBlocks = 0;
168
};
169
170
BlockDevice *ConstructBlockDevice(FileLoader *fileLoader, std::string *errorString);
171
172