Nugget
Loading...
Searching...
No Matches
cdrom-device.hh
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2022 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27#pragma once
28
29#include <EASTL/fixed_vector.h>
30#include <EASTL/functional.h>
31#include <stdint.h>
32
33#include <concepts>
34#include <coroutine>
35#include <cstdint>
36#include <type_traits>
37
38#include "psyqo/cdrom.hh"
39#include "psyqo/msf.hh"
40#include "psyqo/task.hh"
41
42namespace psyqo {
43
44class GPU;
45
46namespace Concepts {
47
48template <typename T, typename = void>
49struct CDRomDeviceStateEnumHasIdle : std::false_type {};
50
51template <typename T>
52struct CDRomDeviceStateEnumHasIdle<T, std::enable_if_t<T::IDLE == T(0)>> : std::true_type {};
53
54template <typename T>
56 std::is_enum_v<T> && std::is_same_v<uint8_t, std::underlying_type_t<T>> && CDRomDeviceStateEnumHasIdle<T>::value;
57
58} // namespace Concepts
59
79class CDRomDevice final : public CDRom {
80 public:
81 typedef eastl::fixed_vector<uint8_t, 16, false> Response;
85 unsigned track;
86 unsigned index;
87 };
88
89 struct ResetAwaiter {
90 ResetAwaiter(CDRomDevice &device) : m_device(device) {}
91 bool await_ready() const { return false; }
92 template <typename U>
93 void await_suspend(std::coroutine_handle<U> handle) {
94 m_device.reset([handle, this](bool result) {
95 m_result = result;
96 handle.resume();
97 });
98 }
99 bool await_resume() { return m_result; }
100
101 private:
102 CDRomDevice &m_device;
103 bool m_result;
104 };
105
107 GetTOCSizeAwaiter(CDRomDevice &device) : m_device(device) {}
108 bool await_ready() const { return false; }
109 template <typename U>
110 void await_suspend(std::coroutine_handle<U> handle) {
111 m_device.getTOCSize(&m_result, [handle, this](bool success) {
112 m_success = success;
113 handle.resume();
114 });
115 }
116 unsigned await_resume() { return m_success ? m_result : 0; }
117
118 private:
119 CDRomDevice &m_device;
120 unsigned m_result;
121 bool m_success;
122 };
123
125 ReadTOCAwaiter(CDRomDevice &device, MSF *toc, unsigned size) : m_device(device), m_toc(toc), m_size(size) {}
126 bool await_ready() const { return false; }
127 template <typename U>
128 void await_suspend(std::coroutine_handle<U> handle) {
129 m_device.readTOC(m_toc, m_size, [handle, this](bool result) {
130 m_result = result;
131 handle.resume();
132 });
133 }
134 bool await_resume() { return m_result; }
135
136 private:
137 CDRomDevice &m_device;
138 MSF *m_toc;
139 unsigned m_size;
140 bool m_result;
141 };
142
143 struct MuteAwaiter {
144 MuteAwaiter(CDRomDevice &device) : m_device(device) {}
145 bool await_ready() const { return false; }
146 template <typename U>
147 void await_suspend(std::coroutine_handle<U> handle) {
148 m_device.mute([handle, this](bool result) {
149 m_result = result;
150 handle.resume();
151 });
152 }
153 bool await_resume() { return m_result; }
154
155 private:
156 CDRomDevice &m_device;
157 bool m_result;
158 };
159
161 UnmuteAwaiter(CDRomDevice &device) : m_device(device) {}
162 bool await_ready() const { return false; }
163 template <typename U>
164 void await_suspend(std::coroutine_handle<U> handle) {
165 m_device.unmute([handle, this](bool result) {
166 m_result = result;
167 handle.resume();
168 });
169 }
170 bool await_resume() { return m_result; }
171
172 private:
173 CDRomDevice &m_device;
174 bool m_result;
175 };
176
178 GetPlaybackLocationAwaiter(CDRomDevice &device) : m_device(device) {}
179 bool await_ready() const { return false; }
180 template <typename U>
181 void await_suspend(std::coroutine_handle<U> handle) {
182 m_device.getPlaybackLocation([handle, this](PlaybackLocation *location) {
183 m_location = location;
184 handle.resume();
185 });
186 }
187 PlaybackLocation *await_resume() { return m_location; }
188
189 private:
190 CDRomDevice &m_device;
191 PlaybackLocation *m_location;
192 };
193
194 private:
195 struct ActionBase {
196 const char *name() const { return m_name; }
197
198 protected:
199 ActionBase(const char *const name) : m_name(name) {}
200 virtual ~ActionBase() = default;
201
202 virtual bool dataReady(const Response &response);
203 virtual bool complete(const Response &response);
204 virtual bool acknowledge(const Response &response);
205 virtual bool end(const Response &response);
206
207 void setCallback(eastl::function<void(bool)> &&callback);
208 void queueCallbackFromISR(bool success);
209 void setSuccess(bool success);
210 // This isn't really a great way to do this, but it's the best I can come up with
211 // that doesn't involve friending a bunch of classes.
212 PlaybackLocation *getPendingLocationPtr() const;
213 void queueGetLocationCallback(bool success = true);
214
215 friend class CDRomDevice;
216 CDRomDevice *m_device = nullptr;
217 const char *const m_name = nullptr;
218 };
219
220 public:
221 virtual ~CDRomDevice();
222
231 void prepare();
232
242 void reset(eastl::function<void(bool)> &&callback);
243 TaskQueue::Task scheduleReset();
244 bool resetBlocking(GPU &);
245 ResetAwaiter reset() { return {*this}; }
246
263 void readSectors(uint32_t sector, uint32_t count, void *buffer, eastl::function<void(bool)> &&callback) override;
265
275 void getTOCSize(unsigned *size, eastl::function<void(bool)> &&callback);
277 unsigned getTOCSizeBlocking(GPU &);
278 GetTOCSizeAwaiter getTOCSize() { return {*this}; }
279
297 void readTOC(MSF *toc, unsigned size, eastl::function<void(bool)> &&callback);
298 TaskQueue::Task scheduleReadTOC(MSF *toc, unsigned size);
299 bool readTOCBlocking(MSF *toc, unsigned size, GPU &);
300 ReadTOCAwaiter readTOC(MSF *toc, unsigned size) { return {*this, toc, size}; }
301
307 void mute(eastl::function<void(bool)> &&callback);
310 MuteAwaiter mute() { return MuteAwaiter(*this); }
311
317 void unmute(eastl::function<void(bool)> &&callback);
320 UnmuteAwaiter unmute() { return {*this}; }
321
345 void playCDDATrack(MSF start, eastl::function<void(bool)> &&callback);
346 void playCDDATrack(unsigned track, eastl::function<void(bool)> &&callback);
347 void playCDDADisc(MSF start, eastl::function<void(bool)> &&callback);
348 void playCDDADisc(unsigned track, eastl::function<void(bool)> &&callback);
349 void resumeCDDA(eastl::function<void(bool)> &&callback);
350
363 void pauseCDDA();
364
373 void stopCDDA();
374
388 void getPlaybackLocation(PlaybackLocation *location, eastl::function<void(PlaybackLocation *)> &&callback);
389 void getPlaybackLocation(eastl::function<void(PlaybackLocation *)> &&callback);
390 TaskQueue::Task scheduleGetPlaybackLocation(PlaybackLocation *location);
392
413 void setVolume(uint8_t leftToLeft, uint8_t rightToLeft, uint8_t leftToRight, uint8_t rightToRight);
414
425 template <Concepts::IsCDRomDeviceStateEnum S>
426 class Action : public ActionBase {
427 protected:
428 Action(const char *const name) : ActionBase(name) {}
429 void registerMe(CDRomDevice *device) {
430 device->switchAction(this);
431 m_device = device;
432 }
433
434 void setState(S state) { m_device->m_state = static_cast<uint8_t>(state); }
435 S getState() const { return static_cast<S>(m_device->m_state); }
436 };
437
442 [[nodiscard]] bool isIdle() const { return m_state == 0; }
443
444 private:
445 void switchAction(ActionBase *action);
446 void irq();
447 void actionComplete();
448
449 friend class ActionBase;
450
451 eastl::function<void(bool)> m_callback;
452 eastl::function<void(PlaybackLocation *)> m_locationCallback;
453 PlaybackLocation m_locationStorage;
454 PlaybackLocation *m_locationPtr = nullptr;
455 uint32_t m_event = 0;
456 ActionBase *m_action = nullptr;
457 uint8_t m_state = 0;
458 bool m_success = false;
459 bool m_blocking = false;
460 bool m_pendingGetLocation = false;
461
462 struct BlockingAction {
463 BlockingAction(CDRomDevice *, GPU &);
464 ~BlockingAction();
465
466 private:
467 CDRomDevice *m_device;
468 GPU &m_gpu;
469 };
470
471 struct MaskedIRQ {
472 MaskedIRQ();
473 ~MaskedIRQ();
474 };
475};
476
477} // namespace psyqo
The action base class for the internal state machine.
Definition cdrom-device.hh:426
Action(const char *const name)
Definition cdrom-device.hh:428
S getState() const
Definition cdrom-device.hh:435
void registerMe(CDRomDevice *device)
Definition cdrom-device.hh:429
void setState(S state)
Definition cdrom-device.hh:434
A specialization of the CDRom interface.
Definition cdrom-device.hh:79
void unmute(eastl::function< void(bool)> &&callback)
Unmutes the CD audio for both CDDA and CDXA.
Definition cdrom-device-muteunmute.cpp:98
void resumeCDDA(eastl::function< void(bool)> &&callback)
Definition cdrom-device-cdda.cpp:188
unsigned getTOCSizeBlocking(GPU &)
Definition cdrom-device-toc.cpp:78
void muteBlocking(GPU &)
GetTOCSizeAwaiter getTOCSize()
Definition cdrom-device.hh:278
bool readTOCBlocking(MSF *toc, unsigned size, GPU &)
Definition cdrom-device-toc.cpp:167
MuteAwaiter mute()
Definition cdrom-device.hh:310
TaskQueue::Task scheduleGetTOCSize(unsigned *size)
Definition cdrom-device-toc.cpp:73
TaskQueue::Task scheduleReset()
Definition cdrom-device-reset.cpp:77
ReadTOCAwaiter readTOC(MSF *toc, unsigned size)
Definition cdrom-device.hh:300
void setVolume(uint8_t leftToLeft, uint8_t rightToLeft, uint8_t leftToRight, uint8_t rightToRight)
Set the Volume of the CDDA audio.
Definition cdrom-device-cdda.cpp:270
void playCDDADisc(MSF start, eastl::function< void(bool)> &&callback)
Definition cdrom-device-cdda.cpp:183
bool isIdle() const
Checks if the CDROM device is in idle state.
Definition cdrom-device.hh:442
void mute(eastl::function< void(bool)> &&callback)
Mutes the CD audio for both CDDA and CDXA.
Definition cdrom-device-muteunmute.cpp:61
friend class ActionBase
Definition cdrom-device.hh:449
virtual ~CDRomDevice()
Definition cdrom-device.cpp:54
void reset(eastl::function< void(bool)> &&callback)
Resets the CDRom controller.
Definition cdrom-device-reset.cpp:72
TaskQueue::Task scheduleReadTOC(MSF *toc, unsigned size)
Definition cdrom-device-toc.cpp:154
void pauseCDDA()
Pauses CDDA playback.
Definition cdrom-device-cdda.cpp:193
TaskQueue::Task scheduleGetPlaybackLocation(PlaybackLocation *location)
Definition cdrom-device-cdda.cpp:250
bool resetBlocking(GPU &)
Definition cdrom-device-reset.cpp:81
void playCDDATrack(MSF start, eastl::function< void(bool)> &&callback)
Begins playing CDDA audio from a given starting point.
Definition cdrom-device-cdda.cpp:173
void readSectors(uint32_t sector, uint32_t count, void *buffer, eastl::function< void(bool)> &&callback) override
Reads sectors from the CDRom.
Definition cdrom-device-readsectors.cpp:125
TaskQueue::Task scheduleMute()
Definition cdrom-device-muteunmute.cpp:66
UnmuteAwaiter unmute()
Definition cdrom-device.hh:320
GetPlaybackLocationAwaiter getPlaybackLocation()
Definition cdrom-device.hh:391
void getTOCSize(unsigned *size, eastl::function< void(bool)> &&callback)
Gets the size of the Table of Contents from the CDRom. Note that while the blocking variant is availa...
Definition cdrom-device-toc.cpp:68
void prepare()
Prepares the CDRom subsystem.
Definition cdrom-device.cpp:38
void unmuteBlocking(GPU &)
TaskQueue::Task scheduleUnmute()
Definition cdrom-device-muteunmute.cpp:103
ResetAwaiter reset()
Definition cdrom-device.hh:245
eastl::fixed_vector< uint8_t, 16, false > Response
Definition cdrom-device.hh:81
bool readSectorsBlocking(uint32_t sector, uint32_t count, void *buffer, GPU &)
Definition cdrom-device-readsectors.cpp:131
void stopCDDA()
Stops CDDA playback.
Definition cdrom-device-cdda.cpp:207
void getPlaybackLocation(PlaybackLocation *location, eastl::function< void(PlaybackLocation *)> &&callback)
Get the Playback location of the CDDA audio.
Definition cdrom-device-cdda.cpp:235
void readTOC(MSF *toc, unsigned size, eastl::function< void(bool)> &&callback)
Reads the Table of Contents from the CDRom.
Definition cdrom-device-toc.cpp:149
The base CDRom class.
Definition cdrom.hh:46
The singleton GPU class.
Definition gpu.hh:88
The Task class.
Definition task.hh:140
Definition cdrom-device.hh:55
void * result
Definition memcpy.c:47
void queueCallbackFromISR(eastl::function< void()> &&lambda)
Queues a callback to be called from the main thead.
Definition kernel.cpp:382
Definition cdrom-loader.hh:39
static int size
Definition string.h:32
PlaybackLocation * await_resume()
Definition cdrom-device.hh:187
bool await_ready() const
Definition cdrom-device.hh:179
GetPlaybackLocationAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:178
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:181
Definition cdrom-device.hh:106
bool await_ready() const
Definition cdrom-device.hh:108
GetTOCSizeAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:107
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:110
unsigned await_resume()
Definition cdrom-device.hh:116
Definition cdrom-device.hh:143
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:147
bool await_resume()
Definition cdrom-device.hh:153
MuteAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:144
bool await_ready() const
Definition cdrom-device.hh:145
Definition cdrom-device.hh:82
MSF relative
Definition cdrom-device.hh:83
MSF absolute
Definition cdrom-device.hh:84
unsigned index
Definition cdrom-device.hh:86
unsigned track
Definition cdrom-device.hh:85
Definition cdrom-device.hh:124
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:128
bool await_ready() const
Definition cdrom-device.hh:126
bool await_resume()
Definition cdrom-device.hh:134
ReadTOCAwaiter(CDRomDevice &device, MSF *toc, unsigned size)
Definition cdrom-device.hh:125
Definition cdrom-device.hh:89
ResetAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:90
bool await_resume()
Definition cdrom-device.hh:99
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:93
bool await_ready() const
Definition cdrom-device.hh:91
Definition cdrom-device.hh:160
bool await_ready() const
Definition cdrom-device.hh:162
bool await_resume()
Definition cdrom-device.hh:170
UnmuteAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:161
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:164
Definition msf.hh:38
static void * buffer
Definition syscalls.h:230
static const void size_t count
Definition syscalls.h:145
static int sector
Definition syscalls.h:467
void void(ptr, size)
void uint32_t(classId, spec)