Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/core/cdrom_async_reader.h
4223 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
#include "util/cd_image.h"
6
#include "types.h"
7
#include <array>
8
#include <atomic>
9
#include <condition_variable>
10
#include <thread>
11
12
class ProgressCallback;
13
14
class CDROMAsyncReader
15
{
16
public:
17
using SectorBuffer = std::array<u8, CDImage::RAW_SECTOR_SIZE>;
18
19
struct BufferSlot
20
{
21
CDImage::LBA lba;
22
SectorBuffer data;
23
CDImage::SubChannelQ subq;
24
bool result;
25
};
26
27
CDROMAsyncReader();
28
~CDROMAsyncReader();
29
30
CDImage::LBA GetLastReadSector() const { return m_buffers[m_buffer_front.load()].lba; }
31
const SectorBuffer& GetSectorBuffer() const { return m_buffers[m_buffer_front.load()].data; }
32
const CDImage::SubChannelQ& GetSectorSubQ() const { return m_buffers[m_buffer_front.load()].subq; }
33
u32 GetBufferedSectorCount() const { return m_buffer_count.load(); }
34
bool HasBufferedSectors() const { return (m_buffer_count.load() > 0); }
35
u32 GetReadaheadCount() const { return static_cast<u32>(m_buffers.size()); }
36
37
bool HasMedia() const { return static_cast<bool>(m_media); }
38
const CDImage* GetMedia() const { return m_media.get(); }
39
CDImage* GetMedia() { return m_media.get(); }
40
const std::string& GetMediaPath() const { return m_media->GetPath(); }
41
42
bool IsUsingThread() const { return m_read_thread.joinable(); }
43
void StartThread(u32 readahead_count = 8);
44
void StopThread();
45
46
void SetMedia(std::unique_ptr<CDImage> media);
47
std::unique_ptr<CDImage> RemoveMedia();
48
49
/// Precaches image, either to memory, or using the underlying image precache.
50
bool Precache(ProgressCallback* callback);
51
52
void QueueReadSector(CDImage::LBA lba);
53
54
bool WaitForReadToComplete();
55
void WaitForIdle();
56
57
/// Bypasses the sector cache and reads directly from the image.
58
bool ReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data);
59
60
private:
61
void EmptyBuffers();
62
bool ReadSectorIntoBuffer(std::unique_lock<std::mutex>& lock);
63
void ReadSectorNonThreaded(CDImage::LBA lba);
64
bool InternalReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data);
65
void CancelReadahead();
66
67
void WorkerThreadEntryPoint();
68
69
std::unique_ptr<CDImage> m_media;
70
71
std::mutex m_mutex;
72
std::thread m_read_thread;
73
std::condition_variable m_do_read_cv;
74
std::condition_variable m_notify_read_complete_cv;
75
76
std::atomic<CDImage::LBA> m_next_position{};
77
std::atomic_bool m_next_position_set{false};
78
std::atomic_bool m_shutdown_flag{true};
79
80
std::atomic_bool m_is_reading{false};
81
std::atomic_bool m_can_readahead{false};
82
std::atomic_bool m_seek_error{false};
83
84
std::vector<BufferSlot> m_buffers;
85
std::atomic<u32> m_buffer_front{0};
86
std::atomic<u32> m_buffer_back{0};
87
std::atomic<u32> m_buffer_count{0};
88
};
89
90