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
39#include "psyqo/cdrom.hh"
40#include "psyqo/msf.hh"
41#include "psyqo/task.hh"
42
43namespace psyqo {
44
45class GPU;
46
47namespace Concepts {
48
49template <typename T, typename = void>
50struct CDRomDeviceStateEnumHasIdle : std::false_type {};
51
52template <typename T>
53struct CDRomDeviceStateEnumHasIdle<T, std::enable_if_t<T::IDLE == T(0)>> : std::true_type {};
54
55template <typename T>
57 std::is_enum_v<T> && std::is_same_v<uint8_t, std::underlying_type_t<T>> && CDRomDeviceStateEnumHasIdle<T>::value;
58
59} // namespace Concepts
60
80class CDRomDevice final : public CDRom {
81 public:
82 typedef eastl::fixed_vector<uint8_t, 16, false> Response;
86 unsigned track;
87 unsigned index;
88 };
89
90 struct ResetAwaiter {
91 ResetAwaiter(CDRomDevice &device) : m_device(device) {}
92 bool await_ready() const { return false; }
93 template <typename U>
94 void await_suspend(std::coroutine_handle<U> handle) {
95 m_device.reset([handle, this](bool result) {
96 m_result = result;
97 handle.resume();
98 });
99 }
100 bool await_resume() { return m_result; }
101
102 private:
103 CDRomDevice &m_device;
104 bool m_result;
105 };
106
108 GetTOCSizeAwaiter(CDRomDevice &device) : m_device(device) {}
109 bool await_ready() const { return false; }
110 template <typename U>
111 void await_suspend(std::coroutine_handle<U> handle) {
112 m_device.getTOCSize(&m_result, [handle, this](bool success) {
113 m_success = success;
114 handle.resume();
115 });
116 }
117 unsigned await_resume() { return m_success ? m_result : 0; }
118
119 private:
120 CDRomDevice &m_device;
121 unsigned m_result;
122 bool m_success;
123 };
124
126 ReadTOCAwaiter(CDRomDevice &device, MSF *toc, unsigned size) : m_device(device), m_toc(toc), m_size(size) {}
127 bool await_ready() const { return false; }
128 template <typename U>
129 void await_suspend(std::coroutine_handle<U> handle) {
130 m_device.readTOC(m_toc, m_size, [handle, this](bool result) {
131 m_result = result;
132 handle.resume();
133 });
134 }
135 bool await_resume() { return m_result; }
136
137 private:
138 CDRomDevice &m_device;
139 MSF *m_toc;
140 unsigned m_size;
141 bool m_result;
142 };
143
144 struct MuteAwaiter {
145 MuteAwaiter(CDRomDevice &device) : m_device(device) {}
146 bool await_ready() const { return false; }
147 template <typename U>
148 void await_suspend(std::coroutine_handle<U> handle) {
149 m_device.mute([handle, this](bool result) {
150 m_result = result;
151 handle.resume();
152 });
153 }
154 bool await_resume() { return m_result; }
155
156 private:
157 CDRomDevice &m_device;
158 bool m_result;
159 };
160
162 UnmuteAwaiter(CDRomDevice &device) : m_device(device) {}
163 bool await_ready() const { return false; }
164 template <typename U>
165 void await_suspend(std::coroutine_handle<U> handle) {
166 m_device.unmute([handle, this](bool result) {
167 m_result = result;
168 handle.resume();
169 });
170 }
171 bool await_resume() { return m_result; }
172
173 private:
174 CDRomDevice &m_device;
175 bool m_result;
176 };
177
179 GetPlaybackLocationAwaiter(CDRomDevice &device) : m_device(device) {}
180 bool await_ready() const { return false; }
181 template <typename U>
182 void await_suspend(std::coroutine_handle<U> handle) {
183 m_device.getPlaybackLocation([handle, this](PlaybackLocation *location) {
184 m_location = location;
185 handle.resume();
186 });
187 }
188 PlaybackLocation *await_resume() { return m_location; }
189
190 private:
191 CDRomDevice &m_device;
192 PlaybackLocation *m_location;
193 };
194
195 private:
196 struct ActionBase {
197 const char *name() const { return m_name; }
198
199 protected:
200 ActionBase(const char *const name) : m_name(name) {}
201 virtual ~ActionBase() = default;
202
203 virtual bool dataReady(const Response &response);
204 virtual bool complete(const Response &response);
205 virtual bool acknowledge(const Response &response);
206 virtual bool end(const Response &response);
207
208 void setCallback(eastl::function<void(bool)> &&callback);
209 void queueCallbackFromISR(bool success);
210 void setSuccess(bool success);
211 // This isn't really a great way to do this, but it's the best I can come up with
212 // that doesn't involve friending a bunch of classes.
213 PlaybackLocation *getPendingLocationPtr() const;
214 void queueGetLocationCallback(bool success = true);
215
216 friend class CDRomDevice;
217 CDRomDevice *m_device = nullptr;
218 const char *const m_name = nullptr;
219 };
220
221 public:
222 virtual ~CDRomDevice();
223
232 void prepare();
233
243 void reset(eastl::function<void(bool)> &&callback);
244 TaskQueue::Task scheduleReset();
245 bool resetBlocking(GPU &);
246 ResetAwaiter reset() { return {*this}; }
247
264 void readSectors(uint32_t sector, uint32_t count, void *buffer, eastl::function<void(bool)> &&callback) override;
266
276 void getTOCSize(unsigned *size, eastl::function<void(bool)> &&callback);
278 unsigned getTOCSizeBlocking(GPU &);
279 GetTOCSizeAwaiter getTOCSize() { return {*this}; }
280
298 void readTOC(MSF *toc, unsigned size, eastl::function<void(bool)> &&callback);
299 TaskQueue::Task scheduleReadTOC(MSF *toc, unsigned size);
300 bool readTOCBlocking(MSF *toc, unsigned size, GPU &);
301 ReadTOCAwaiter readTOC(MSF *toc, unsigned size) { return {*this, toc, size}; }
302
308 void mute(eastl::function<void(bool)> &&callback);
311 MuteAwaiter mute() { return MuteAwaiter(*this); }
312
318 void unmute(eastl::function<void(bool)> &&callback);
321 UnmuteAwaiter unmute() { return {*this}; }
322
346 void playCDDATrack(MSF start, eastl::function<void(bool)> &&callback);
347 void playCDDATrack(unsigned track, eastl::function<void(bool)> &&callback);
348 void playCDDADisc(MSF start, eastl::function<void(bool)> &&callback);
349 void playCDDADisc(unsigned track, eastl::function<void(bool)> &&callback);
350 void resumeCDDA(eastl::function<void(bool)> &&callback);
351
364 void pauseCDDA();
365
374 void stopCDDA();
375
389 void getPlaybackLocation(PlaybackLocation *location, eastl::function<void(PlaybackLocation *)> &&callback);
390 void getPlaybackLocation(eastl::function<void(PlaybackLocation *)> &&callback);
391 TaskQueue::Task scheduleGetPlaybackLocation(PlaybackLocation *location);
393
414 void setVolume(uint8_t leftToLeft, uint8_t rightToLeft, uint8_t leftToRight, uint8_t rightToRight);
415
421 void test(const psyqo::Hardware::CDRom::CDRomCommandBuffer &commandBuffer, eastl::function<void(bool)> &&callback);
423 void testBlocking(GPU &, const psyqo::Hardware::CDRom::CDRomCommandBuffer &commandBuffer);
424
435 template <Concepts::IsCDRomDeviceStateEnum S>
436 class Action : public ActionBase {
437 protected:
438 Action(const char *const name) : ActionBase(name) {}
439 void registerMe(CDRomDevice *device) {
440 device->switchAction(this);
441 m_device = device;
442 }
443
444 void setState(S state) { m_device->m_state = static_cast<uint8_t>(state); }
445 S getState() const { return static_cast<S>(m_device->m_state); }
446 };
447
452 [[nodiscard]] bool isIdle() const { return m_state == 0; }
453
454 private:
455 void switchAction(ActionBase *action);
456 void irq();
457 void actionComplete();
458
459 friend class ActionBase;
460
461 eastl::function<void(bool)> m_callback;
462 eastl::function<void(PlaybackLocation *)> m_locationCallback;
463 PlaybackLocation m_locationStorage;
464 PlaybackLocation *m_locationPtr = nullptr;
465 uint32_t m_event = 0;
466 ActionBase *m_action = nullptr;
467 uint8_t m_state = 0;
468 bool m_success = false;
469 bool m_blocking = false;
470 bool m_pendingGetLocation = false;
471
472 struct BlockingAction {
473 BlockingAction(CDRomDevice *, GPU &);
474 ~BlockingAction();
475
476 private:
477 CDRomDevice *m_device;
478 GPU &m_gpu;
479 };
480
481 struct MaskedIRQ {
482 MaskedIRQ();
483 ~MaskedIRQ();
484 };
485};
486
487} // namespace psyqo
The action base class for the internal state machine.
Definition cdrom-device.hh:436
Action(const char *const name)
Definition cdrom-device.hh:438
S getState() const
Definition cdrom-device.hh:445
void registerMe(CDRomDevice *device)
Definition cdrom-device.hh:439
void setState(S state)
Definition cdrom-device.hh:444
A specialization of the CDRom interface.
Definition cdrom-device.hh:80
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:279
bool readTOCBlocking(MSF *toc, unsigned size, GPU &)
Definition cdrom-device-toc.cpp:167
MuteAwaiter mute()
Definition cdrom-device.hh:311
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:301
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:452
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:459
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 test(const psyqo::Hardware::CDRom::CDRomCommandBuffer &commandBuffer, eastl::function< void(bool)> &&callback)
Sends a test command to the CDRom mech.
Definition cdrom-device-test.cpp:74
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:321
GetPlaybackLocationAwaiter getPlaybackLocation()
Definition cdrom-device.hh:392
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
TaskQueue::Task scheduleTest(const psyqo::Hardware::CDRom::CDRomCommandBuffer &commandBuffer)
Definition cdrom-device-test.cpp:80
void testBlocking(GPU &, const psyqo::Hardware::CDRom::CDRomCommandBuffer &commandBuffer)
Definition cdrom-device-test.cpp:88
void unmuteBlocking(GPU &)
TaskQueue::Task scheduleUnmute()
Definition cdrom-device-muteunmute.cpp:103
ResetAwaiter reset()
Definition cdrom-device.hh:246
eastl::fixed_vector< uint8_t, 16, false > Response
Definition cdrom-device.hh:82
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:56
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:401
Definition lua.hh:38
static int size
Definition string.h:32
PlaybackLocation * await_resume()
Definition cdrom-device.hh:188
bool await_ready() const
Definition cdrom-device.hh:180
GetPlaybackLocationAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:179
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:182
Definition cdrom-device.hh:107
bool await_ready() const
Definition cdrom-device.hh:109
GetTOCSizeAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:108
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:111
unsigned await_resume()
Definition cdrom-device.hh:117
Definition cdrom-device.hh:144
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:148
bool await_resume()
Definition cdrom-device.hh:154
MuteAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:145
bool await_ready() const
Definition cdrom-device.hh:146
Definition cdrom-device.hh:83
MSF relative
Definition cdrom-device.hh:84
MSF absolute
Definition cdrom-device.hh:85
unsigned index
Definition cdrom-device.hh:87
unsigned track
Definition cdrom-device.hh:86
Definition cdrom-device.hh:125
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:129
bool await_ready() const
Definition cdrom-device.hh:127
bool await_resume()
Definition cdrom-device.hh:135
ReadTOCAwaiter(CDRomDevice &device, MSF *toc, unsigned size)
Definition cdrom-device.hh:126
Definition cdrom-device.hh:90
ResetAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:91
bool await_resume()
Definition cdrom-device.hh:100
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:94
bool await_ready() const
Definition cdrom-device.hh:92
Definition cdrom-device.hh:161
bool await_ready() const
Definition cdrom-device.hh:163
bool await_resume()
Definition cdrom-device.hh:171
UnmuteAwaiter(CDRomDevice &device)
Definition cdrom-device.hh:162
void await_suspend(std::coroutine_handle< U > handle)
Definition cdrom-device.hh:165
Definition cdrom-commandbuffer.hh:39
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)