OSDN Git Service

[VM][FMTOWNS][CDROM] CDROM checks DMAC's mask as running DMAC CH.3.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / cdrom / cdrom.cpp
1 /*
2         FUJITSU FM Towns Emulator 'eFMTowns'
3
4         Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2019.01.31 -
6
7         [FM-Towns CD-ROM based on SCSI CDROM]
8 */
9
10 /*
11  * Note: Re-Write CD-ROM from SCSI_CDROM, but not related from SCSI_DEV.
12  * -- 20200411 K.O
13  */
14 #include "../cdrom.h"
15 #include "../dmac.h"
16 #include "../../../fifo.h"
17 #include "../../../ringbuffer.h"
18 #include "../../../fileio.h"
19 #include "../../debugger.h"
20 #include "../../types/util_sound.h"
21
22 //#include <iostream>
23 //#include <utility>
24
25 // SAME AS SCSI_CDROM::
26 #define CDDA_OFF                0
27 #define CDDA_PLAYING    1
28 #define CDDA_PAUSED             2
29 #define CDDA_ENDED              3
30
31 // 0-99 is reserved for SCSI_DEV class
32 #define EVENT_CDDA                                                      100
33 #define EVENT_CDDA_DELAY_PLAY                           101
34 #define EVENT_CDROM_SEEK                                        102
35 #define EVENT_CDROM_DELAY_INTERRUPT_ON          103
36 #define EVENT_CDROM_DELAY_INTERRUPT_OFF         104
37 #define EVENT_CDDA_DELAY_STOP                           105
38 #define EVENT_CDROM_READY_TO_READ                       106
39 #define EVENT_CDROM_DRQ                                         107
40 #define EVENT_CDROM_NEXT_SECTOR                         108
41 #define EVENT_CDROM_DELAY_READY                         109
42 #define EVENT_CDROM_DELAY_NOT_READY                     110
43
44 #define EVENT_CDROM_DELAY_START_DRQ                     111
45 #define EVENT_CDROM_DELAY_EOT_PIO                       112
46
47 #define EVENT_CDROM_RESTORE                                     113
48 #define EVENT_CDROM_WAIT                                        114
49 #define EVENT_CDROM_TIMEOUT                                     115
50 #define EVENT_CDROM_READY_EOT                           116
51 #define EVENT_CDROM_READY_CDDAREPLY                     117
52 #define EVENT_CDROM_CDDA_PLAY_STATUS            118
53 #define EVENT_CDDA_REPEAT                                       119
54 #define EVENT_CDROM_READ_PRE_SEEK                       120
55
56 #define EVENT_CDROM_DELAY_COMMAND                       128
57 #define EVENT_CDROM_DELAY_READY_FORCEINT        129
58 #define EVENT_CDROM_DELAY_NOT_READY_FORCEINT    130
59 #define EVENT_CDROM_READY_EOT_FORCEINT          136
60
61 //#define _CDROM_DEBUG_LOG
62 namespace FMTOWNS {
63
64 // crc table from vm/disk.cpp
65 const uint16_t TOWNS_CDROM::crc_table[256] = {
66         0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
67         0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
68         0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
69         0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
70         0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
71         0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
72         0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
73         0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
74         0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
75         0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
76         0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
77         0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
78         0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
79         0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
80         0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
81         0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
82 };
83
84
85 uint16_t TOWNS_CDROM::calc_subc_crc16(uint8_t *databuf, int bytes, uint16_t initval)
86 {
87         uint16_t crc16 = initval;
88         for(int i = 0; i < bytes ; i++) {
89                 crc16 = (uint16_t)((crc16 << 8) ^ crc_table[(uint8_t)(crc16 >> 8) ^ databuf[i]]);
90         }
91         return crc16;
92 }
93
94 void TOWNS_CDROM::cdrom_debug_log(const char *fmt, ...)
95 {
96                 char strbuf[4096];
97                 va_list ap;
98                 va_start(ap, fmt);
99                 vsnprintf(strbuf, 4095, fmt, ap);
100                 out_debug_log_with_switch(((__CDROM_DEBUG_LOG) || (force_logging)),
101                                                                   "%s",
102                                                                   strbuf);
103                 va_end(ap);
104 }
105
106 void TOWNS_CDROM::initialize()
107 {
108         DEVICE::initialize();
109         __CDROM_DEBUG_LOG = osd->check_feature(_T("_CDROM_DEBUG_LOG"));
110         __CDROM_DEBUG_LOG = true;
111         _USE_CDROM_PREFETCH = osd->check_feature(_T("USE_CDROM_PREFETCH"));
112         force_logging = false;
113
114         subq_overrun = false;
115         memset(subq_bytes, 0x00, sizeof(subq_bytes));
116         memset(subq_snapshot, 0x00, sizeof(subq_snapshot));
117         memset(subq_buffer, 0x00, sizeof(subq_buffer));
118
119         stat_track = 0;
120         track_num = 0;
121         //status_queue = new FIFO(4 * (6 + 100 + 2)); // With PAD
122         status_queue = new FIFO(4); // With PAD
123         param_queue = new RINGBUFFER(8);
124         // ToDo: MasterDevice::initialize()
125         fio_img = new FILEIO();
126
127         memset(img_file_path_bak, 0x00, sizeof(img_file_path_bak));
128         media_changed = false;
129         media_ejected = false;
130
131         //if(44100 % emu->get_sound_rate() == 0) {
132         //      mix_loop_num = 44100 / emu->get_sound_rate();
133         //} else {
134                 mix_loop_num = 0;
135         //}
136         event_execute = -1;
137         event_cdda = -1;
138         event_cdda_delay_play = -1;
139         event_delay_interrupt = -1;
140         event_drq = -1;
141
142         event_next_sector = -1;
143         event_seek = -1;
144         event_delay_ready = -1;
145         event_cdda_delay_stop = -1;
146         event_time_out = -1;
147         event_eot = -1;
148
149         // ToDo: larger buffer for later VMs.
150         max_fifo_length = ((machine_id == 0x0700) || (machine_id >= 0x0900)) ? 65536 : 8192;
151         fifo_length = 8192;
152 //      fifo_length = 65536;
153         databuffer = new FIFO(max_fifo_length);
154
155         cdda_status = CDDA_OFF;
156         is_cue = false;
157         is_iso = false;
158         current_track = 0;
159         read_sector = 0;
160
161         transfer_speed = 1;
162         for(int i = 0; i < 99; i++) {
163                 memset(track_data_path[i], 0x00, _MAX_PATH * sizeof(_TCHAR));
164         }
165         /*!
166           @note values related muting/voluming are set by electric volume,
167                 not inside of CD-ROM DRIVE.
168         */
169         _decibel_l = 0;
170         _decibel_r = 0;
171         mute_left = false;
172         mute_right = false;
173
174         memset(w_regs, 0x00, sizeof(w_regs));
175 }
176
177 void TOWNS_CDROM::release()
178 {
179         if(fio_img != NULL) {
180                 if(fio_img->IsOpened()) {
181                         fio_img->Fclose();
182                 }
183                 fio_img = NULL;
184                 delete fio_img;
185         }
186         if(databuffer != NULL) {
187                 databuffer->release();
188                 delete databuffer;
189                 databuffer = NULL;
190         }
191         if(status_queue != NULL) {
192                 status_queue->release();
193                 delete status_queue;
194                 status_queue = NULL;
195         }
196         if(param_queue != NULL) {
197                 param_queue->release();
198                 delete param_queue;
199                 param_queue = NULL;
200         }
201
202 }
203
204 void TOWNS_CDROM::reset()
205 {
206         cdrom_debug_log("RESET");
207         w_regs[0] = 0x00;
208
209         reset_device();
210         // Interrupt masks must set after device reset : From Tsugaru.
211         mcu_intr_mask = false;
212         dma_intr_mask = false;
213         write_mcuint_signals(false);
214         // Q: Does not seek to track 0? 20181118 K.O
215 }
216
217 void TOWNS_CDROM::reset_device()
218 {
219         uint8_t reg4c0 = w_regs[0];
220         memset(w_regs, 0x00, sizeof(w_regs));
221         w_regs[0] = reg4c0;
222
223         touch_sound();
224         clear_event(this, event_execute);
225         clear_event(this, event_cdda);
226         clear_event(this, event_cdda_delay_play);
227         clear_event(this, event_cdda_delay_stop);
228         clear_event(this, event_delay_interrupt);
229         clear_event(this, event_next_sector);
230
231         clear_event(this, event_seek);
232         clear_event(this, event_delay_ready);
233         clear_event(this, event_time_out);
234         clear_event(this, event_eot);
235         clear_event(this, event_drq);
236
237         // Around internal variables.
238 //      if(44100 % emu->get_sound_rate() == 0) {
239 //              mix_loop_num = 44100 / emu->get_sound_rate();
240 //      } else {
241                 mix_loop_num = 0;
242 //      }
243
244         access = false;
245         cdda_stopped = true;
246         cdda_status = CDDA_OFF;
247         cdda_repeat_count = -1;
248
249         cdda_start_frame = 0;
250         cdda_end_frame = 150;
251         cdda_playing_frame = 0;
252         cdda_buffer_ptr = 0;
253
254         status_seek = false;
255         media_changed = false;
256         media_ejected = false;
257         cdrom_prefetch = false;
258
259         next_seek_lba = 0;
260         read_length = 0;
261         current_track = 0;
262         read_sector = 0;
263
264         if(mounted()) {
265                 get_track_by_track_num(0); // HEAD OF track 1
266         }
267         stat_track = current_track;
268         // Note: Reorder sequence.
269         // 20220127 K.O
270         // Around Register 4C0h:R
271         mcu_intr = false;
272         dma_intr = false;
273         mcu_ready = true;
274         has_status = false;
275         command_execute_phase = false;
276
277         // Around Register 4C2h:R
278         status_queue->clear();
279         extra_status = 0;
280
281         // Around Register 4C2h:W
282         command_received = false;
283
284         stat_reply_intr = false;
285         req_status = false;
286
287         // Around Register 4C4h:R
288         databuffer->clear();
289         data_reg.w = 0x0000;
290
291         // Around Register 4C4h:W
292         reserved_command = 0x00;
293         param_queue->clear();
294
295         latest_command = 0x00;
296         memset(exec_params, 0x00, sizeof(exec_params));
297         prev_command = 0x00;
298         memset(prev_params, 0x00, sizeof(prev_params));
299
300         // Around Register 4C6h:W
301         dma_transfer = false;
302         pio_transfer = false;
303         dma_transfer_phase = false;
304         pio_transfer_phase = false;
305
306         // Around Register 4CCh:R and 4CDh:R
307         subq_bitptr = 0;
308         subq_bitwidth = 96;
309         subq_overrun = false;
310         set_subq(0);
311         memcpy(subq_snapshot, subq_bytes, sizeof(subq_snapshot));
312
313         if(d_dmac != NULL) {
314                 dmac_running = (d_dmac->read_signal(SIG_TOWNS_DMAC_MASK_CH3) != 0) ? true : false;
315         } else {
316                 dmac_running = false;
317         }
318         // Maybe not need to reset interrupt from I/O 04C0h:bit7 .
319 //      write_mcuint_signals(false);
320         // Will Implement
321 }
322
323 void TOWNS_CDROM::set_dma_intr(bool val)
324 {
325 //      cdrom_debug_log(_T("set_dma_intr(%s) MASK=%s stat_reply_intr = %s"),
326 //                                (val) ? _T("true ") : _T("false"),
327 //                                (dma_intr_mask) ? _T("ON ") : _T("OFF"),
328 //                                (stat_reply_intr) ? _T("ON ") : _T("OFF"));
329         // At least, DMA interrupt mask is needed (by TownsOS v.1.1) 20200511 K.O
330         if(!(dma_intr_mask) /*&& (val)*/) { // âˆ‘(゚Д゚)!! from Tsugaru 20231001
331                 write_mcuint_signals(true);
332         }
333         // Interrupt flag may set after interrupt happened ?? (;´Д`) From Tsugaru.
334         dma_intr = val;
335 }
336
337
338 void TOWNS_CDROM::set_mcu_intr(bool val)
339 {
340 //      cdrom_debug_log(_T("set_mcu_intr(%s) MASK=%s stat_reply_intr = %s"),
341 //                                (val) ? _T("true ") : _T("false"),
342 //                                (mcu_intr_mask) ? _T("ON ") : _T("OFF"),
343 //                                (stat_reply_intr) ? _T("ON ") : _T("OFF"));
344         if(!(mcu_intr_mask) /*&& (val)*/) { // âˆ‘(゚Д゚)!! from Tsugaru 20231001
345                 write_mcuint_signals(true);
346         }
347         mcu_intr = val;
348 }
349
350
351 void TOWNS_CDROM::start_time_out()
352 {
353         stop_time_out();
354         // TIMEOUT = 1000msec = 1sec.
355         if(event_time_out < 0) {
356                 register_event(this, EVENT_CDROM_TIMEOUT, 100.0e3, false, &event_time_out);
357         }
358 }
359
360 void TOWNS_CDROM::stop_time_out()
361 {
362         clear_event(this, event_time_out);
363 }
364
365 void TOWNS_CDROM::do_drq()
366 {
367         // Note: EMULATE NONE BUFFER. 20230531 K.O
368         if((dma_transfer_phase) && (dma_transfer)) {
369                 __LIKELY_IF(!(databuffer->empty())) {
370                         __LIKELY_IF(dmac_running) {
371                                 write_signals(&outputs_drq, 0xffffffff);
372                         }
373                 } else {
374                         if(read_length <= 0) {
375                                 dma_transfer_epilogue();  // Remove Duplicate calling.
376                         }
377                 }
378         }
379 }
380
381 void TOWNS_CDROM::stop_drq()
382 {
383         clear_event(this, event_drq);
384 }
385
386 void TOWNS_CDROM::start_drq(const double usec)
387 {
388         if(d_dmac != NULL) {
389                 dmac_running = (d_dmac->read_signal(SIG_TOWNS_DMAC_MASK_CH3) != 0) ? true : false;
390         } else {
391                 dmac_running = false;
392         }
393         if(event_drq < 0) {
394                 register_event(this, EVENT_CDROM_DELAY_START_DRQ,
395                                            usec,
396                                            true, &event_drq);
397         }
398 }
399
400 void TOWNS_CDROM::clear_status_queue(const bool is_clear_extra)
401 {
402         has_status = false;
403         if(is_clear_extra) {
404                 extra_status = 0;
405         }
406         __UNLIKELY_IF(status_queue == NULL) {
407                 return;
408         }
409         status_queue->clear();
410 }
411
412 void TOWNS_CDROM::push_status_queue(uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3)
413 {
414         __UNLIKELY_IF(status_queue == NULL) {
415                 has_status = false;
416                 return;
417         }
418         status_queue->write(s0);
419         status_queue->write(s1);
420         status_queue->write(s2);
421         status_queue->write(s3);
422         has_status = true;
423 }
424
425 void TOWNS_CDROM::write_signal(int id, uint32_t data, uint32_t mask)
426 {
427         bool _b = ((data & mask) != 0);
428
429         switch(id) {
430         case SIG_TOWNS_CDROM_CDDA_STOP:
431                 if(cdda_status != CDDA_OFF) {
432                         if(_b) set_cdda_status(CDDA_OFF);
433                 }
434                 break;
435         case SIG_TOWNS_CDROM_CDDA_PLAY:
436                 if(cdda_status != CDDA_PLAYING) {
437                         if(_b) set_cdda_status(CDDA_PLAYING);
438                 }
439                 break;
440         case SIG_TOWNS_CDROM_CDDA_PAUSE:
441                 if(cdda_status != CDDA_PAUSED) {
442                         if(_b) set_cdda_status(CDDA_PAUSED);
443                 }
444                 break;
445         case SIG_TOWNS_CDROM_SET_TRACK:
446                 if(((data < 100) && (data >= 0)) || (data == 0xaa)) {
447                         stat_track = data;
448                 }
449                 break;
450         case SIG_TOWNS_CDROM_RESET:
451                 if((data & mask) != 0) {
452                         reset();
453                 }
454                 break;
455         case SIG_TOWNS_CDROM_MUTE_L:
456                 mute_left = ((data & mask) != 0) ? true : false;
457                 break;
458         case SIG_TOWNS_CDROM_MUTE_R:
459                 mute_right = ((data & mask) != 0) ? true : false;
460                 break;
461         case SIG_TOWNS_CDROM_MUTE_ALL:
462                 mute_left = ((data & mask) != 0) ? true : false;
463                 mute_right = mute_left;
464                 break;
465                 // By DMA/TC, EOT.This means ABORTing request from EXTERNAL BUS.
466         case SIG_TOWNS_CDROM_DMAINT:
467                 if((data & mask) != 0) {
468                         // This seems to be aborting to transfer?
469                         if(dma_transfer_phase) {
470                                 //if(databuffer->empty()) {
471                                         dma_transfer_epilogue();
472                                         // ToDo: Abort Sequence.
473                                 //}
474                         }
475                 }
476                 break;
477         case SIG_TOWNS_CDROM_DMAMASK:
478                 dmac_running = ((data & mask) != 0) ? true : false;
479                 break;
480         default:
481                 // ToDo: Implement master devices.
482                 break;
483         }
484
485 }
486
487 bool TOWNS_CDROM::status_media_changed_or_not_ready(const bool force_interrupt)
488 {
489         if(status_not_ready(force_interrupt)) {
490                 media_changed = false;
491                 return true;
492         }
493         if(status_media_changed(force_interrupt)) {
494                 return true;
495         }
496         return false;
497 }
498
499 bool TOWNS_CDROM::status_not_ready(const bool force_interrupt)
500 {
501         bool _b = (mounted()) ? false : true;
502         if(_b) {
503                 cdrom_debug_log(_T("CMD (%02X) BUT DISC NOT ACTIVE"), latest_command);
504                 command_execute_phase = false;
505                 set_status_immediate(req_status, force_interrupt, 0,
506                                    TOWNS_CD_STATUS_CMD_ABEND, TOWNS_CD_ABEND_DRIVE_NOT_READY, 0, 0);
507         }
508         return _b;
509 }
510
511 bool TOWNS_CDROM::status_media_changed(const bool force_interrupt)
512 {
513         bool _b = media_changed;
514         media_changed = false;
515         if(_b) {
516                 command_execute_phase = false;
517                 set_status_immediate(req_status, force_interrupt, 0,
518                                    TOWNS_CD_STATUS_CMD_ABEND, TOWNS_CD_ABEND_MEDIA_CHANGED, 0, 0);
519         }
520         return _b;
521 }
522
523 void TOWNS_CDROM::status_hardware_error(const bool force_interrupt)
524 {
525         command_execute_phase = false; // OK?
526         set_status_immediate(req_status, force_interrupt, 0,
527                            TOWNS_CD_STATUS_CMD_ABEND, TOWNS_CD_ABEND_HARDWARE_ERROR_04, 0, 0);
528 }
529
530 void TOWNS_CDROM::status_parameter_error(const bool force_interrupt)
531 {
532         command_execute_phase = false;
533         set_status_immediate(req_status, force_interrupt, 0,
534                            TOWNS_CD_STATUS_CMD_ABEND, TOWNS_CD_ABEND_PARAMETER_ERROR, 0, 0);
535 }
536
537 void TOWNS_CDROM::status_time_out(const bool force_interrupt)
538 {
539         status_seek = false;
540         //clear_event(this, event_execute); // OK?
541         //clear_event(this, event_cdda); // OK?
542         clear_event(this, event_cdda_delay_play);
543         clear_event(this, event_cdda_delay_stop);
544         //clear_event(this, event_delay_interrupt); // OK?
545         clear_event(this, event_next_sector);
546
547         clear_event(this, event_seek);
548         clear_event(this, event_delay_ready); // OK?
549         clear_event(this, event_eot);
550         //clear_event(this, event_time_out);
551         command_execute_phase = false;
552
553         set_status_immediate(true, force_interrupt, 0, TOWNS_CD_STATUS_CMD_ABEND, TOWNS_CD_ABEND_RETRY, 0x00, 0x00);
554         // Backport from Tsugaru, 2023-10-01
555         dma_intr = false;
556         dma_transfer_phase = false;
557         pio_transfer_phase = false;
558         mcu_ready = true;
559 }
560
561 void TOWNS_CDROM::status_read_done(const bool force_interrupt)
562 {
563         mcu_ready = true;
564         clear_status_queue(true);
565         command_execute_phase = false;
566         push_status_queue(TOWNS_CD_STATUS_READ_DONE, 0x00, 0x00, 0x00);
567         if(req_status) {
568                 mcu_intr = true;
569                 bool i_enabled = (!(mcu_intr_mask) || (force_interrupt)) ? true : false;
570                 if((stat_reply_intr) && (i_enabled)) { // Without MASK.
571                         write_mcuint_signals(true);
572                 }
573         } else {
574                 mcu_intr = false;
575         }
576 }
577
578 void TOWNS_CDROM::status_data_ready(const bool force_interrupt)
579 {
580         clear_status_queue(true);
581 //      if(req_status) {
582         push_status_queue(TOWNS_CD_STATUS_DATA_DMA, 0x00, 0x00, 0x00);
583
584         if(req_status) {
585                 bool i_enabled = (!(mcu_intr_mask) || (force_interrupt)) ? true : false;
586                 if((stat_reply_intr) && (i_enabled)) { // Without MASK.
587                         write_mcuint_signals(true);
588                 }
589                 mcu_intr = true;
590         } else {
591                 mcu_intr = false;
592         }
593         dma_intr = false;
594 }
595
596 void TOWNS_CDROM::status_illegal_lba(int extra, uint8_t s1, uint8_t s2, uint8_t s3)
597 {
598         cdrom_debug_log(_T("Error on reading (ILLGLBLKADDR): EXTRA=%d s1=%02X s2=%02X s3=%02X LBA=%d\n"), extra, s1, s2, s3, read_sector);
599         command_execute_phase = false;
600         set_status(req_status, extra, TOWNS_CD_STATUS_CMD_ABEND, s1, s2, s3, false);
601 }
602
603 void TOWNS_CDROM::status_accept(int extra, uint8_t s2, uint8_t s3, bool immediate_interrupt, const bool force_interrupt)
604 {
605         if(immediate_interrupt) {
606                 status_accept2(force_interrupt, extra, s2, s3);
607         } else {
608                 status_accept3(extra, s2, s3);
609                 set_delay_ready(force_interrupt);
610         }
611 }
612
613
614 void TOWNS_CDROM::status_accept2(const bool force_interrupt, int extra, uint8_t s2, uint8_t s3)
615 {
616         status_accept3(extra, s2, s3);
617         if(req_status) {
618                 bool i_enabled = (!(mcu_intr_mask) || (force_interrupt)) ? true : false;
619                 if((stat_reply_intr) && (i_enabled)) { // Without MASK.
620                         write_mcuint_signals(true);
621                         mcu_intr = true;
622                 }
623         }
624 }
625
626 void TOWNS_CDROM::status_accept3(int extra, uint8_t s2, uint8_t s3)
627 {
628         // Note: 2020-05-29 K.O
629         // Second byte (ARG s1) may below value (Thanks to Soji Yamakawa-San).
630         // 00h : NOT PLAYING CDDA
631         // 01h : DATA TRACK? (from Towns Linux)
632         // 03h : PLAYING CDDA
633         // 09h : MEDIA CHANGED? (from Towns Linux)
634         // 0Dh : After STOPPING CD-DA.Will clear.
635         // 01h and 09h maybe incorrect.
636
637         //uint8_t playcode = TOWNS_CD_ACCEPT_DATA_TRACK; // OK?
638         uint8_t playcode = TOWNS_CD_ACCEPT_NOERROR; // OK?
639         if(cdda_status == CDDA_PAUSED) {
640                 playcode = TOWNS_CD_ACCEPT_CDDA_PAUSED;
641         } else if(cdda_status == CDDA_PLAYING) {
642                 playcode = TOWNS_CD_ACCEPT_CDDA_PLAYING;
643         } else {
644                 #if 0 // TRY 20230530 K.O
645                 if(((latest_command & 0xb0) == 0xa0) ||
646                    ((prev_command & 0xb0) == 0xa0)) {
647                         switch(exec_params[0]) {
648                         case 0x04:
649                                 playcode = TOWNS_CD_ACCEPT_04H_FOR_CMD_A0H;
650                                 break;
651                         case 0x08:
652                                 playcode = TOWNS_CD_ACCEPT_08H_FOR_CMD_A0H;
653                                 //playcode = TOWNS_CD_ACCEPT_NOERROR;
654                                 break;
655                         }
656                 }
657                 #endif
658         }
659         clear_status_queue(true);
660         if(req_status) {
661                 if(extra >= 0) {
662                         extra_status = extra;
663                 }
664                 push_status_queue(TOWNS_CD_STATUS_ACCEPT, playcode, s2, s3);
665         }
666 }
667
668
669 void TOWNS_CDROM::send_mcu_ready()
670 {
671         mcu_ready = true;
672         if(stat_reply_intr) {
673                 set_mcu_intr(true);
674         }
675 }
676
677 void TOWNS_CDROM::set_delay_ready(const bool force_interrupt)
678 {
679         // From Towns Linux 2.2
680         // But, some software (i.e. Star Cruiser II) failes to loading at 300uS.
681         // May need *at least* 1000uS. - 20200517 K.O
682         int evnum = (force_interrupt) ? EVENT_CDROM_DELAY_READY_FORCEINT : EVENT_CDROM_DELAY_READY;
683         force_register_event(this, evnum, 1000.0, false, event_delay_ready);
684 }
685
686
687 void TOWNS_CDROM::set_delay_ready_eot(const bool force_interrupt)
688 {
689         int evnum = (force_interrupt) ? EVENT_CDROM_READY_EOT_FORCEINT : EVENT_CDROM_READY_EOT;
690         force_register_event(this, evnum, 1000.0, false, event_delay_ready);
691 }
692
693 void TOWNS_CDROM::status_not_accept(int extra, uint8_t s1, uint8_t s2, uint8_t s3, bool immediate_interrupt, const bool force_interrupt)
694 {
695         clear_status_queue(true);
696         if(req_status) {
697                 if(extra >= 0) {
698                         extra_status = extra;
699                 }
700                 push_status_queue(TOWNS_CD_STATUS_NOT_ACCEPT, s1, s2, s3);
701         }
702         command_execute_phase = false;
703
704         if(immediate_interrupt) {
705                 if(req_status) {
706                         bool i_enabled = (!(mcu_intr_mask) || (force_interrupt)) ? true : false;
707                         if((stat_reply_intr) && (i_enabled)) { // Without MASK.
708                                 write_mcuint_signals(true);
709                                 mcu_intr = true;
710                         }
711                 }
712         } else {
713                 set_delay_ready(force_interrupt);
714         }
715 }
716
717 const _TCHAR* TOWNS_CDROM::get_cdda_status_name(int _status)
718 {
719         const _TCHAR *playstatus = _T("UNKNOWN");
720         switch(_status) {
721         case CDDA_OFF:
722                 playstatus = _T("OFF    ");
723                 break;
724         case CDDA_PLAYING:
725                 playstatus = _T("PLAY   ");
726                 break;
727         case CDDA_PAUSED:
728                 playstatus = _T("PAUSE  ");
729                 break;
730         case CDDA_ENDED:
731                 playstatus = _T("ENDED  ");
732                 break;
733         }
734         return playstatus;
735 }
736
737 const _TCHAR* TOWNS_CDROM::get_command_name_from_command(uint8_t cmd)
738 {
739         const _TCHAR *cmdname = _T("UNKNOWN");
740         switch(cmd & 0x9f) {
741         case CDROM_COMMAND_SEEK: // 00h
742                 cmdname = _T("CDROM SEEK/RESTORE");
743                 break;
744         case CDROM_COMMAND_READ_MODE2: // 01h
745                 cmdname = _T("CDROM READ MODE2");
746                 break;
747         case CDROM_COMMAND_READ_MODE1: // 02h
748                 cmdname = _T("CDROM READ MODE1");
749                 break;
750         case CDROM_COMMAND_READ_RAW: // 03h
751                 cmdname = _T("CDROM READ RAW");
752                 break;
753         case CDROM_COMMAND_PLAY_TRACK: // 04h
754                 cmdname = _T("CDROM PLAY TRACK");
755                 break;
756         case CDROM_COMMAND_READ_TOC: // 05h
757                 cmdname = _T("CDROM READ TOC");
758                 break;
759         case CDROM_COMMAND_READ_CDDA_STATE: // 06h
760                 cmdname = _T("CDROM READ CDDA STATE (SUBQ)");
761                 break;
762         case CDROM_COMMAND_1F:
763                 cmdname = _T("CDROM UNKNOWN CMD 1Fh");
764                 break;
765         case CDROM_COMMAND_SET_STATE: // 80h
766                 cmdname = _T("CDROM SET STATE");
767                 break;
768         case CDROM_COMMAND_SET_CDDASET: // 81h
769                 cmdname = _T("CDROM SET CDDA STATUS");
770                 break;
771         case CDROM_COMMAND_STOP_CDDA: // 84h
772                 cmdname = _T("CDROM STOP CDDA");
773                 break;
774         case CDROM_COMMAND_PAUSE_CDDA: // 85h
775                 cmdname = _T("CDROM PAUSE CDDA");
776                 break;
777         case CDROM_COMMAND_RESUME_CDDA: // 87h
778                 cmdname = _T("CDROM RESUME CDDA");
779                 break;
780         }
781         return cmdname;
782 }
783 /*!
784  * @brief Execute CD-ROM command.
785  * @arg command  CD-ROM command.
786  * @note structure of comman is below:
787  * @note Bit7 and Bit4-0 : command code
788  * @note Bit6            : Interrupt on status at '1'
789  * @note Bit5            : Require status (must read from queue)..
790  */
791 void TOWNS_CDROM::execute_command(uint8_t command)
792 {
793         stat_reply_intr = ((command & 0x40) != 0) ? true : false;
794         req_status              = ((command & 0x20) != 0) ? true : false;
795         latest_command = command;
796         #if 1
797         for(int i = 0; i < 8; i++) {
798                 exec_params[i] = param_queue->read();
799         }
800         param_queue->clear();
801         #endif
802         extra_status = 0;
803         //command_received = false;
804
805 //      if(!(is_device_ready()) && ((command & 0xb0) != 0xa0)) { // From MAME 0.254 20230530 K.O
806 //              command_execute_phase = false;
807 //              set_status(req_status, 0, TOWNS_CD_STATUS_DISC_NOT_READY, 0, 0, 0, false);
808 //              stop_time_out();
809 //              return;
810 //      }
811
812         switch(command & 0x9f) {
813         case CDROM_COMMAND_SEEK: // 00h (RESTORE?)
814                 {
815 //                      set_cdda_status(CDDA_OFF);
816                         uint8_t m, s, f;
817                         m = FROM_BCD(exec_params[0]);
818                         s = FROM_BCD(exec_params[1]);
819                         f = FROM_BCD(exec_params[2]);
820                         int32_t lba = ((m * (60 * 75)) + (s * 75) + f) - 150;
821                         if(lba < 0) lba = 0;
822                         next_seek_lba = lba;
823                         cdrom_debug_log(_T("CMD SEEK(%02X) M/S/F = %d/%d/%d  M2/S2/F2 = %d/%d/%d LBA=%d"), command,
824                                                   TO_BCD(m), TO_BCD(s), TO_BCD(f),
825                                                   TO_BCD(exec_params[3]), TO_BCD(exec_params[4]), TO_BCD(exec_params[5]),
826                                                   lba
827                         );
828                         double usec = 50.0e3; // From Tsugaru.
829                         stop_time_out();
830                         //double usec = get_seek_time(0); // At first, seek to track 0.
831                         //if(usec < 1.0e3) usec = 1.0e3;
832
833                         // 20200626 K.O
834                         // At first, SEEK to LBA0.
835                         // Next, SEEK TO ARG's LBA.
836                         // Then, If set status to queue if (CMD & 20h) == 20h.
837                         // Last, *FORCE TO MAKE* interrupt even (CMD & 20h) != 20h..
838                         // See event_callback(EVENT_CDROM_RESTORE, foo).
839                         //req_status = true;
840                         status_seek = true;
841                         force_register_event(this,
842                                                    EVENT_CDROM_RESTORE,
843                                                    usec, false, event_seek);
844                 }
845                 break;
846         case CDROM_COMMAND_READ_MODE2: // 01h
847                 cdrom_debug_log(_T("CMD READ MODE2(%02X)"), command);
848                 read_mode = CDROM_READ_MODE2;
849                 read_cdrom();
850                 break;
851         case CDROM_COMMAND_READ_MODE1: // 02h
852                 cdrom_debug_log(_T("CMD READ MODE1(%02X)"), command);
853                 read_mode = CDROM_READ_MODE1;
854                 read_cdrom();
855                 break;
856         case CDROM_COMMAND_READ_RAW: // 03h
857                 cdrom_debug_log(_T("CMD READ RAW(%02X)"), command);
858                 read_mode = CDROM_READ_RAW;
859                 read_cdrom();
860                 break;
861         case CDROM_COMMAND_PLAY_TRACK: // 04h
862                 cdrom_debug_log(_T("CMD PLAY TRACK(%02X)"), command);
863                 play_cdda_from_cmd(); // ToDo : Re-Implement.
864                 break;
865         case CDROM_COMMAND_READ_TOC: // 05h
866                 cdrom_debug_log(_T("CMD READ TOC(%02X)"), command);
867                 if(req_status) {
868                         if(status_media_changed_or_not_ready(false)) {
869                                 break;
870                         }
871                         status_accept(1, 0x00, 0x00, true, false);
872                 } else {
873                         set_status(true, 2, TOWNS_CD_STATUS_TOC_ADDR, 0, 0xa0, 0, false);
874                 }
875                 // TOC READING
876                 break;
877         case CDROM_COMMAND_READ_CDDA_STATE: // 06h
878                 // ToDo: Some softwares check via this command, strongly to be fixed.
879                 // -- 20220125 K.O
880                 command_execute_phase = false;
881                 if(req_status) {
882                         if(status_media_changed_or_not_ready(false)) {
883                                 return;
884                         }
885                         memcpy(subq_snapshot, subq_bytes, sizeof(subq_snapshot));
886                         set_status(true, 1, TOWNS_CD_STATUS_ACCEPT, TOWNS_CD_ACCEPT_NOERROR, 0x00, 0x00, false);
887                 } else {
888                         mcu_ready = true;
889                 }
890                 break;
891         case CDROM_COMMAND_1F:
892                 cdrom_debug_log(_T("CMD UNKNOWN 1F(%02X)"), command);
893                 command_execute_phase = false;
894                 if(req_status) {
895                         if(status_media_changed_or_not_ready(false)) {
896                                 return;
897                         }
898                         status_accept(0, 0, 0, true, true); // Say reply.
899                 } else {
900                         mcu_ready = true;
901                         //set_delay_ready(false); // OK? 20230127 K.O
902                 }
903                 break;
904         case CDROM_COMMAND_SET_STATE: // 80h
905                 cdrom_debug_log(_T("CMD SET STATE(%02X) PARAM=%02X %02X %02X %02X %02X %02X %02X %02X"),
906                                           command,
907                                           exec_params[0],
908                                           exec_params[1],
909                                           exec_params[2],
910                                           exec_params[3],
911                                           exec_params[4],
912                                           exec_params[5],
913                                           exec_params[6],
914                                           exec_params[7]
915                         );
916                 command_execute_phase = false; // OK?
917                 if(req_status) {
918                         // ToDo:
919                         if(status_media_changed_or_not_ready(false)) {
920                                 return;
921                         }
922                         #if 0
923                         uint8_t __s1 = TOWNS_CD_ACCEPT_NOERROR;
924                         clear_status_queue(true);
925                         if(status_seek) {
926                                 // @note In SUPER REAL MAHJONG PIV, maybe check below.
927                                 // @note 20201110 K.O
928                                 __s1 = (toc_table[current_track].is_audio) ? TOWNS_CD_ACCEPT_WAIT : TOWNS_CD_ACCEPT_DATA_TRACK;
929                         }
930                         extra_status = 0;
931                         push_status_queue(TOWNS_CD_STATUS_ACCEPT, __s1, 0x00, 0x00);
932                         #else
933                         status_accept(0, 0x00, 0x00, true, false); // Push queue Immediately
934                         #endif
935                         if(cdda_status == CDDA_ENDED) {
936                                 // From Tsugaru 95afde8c :
937                                 // 2020/07/30
938                                 // Vain Dream crashes when CD BIOS Call AX=53C0H returns an error because the BIOS is expecting
939                                 // status 00 00 00 00, but this PushStatusCDDAPlayEnded() pushes 07 00 00 00.
940                                 // The retry code jumps to 4600:0084
941                                 //     4600:0084 1E                        PUSH    DS
942                                 //     4600:0085 8CC8                      MOV     AX,CS
943                                 // However, it should really jump to 4600:0085.  By jumping to 4600:0084, PUSH DS moves SP
944                                 // by two bytes, and the subsequent RETF fails to return to the correct address.
945                                 //
946                                 // Vain Dream runs by commenting out PushStatusCDDAPlayEnded() below.  But,
947                                 // in the past I saw something (presumably one version of CD-ROM BIOS) was expecting
948                                 // 07 00 00 00 status after CDDA is done, but I cannot find it
949                                 //
950                                 // Maybe subsequent to CDDA Stop command?
951
952                                 // PushStatusCDDAPlayEnded();
953                                 set_cdda_status(CDDA_OFF);
954                         }
955                         if(stat_reply_intr) {
956                                 mcu_intr = true;
957                                 write_mcuint_signals(true);
958                         }
959                 }
960                 mcu_ready = true;
961                 break;
962         case CDROM_COMMAND_SET_CDDASET: // 81h
963                 cdrom_debug_log(_T("%s(%02X)"), get_command_name_from_command(command), command);
964                 command_execute_phase = false;
965                 if(req_status) {
966                         // FROM Tsugaru:
967                         // I don't know what to do with this command.
968                         // CDROM BIOS AH=52H fires command 0xA1 with parameters {07 FF 00 00 00 00 00 00}
969                         if(!(status_media_changed_or_not_ready(false))) {
970                                 //status_accept(0, 0x00, 0x00, true, true); // OK?
971                                 status_accept(0, 0x00, 0x00, true, false); // OK?
972                         }
973                 }
974                 mcu_ready = true;
975                 break;
976         case CDROM_COMMAND_STOP_CDDA: // 84h
977                 cdrom_debug_log(_T("CMD STOP CDDA(%02X)"), command);
978                 ///@note From Tsugaru : 20200530 K.O
979                 //      clear_event(this, event_drq);
980                 //      write_signals(&outputs_drq, 0x00000000); // CLEAR DRQ
981
982                 if(cdda_status == CDDA_PLAYING) {
983                         force_register_event(this, EVENT_CDDA_DELAY_STOP, 1000.0, false, event_cdda_delay_stop);
984                 } else {
985                         clear_event(this, event_cdda_delay_stop);
986                         stop_cdda_from_cmd();
987                 }
988                 break;
989         case CDROM_COMMAND_PAUSE_CDDA: // 85h
990                 cdrom_debug_log(_T("CMD PAUSE CDDA2(%02X)"), command);
991                 pause_cdda_from_cmd(); // ToDo : Re-Implement.
992                 break;
993         case CDROM_COMMAND_RESUME_CDDA: // 87h
994                 cdrom_debug_log(_T("CMD RESUME CDDA(%02X)"), command);
995                 unpause_cdda_from_cmd();
996                 break;
997         case CDROM_COMMAND_86: // 86h
998                 cdrom_debug_log(_T("CMD UNKNOWN 86(%02X)"), command);
999                 status_not_accept(0, 0x00, 0x00, 0x00, false, true); // ToDo: Will implement
1000                 break;
1001         case CDROM_COMMAND_9F: // 9Fh
1002                 cdrom_debug_log(_T("CMD UNKNOWN 9F(%02X)"), command);
1003                 command_execute_phase = false;
1004                 clear_status_queue(true);
1005                 push_status_queue(TOWNS_CD_STATUS_CMD_ABEND, 0x00, 0x00, 0x00); // OK?
1006                 mcu_ready = true;
1007                 //set_delay_ready(false); // OK? 20230127 K.O
1008                 break;
1009         default:
1010                 cdrom_debug_log(_T("CMD Illegal(%02X)"), command);
1011                 command_execute_phase = false;
1012                 status_not_accept(0, 0x00, 0x00, 0x00, false, true); // ToDo: Will implement
1013                 break;
1014         }
1015 }
1016
1017 void TOWNS_CDROM::set_extra_status_values(uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3, const bool is_immediate, const bool force_interrupt)
1018 {
1019         clear_status_queue(false);
1020         push_status_queue(s0, s1, s2, s3);
1021 //      cdrom_debug_log(_T("SET EXTRA STATUS %02x: %02x %02x %02x %02x EXTRA COUNT=%d"), latest_command, s0, s1, s2, s3, extra_status);
1022         if(is_immediate) {
1023                 mcu_intr = false;
1024                 mcu_ready = true;
1025                 bool i_enable = (!(mcu_intr_mask) || (force_interrupt)) ? true :  false;
1026                 if((stat_reply_intr) && (i_enable)) { // From Tsugaru, 20231001
1027                         set_mcu_intr(true);
1028                 }
1029         } else {
1030                 set_delay_ready(force_interrupt);
1031         }
1032 }
1033
1034 void TOWNS_CDROM::set_status_extra_toc_addr(uint8_t s1, uint8_t s2, uint8_t s3)
1035 {
1036         set_extra_status_values(TOWNS_CD_STATUS_TOC_ADDR, s1, s2, s3, false, false); // OK?
1037         extra_status++;
1038 }
1039
1040 void TOWNS_CDROM::set_status_extra_toc_data(uint8_t s1, uint8_t s2, uint8_t s3)
1041 {
1042         set_extra_status_values(TOWNS_CD_STATUS_TOC_DATA, s1, s2, s3, false, false); // OK?
1043         extra_status++;
1044 }
1045
1046 uint8_t TOWNS_CDROM::read_status()
1047 {
1048         uint8_t val = 0xff;
1049         if(status_queue->empty()) {
1050                 has_status = false;
1051                 return val;
1052         }
1053         val = status_queue->read();
1054         has_status = (status_queue->empty()) ? false : true;
1055
1056         if((status_queue->empty()) && (extra_status > 0)) {
1057                 set_extra_status();
1058         }
1059         return val;
1060 }
1061
1062
1063 void TOWNS_CDROM::dma_transfer_epilogue()
1064 {
1065         stop_drq();
1066         // ToDo:
1067         // ToDo: CD-ROM with cache.
1068         stop_time_out();
1069
1070         dma_transfer_phase = false;
1071         pio_transfer_phase = false;
1072         //dma_transfer = false;
1073         //pio_transfer = false;
1074         write_signals(&outputs_drq, 0x00000000); // CLEAR DRQ
1075
1076         if(read_length <= 0) {
1077                 clear_event(this, event_next_sector);
1078                 dma_transfer = false;
1079                 pio_transfer = false;
1080                 status_seek = false;
1081                 cdrom_debug_log(_T("DMA: EOT by READ COMPLETED"));
1082                 write_signals(&outputs_eot, 0xffffffff);
1083                 status_read_done(false);
1084         } else {
1085                 // Call to read next sector.  -> Move to READING EVENT.
1086         }
1087         set_dma_intr(true);
1088 }
1089
1090
1091 void TOWNS_CDROM::pio_transfer_epilogue()
1092 {
1093         // ToDo:
1094         // ToDo: CD-ROM with cache.
1095         stop_drq();
1096
1097         stop_time_out();
1098         dma_transfer_phase = false;
1099         pio_transfer_phase = false;
1100         //dma_transfer = false;
1101         //pio_transfer = false;
1102         write_signals(&outputs_drq, 0x00000000); // CLEAR DRQ
1103
1104         if(read_length <= 0) {
1105                 status_seek = false;
1106                 dma_transfer = false;
1107                 pio_transfer = false;
1108                 clear_event(this, event_next_sector);
1109                 cdrom_debug_log(_T("PIO: EOT by READ COMPLETED"));
1110                 //write_signals(&outputs_eot, 0xffffffff);
1111                 status_read_done(false);
1112         } else {
1113                 // Call to read next sector
1114                 #if 0
1115                 status_seek = true;
1116                 int physical_size = physical_block_size();
1117                 int l = physical_size - logical_block_size();
1118                 if(l <= 2) l = 1;
1119                 register_event(this, EVENT_CDROM_READY_TO_READ,
1120                                            (1.0e6 / ((double)transfer_speed * 150.0e3)) *
1121                                            (double)l,
1122                                            false,
1123                                            &event_next_sector);
1124                 //cdrom_debug_log(_T("PIO: NEXT SECTOR LEFT=%d"), read_length);
1125                 #endif
1126         }
1127 //      set_dma_intr(true);
1128 }
1129
1130 uint32_t TOWNS_CDROM::read_dma_io8w(uint32_t addr, int *wait)
1131 {
1132         __LIKELY_IF(wait != NULL) {
1133                 *wait = 0; // Temporally.
1134         }
1135         __UNLIKELY_IF(!(dmac_running) && (dma_transfer_phase) && (dma_transfer)) { // Fallthrough
1136                 return 0x00;
1137         }
1138         bool is_empty = databuffer->empty();
1139
1140         __UNLIKELY_IF(!(dma_transfer_phase) && !(pio_transfer_phase)) {
1141                 return 0x00;
1142         }
1143         __UNLIKELY_IF(is_empty) {
1144                 data_reg.b.h = data_reg.b.l;
1145                 data_reg.b.l = 0x00;
1146         } else {
1147                 fetch_datareg_8();
1148         }
1149         __LIKELY_IF(dma_transfer_phase) {
1150                 write_signals(&outputs_drq, 0x0);
1151         } else if(pio_transfer_phase) {
1152                 if(!(is_empty) && (databuffer->empty())) {
1153                         cancel_event(this, event_delay_ready);
1154                         pio_transfer_epilogue();
1155                         //register_event(this, EVENT_CDROM_DELAY_EOT_PIO,
1156                         //                         1.0, // Temporally
1157                         //                         false,
1158                         //                         &event_delay_ready);
1159                 }
1160         }
1161         return data_reg.b.l;
1162 }
1163
1164 void TOWNS_CDROM::write_dma_io8w(uint32_t addr, uint32_t data, int *wait)
1165 {
1166         *wait = 0; // Temporally.
1167         // data_reg = data;
1168         return; // OK?
1169 }
1170
1171 uint32_t TOWNS_CDROM::read_dma_io16w(uint32_t addr, int *wait)
1172 {
1173         __LIKELY_IF(wait != NULL) {
1174                 *wait = 0; // Temporally.
1175         }
1176         __UNLIKELY_IF(!(dmac_running) && (dma_transfer_phase) && (dma_transfer)) { // Fallthrough
1177                 return 0x0000;
1178         }
1179         bool is_empty = databuffer->empty();
1180
1181         __UNLIKELY_IF(!(dma_transfer_phase) && !(pio_transfer_phase)) {
1182                 return 0x0000;
1183         }
1184         __UNLIKELY_IF(is_empty) {
1185                 data_reg.w = 0x0000;
1186         } else {
1187                 fetch_datareg_16();
1188         }
1189         __LIKELY_IF(dma_transfer_phase) {
1190                 write_signals(&outputs_drq, 0x0);
1191         } else if(pio_transfer_phase) {
1192                 if(!(is_empty) && (databuffer->empty())) {
1193                         cancel_event(this, event_delay_ready);
1194                         pio_transfer_epilogue();
1195                         //register_event(this, EVENT_CDROM_DELAY_EOT_PIO,
1196                         //                         1.0, // Temporally
1197                         //                         false,
1198                         //                         &event_delay_ready);
1199                 }
1200         }
1201         return data_reg.w;
1202 }
1203
1204 void TOWNS_CDROM::write_dma_io16w(uint32_t addr, uint32_t data, int *wait)
1205 {
1206         *wait = 0; // Temporally.
1207         // data_reg = data;
1208         return; // OK?
1209 }
1210
1211 void TOWNS_CDROM::read_cdrom()
1212 {
1213         mcu_ready = true;
1214         if((cdda_status != CDDA_OFF) && (cdda_status != CDDA_ENDED)) {
1215                 // @note In SUPER REAL MAHJONG PIV, use PAUSE (A5h) command before reading.
1216                 // @note 20201110 K.O
1217                 set_cdda_status(CDDA_ENDED);
1218         } else {
1219                 set_cdda_status(CDDA_OFF);
1220         }
1221         if(status_media_changed_or_not_ready(false)) {
1222                 set_subq(0);
1223                 return;
1224         }
1225
1226         uint8_t m1, s1, f1;
1227         uint8_t m2, s2, f2;
1228 //      uint8_t pad1, dcmd;
1229
1230         m1 = FROM_BCD(exec_params[0]);
1231         s1 = FROM_BCD(exec_params[1]);
1232         f1 = FROM_BCD(exec_params[2]);
1233
1234         m2 = FROM_BCD(exec_params[3]);
1235         s2 = FROM_BCD(exec_params[4]);
1236         f2 = FROM_BCD(exec_params[5]);
1237         uint8_t pad1 = exec_params[6];
1238         uint8_t dcmd = exec_params[7];
1239
1240         int32_t lba1 = ((m1 * (60 * 75)) + (s1 * 75) + f1) - 150;
1241         int32_t lba2 = ((m2 * (60 * 75)) + (s2 * 75) + f2) - 150;
1242
1243         uint32_t __remain;
1244         int track = 0;
1245         extra_status = 0;
1246         read_length = 0;
1247
1248         cdrom_debug_log(_T("READ_CDROM LBA1=%d LBA2=%d M1/S1/F1=%02X/%02X/%02X M2/S2/F2=%02X/%02X/%02X PAD=%02X DCMD=%02X"), lba1, lba2,
1249                                   exec_params[0], exec_params[1], exec_params[2],
1250                                   exec_params[3], exec_params[4], exec_params[5],
1251                                   pad1, dcmd);
1252         uint32_t cur_lba = get_image_cur_position();
1253         set_subq(cur_lba);
1254
1255         if((lba1 > lba2) || (lba1 < 0) || (lba2 < 0)) { // NOOP?
1256                 status_parameter_error(false);
1257                 return;
1258         }
1259
1260         track = get_track(lba1);
1261         //track = get_track_noop(lba1);
1262         if((track <= 0) || (track >= track_num)) {
1263                 status_parameter_error(false);
1264                 return;
1265         }
1266         __remain = (lba2 - lba1 + 1);
1267         read_length = __remain * logical_block_size();
1268         read_sector = lba1;
1269         current_track = track;
1270         dma_transfer_phase = false;
1271         pio_transfer_phase = false;
1272         dma_intr = false;
1273         mcu_intr = false;
1274
1275         //clear_event(this, event_drq);
1276         clear_event(this, event_next_sector);
1277
1278         // Kick a first
1279         status_seek = true;
1280         double usec = 50.0;
1281         databuffer->clear();
1282         stop_time_out();
1283         //double usec = get_seek_time(lba1);
1284         next_seek_lba = lba1;
1285         read_sector = lba1;
1286
1287         clear_event(this, event_next_sector);
1288         clear_event(this, event_seek);
1289
1290         write_signals(&outputs_drq, 0x00000000); // CLEAR DRQ
1291         register_event(this, EVENT_CDROM_READY_TO_READ, usec, false, &event_next_sector);
1292         mcu_intr = true;
1293
1294         status_accept(0, 0, 0, true, false);
1295         mcu_ready = false;
1296 }
1297
1298
1299 void TOWNS_CDROM::set_status(const bool push_status, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3, const bool force_interrupt)
1300 {
1301         cdrom_debug_log(_T("SET STATUS: %02X %02X %02X %02X, EXTRA=%d REQ_STATUS=%s"),
1302                                         s0, s1, s2, s3,
1303                                         extra,
1304                                         (push_status) ? _T("Yes"): _T("No")
1305                 );
1306         clear_status_queue(true);
1307         if(!(push_status) || (extra <= 0)) {
1308                 command_execute_phase = false;
1309         }
1310         if(push_status) {
1311                 if(extra > 0) extra_status = extra;
1312                 push_status_queue(s0, s1, s2, s3);
1313         }
1314         set_delay_ready(force_interrupt);
1315 }
1316
1317 void TOWNS_CDROM::set_status_read_done(bool push_status, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3)
1318 {
1319         cdrom_debug_log(_T("SET STATUS(READ DONE): %02X %02X %02X %02X, EXTRA=%d REQ_STATUS=%s"),
1320                                         s0, s1, s2, s3,
1321                                         extra,
1322                                         (push_status) ? _T("Yes"): _T("No")
1323                 );
1324         clear_status_queue(true);
1325         if(extra >= 0) {
1326                 extra_status = extra;
1327         }
1328         command_execute_phase = false;
1329         push_status_queue(s0, s1, s2, s3);
1330         set_delay_ready_eot(false);
1331 }
1332
1333 void TOWNS_CDROM::set_status_cddareply(const bool force_interrupt, int extra, uint8_t s2, uint8_t s3)
1334 {
1335         cdrom_debug_log(_T("SET STATUS(CDDA REPLY): %02X %02X, EXTRA=%d REQ_STATUS=%s, FORCE_INTERRUPT=%s"),
1336                                         s2, s3,
1337                                         extra,
1338                                         (req_status) ? _T("Yes"): _T("No"),
1339                                         (force_interrupt) ? _T("Yes"): _T("No")
1340                 );
1341         clear_status_queue(true);
1342         mcu_ready = true;
1343         if(!(req_status) || (extra <= 0)) {
1344                 command_execute_phase = false;
1345         }
1346         if(req_status) {
1347                 if(status_media_changed_or_not_ready(force_interrupt)) {
1348                         return;
1349                 }
1350                 mcu_intr = true;
1351                 status_accept(extra, s2, s3, true, force_interrupt);
1352         }
1353 }
1354
1355 void TOWNS_CDROM::set_status_immediate(const bool push_status, const bool force_interrupt, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3)
1356 {
1357         cdrom_debug_log(_T("SET STATUS(IMMEDIATE): %02X %02X %02X %02X, EXTRA=%d FORCE_INTERRUPT=%s, PUSH_STATUS=%s"),
1358                                         s0, s1, s2, s3,
1359                                         extra,
1360                                         (force_interrupt) ? _T("Yes"): _T("No"),
1361                                         (push_status) ? _T("Yes"): _T("No")
1362                 );
1363         clear_status_queue(true);
1364         if(!(push_status) || (extra <= 0)) {
1365                 command_execute_phase = false;
1366         }
1367         if(push_status) {
1368                 if(extra >= 0) {
1369                         extra_status = extra;
1370                 }
1371                 push_status_queue(s0, s1, s2, s3);
1372         }
1373         mcu_intr = false;
1374         mcu_ready = true;
1375         bool i_enable = (!(mcu_intr_mask) || (force_interrupt)) ? true :  false;
1376         if((stat_reply_intr) && (req_status) && (i_enable)) { // From Tsugaru, 20231001
1377                 set_mcu_intr(true);
1378         }
1379 }
1380
1381 void TOWNS_CDROM::set_extra_status()
1382 {
1383         switch(latest_command & 0x9f) {
1384         //switch(prev_command & 0x9f) {
1385         case CDROM_COMMAND_SEEK:
1386                 if(extra_status > 0) {
1387                         set_extra_status_values(TOWNS_CD_STATUS_SEEK_COMPLETED, 0x00, 0x00, 0x00, false, false);
1388                         extra_status = 0;
1389                 }
1390                 command_execute_phase = false;
1391                 break;
1392         case CDROM_COMMAND_READ_MODE1:
1393         case CDROM_COMMAND_READ_MODE2:
1394         case CDROM_COMMAND_READ_RAW:
1395                 //if(extra_status == 2) {
1396                 //      status_data_ready(false);
1397                 //}
1398                 command_execute_phase = false;
1399                 extra_status = 0;
1400                 break;
1401         case CDROM_COMMAND_PLAY_TRACK: // PLAY CDDA
1402                 // From MAME 0.254. 20230530 K.O
1403                 if(cdda_status != CDDA_PLAYING) {
1404                         set_extra_status_values(TOWNS_CD_STATUS_PLAY_DONE, 0, 0, 0, false, false);
1405                 } else {
1406                         set_extra_status_values(TOWNS_CD_STATUS_ACCEPT, 0, TOWNS_CD_ACCEPT_CDDA_PLAYING, 0, false, false); // OK?
1407                 }
1408                 command_execute_phase = false;
1409                 extra_status = 0;
1410                 break;
1411         case CDROM_COMMAND_READ_TOC: // 0x05
1412                         switch(extra_status) {
1413                         case 1:
1414                                 set_status_extra_toc_addr(0x00, 0xa0, 0x00);
1415                                 break;
1416                         case 2: // st1 = first_track_number
1417                                 set_status_extra_toc_data(TO_BCD(0x01), 0x00, 0x00);
1418                                 break;
1419                         case 3:
1420                                 set_status_extra_toc_addr(0x00, 0xa1, 0x00);
1421                                 break;
1422                         case 4:
1423                                 set_status_extra_toc_data(TO_BCD(track_num - 1), 0x00, 0x00); // OK?
1424                                 break;
1425                         case 5:
1426                                 set_status_extra_toc_addr(0x00, 0xa2, 0x00);
1427                                 break;
1428                         case 6:
1429                                 {
1430                                         pair32_t msf;
1431                                         msf.d= read_signal(SIG_TOWNS_CDROM_START_MSF_AA);
1432                                         set_status_extra_toc_data(msf.b.h2, msf.b.h, msf.b.l); // OK?
1433                                         stat_track = 1;
1434                                 }
1435                                 break;
1436                         default:
1437                                 if((extra_status & 0x01) != 0) {
1438 //                                      stat_track = (extra_status - 2) >> 1;
1439                                         uint32_t adr_control = cdrom_get_adr(stat_track);
1440                                         set_status_extra_toc_addr(((adr_control & 0x0f) << 4) | ((adr_control >> 4) & 0x0f), TO_BCD((extra_status / 2) - 2), 0x00);
1441                                 } else {
1442                                         pair32_t msf;
1443                                         msf.d = read_signal(SIG_TOWNS_CDROM_START_MSF);
1444                                         cdrom_debug_log(_T("TRACK=%d M:S:F=%02X:%02X:%02X"), stat_track - 1, msf.b.h2, msf.b.h, msf.b.l);
1445                                         set_status_extra_toc_data(msf.b.h2, msf.b.h, msf.b.l); // OK?
1446                                         if((track_num <= 0) || (stat_track >= track_num)) {
1447                                                 command_execute_phase = false; // OK?
1448                                                 extra_status = 0; // It's end.
1449                                         }
1450                                 }
1451                                 break;
1452                         }
1453                 break;
1454         case CDROM_COMMAND_READ_CDDA_STATE: // 06h
1455                 switch(extra_status) {
1456                 case 1:
1457                         // Track Number
1458                         set_extra_status_values(TOWNS_CD_STATUS_SUBQ_READ1, 0x00, subq_snapshot[2], 0x00, false, false);
1459                         extra_status++;
1460                         break;
1461                 case 2:
1462                         // Relative MSF
1463                         set_extra_status_values(TOWNS_CD_STATUS_SUBQ_READ2, subq_snapshot[7], subq_snapshot[8], subq_snapshot[9], false, false);
1464                         extra_status++;
1465                         break;
1466                 case 3:
1467                         // Absolute MS
1468                         set_extra_status_values(TOWNS_CD_STATUS_SUBQ_READ3, 0x00, subq_snapshot[3], subq_snapshot[4], false, false);
1469                         extra_status++;
1470                         break;
1471                 case 4:
1472                         // Absolute F
1473                         set_extra_status_values(TOWNS_CD_STATUS_SUBQ_READ4, 0x00, subq_snapshot[5], 0x00, false, false);
1474                         command_execute_phase = false;
1475                         extra_status = 0;
1476                         break;
1477                 default:
1478                         command_execute_phase = false;
1479                         extra_status = 0;
1480                         break;
1481                 }
1482                 break;
1483         case CDROM_COMMAND_SET_STATE: // 80h Thank to Yamakawa-San.20200626 K.O
1484                 if(extra_status > 0) {
1485                         set_extra_status_values(TOWNS_CD_STATUS_PLAY_DONE, 0x00, 0x00, 0x00, false, false);
1486                         extra_status = 0;
1487                 }
1488                 command_execute_phase = false;
1489                 break;
1490         case CDROM_COMMAND_STOP_CDDA:
1491                 switch(extra_status) {
1492                 case 1:
1493                         set_extra_status_values(TOWNS_CD_STATUS_STOP_DONE, 0x00, 0x00, 0x00, false, false);
1494                         extra_status++;
1495                         //extra_status = 0; // OK? 20230530 K.O from MAME 0.254
1496                         break;
1497                 case 2:
1498                         set_extra_status_values(0x00, TOWNS_CD_ACCEPT_WAIT, 0x00, 0x00, false, false);
1499                         extra_status = 0;
1500                         command_execute_phase = false;
1501                         break;
1502                 default:
1503                         extra_status = 0;
1504                         command_execute_phase = false;
1505                         break;
1506                 }
1507                 break;
1508         case CDROM_COMMAND_PAUSE_CDDA:
1509                 if(extra_status == 1) {
1510                         set_extra_status_values(TOWNS_CD_STATUS_PAUSE_DONE, 0x00, 0x00, 0x00, false, false);
1511                 }
1512                 extra_status = 0;
1513                 command_execute_phase = false;
1514                 break;
1515         case CDROM_COMMAND_RESUME_CDDA:
1516                 if(extra_status == 1) {
1517                         set_extra_status_values(TOWNS_CD_STATUS_RESUME_DONE, 0, 0x00, 0x00, false, false); // From Tsugaru
1518                 }
1519                 extra_status = 0;
1520                 command_execute_phase = false;
1521                 break;
1522         default:
1523                 extra_status = 0;
1524                 command_execute_phase = false;
1525                 break;
1526         }
1527 }
1528
1529 uint32_t TOWNS_CDROM::read_signal(int id)
1530 {
1531         switch(id) {
1532         case SIG_TOWNS_CDROM_READ_DATA:
1533                 return data_reg.w;
1534                 break;
1535         case SIG_TOWNS_CDROM_PLAYING:
1536                 return (cdda_status == CDDA_PLAYING && cdda_interrupt) ? 0xffffffff : 0;
1537                 break;
1538         case SIG_TOWNS_CDROM_SAMPLE_L:
1539                 return (uint32_t)abs(cdda_sample_l);
1540                 break;
1541         case SIG_TOWNS_CDROM_SAMPLE_R:
1542                 return (uint32_t)abs(cdda_sample_r);
1543                 break;
1544         case SIG_TOWNS_CDROM_IS_MEDIA_INSERTED:
1545                 return ((is_device_ready()) ? 0xffffffff : 0x00000000);
1546                 break;
1547         case SIG_TOWNS_CDROM_MAX_TRACK:
1548                 if(track_num <= 0) {
1549                         return (uint32_t)(TO_BCD(0x00));
1550                 } else {
1551                         return (uint32_t)(TO_BCD(track_num));
1552                 }
1553                 break;
1554                 /*
1555         case SIG_TOWNS_CDROM_REACHED_MAX_TRACK:
1556                 if(track_num <= 0) {
1557                         return 0xffffffff;
1558                 } else {
1559                         if(current_track >= track_num) {
1560                                 return 0xffffffff;
1561                         } else {
1562                                 return 0x00000000;
1563                         }
1564                 }
1565                 break;
1566                 */
1567         case SIG_TOWNS_CDROM_CURRENT_TRACK:
1568                 if(current_track >= track_num) {
1569                         return 0x00000000;
1570                 } else {
1571                         return TO_BCD(current_track);
1572                 }
1573                 break;
1574         case SIG_TOWNS_CDROM_START_MSF:
1575                 {
1576                         int trk = stat_track;
1577                         if(trk <= 0) {
1578                                 return 0xffffffff;
1579                         }
1580                         if(trk == 0xaa) {
1581                                 trk = track_num;
1582                         }
1583                         int index0 = toc_table[trk].index0;
1584                         int index1 = toc_table[trk].index1;
1585                         int pregap = toc_table[trk].pregap;
1586                         //if(pregap > 0) index0 = index0 + pregap;
1587                         //if(index0 < 150) index0 = 150;
1588                         uint32_t lba = (uint32_t)index0;
1589                         uint32_t msf = lba_to_msf(lba); // Q:lba + 150?
1590                         stat_track++;
1591                         return msf;
1592                 }
1593                 break;
1594         case SIG_TOWNS_CDROM_START_MSF_AA:
1595                 {
1596                         int trk = track_num;
1597                         int index0 = toc_table[trk].index0;
1598                         int index1 = toc_table[trk].index1;
1599                         int pregap = toc_table[trk].pregap;
1600                         uint32_t lba = (uint32_t)index0;
1601                         if(pregap > 0) lba = lba + pregap;
1602                         if(lba < 150) lba = 150;
1603                         uint32_t msf = lba_to_msf(lba); // Q:lba + 150?
1604                         return msf;
1605                 }
1606                 break;
1607         case SIG_TOWNS_CDROM_RELATIVE_MSF:
1608                 if(!(is_device_ready())) {
1609                         return 0;
1610                 }
1611                 if((current_track <= 0) || (current_track >= track_num)) {
1612                         return 0;
1613                 }
1614                 if(toc_table[current_track].is_audio) {
1615 //                      uint32_t index1 = toc_table[current_track].index1;
1616                         uint32_t index1 = cdda_start_frame;
1617                         if(cdda_playing_frame <= cdda_start_frame) {
1618                                 return 0;
1619                         }
1620                         if(cdda_end_frame <= cdda_start_frame) {
1621                                 return 0;
1622                         }
1623                         uint32_t n = 0;
1624                         uint32_t lba = cdda_playing_frame;
1625                         __UNLIKELY_IF(lba >= cdda_end_frame) {
1626                                 if(cdda_repeat_count == 0) {
1627                                         lba = 0;
1628                                 } else {
1629                                         if(cdda_end_frame > index1) {
1630                                                 lba = cdda_end_frame;
1631                                         } else {
1632                                                 lba = 0;
1633                                         }
1634                                 }
1635                         }
1636                          if(lba >= index1) {
1637                                 n = lba - index1;
1638                         }
1639                         return lba_to_msf(n);
1640                 } else {
1641                         // Not Audio
1642                         uint32_t index1 = toc_table[current_track].index1;
1643                         uint32_t lba = get_image_cur_position();
1644                         uint32_t n = 0;
1645                         if(lba >= index1) {
1646                                 n = lba - index1;
1647                         }
1648                         return lba_to_msf(n);
1649                 }
1650                 break;
1651         case SIG_TOWNS_CDROM_ABSOLUTE_MSF:
1652                 if(!(is_device_ready())) {
1653                         return 0;
1654                 }
1655                 if((current_track <= 0) || (current_track >= track_num)) {
1656                         return 0;
1657                 }
1658                 {
1659                         uint32_t lba = 0;
1660                         if(toc_table[current_track].is_audio) {
1661                                 if((cdda_status == CDDA_PLAYING) || (cdda_status == CDDA_PAUSED)) {
1662                                         if(cdda_playing_frame >= max_logical_block) {
1663                                                 lba = max_logical_block;
1664                                         } else {
1665                                                 lba = cdda_playing_frame;
1666                                         }
1667                                 } else {
1668                                         lba = cdda_end_frame;
1669                                 }
1670                         } else {
1671                                 lba = get_image_cur_position();
1672                                 if(lba > max_logical_block) {
1673                                         lba = max_logical_block;
1674                                 }
1675                         }
1676                         return lba_to_msf(lba + 75 * 2);
1677                 }
1678                 break;
1679         case SIG_TOWNS_CDROM_GET_ADR:
1680                 return cdrom_get_adr(stat_track);
1681                 break;
1682         default:
1683                 // ToDo: Implement master DEV
1684                 //return SCSI_DEV::read_signal(id);
1685                 break;
1686         }
1687         return 0; // END TRAM
1688 }
1689
1690 uint32_t TOWNS_CDROM::cdrom_get_adr(int trk)
1691 {
1692         if(!(is_device_ready())) {
1693                 return 0xffffffff; // OK?
1694         }
1695         if(trk == 0xaa) {
1696                 return 0x10; // AUDIO SUBQ
1697         }
1698         if(trk > track_num) {
1699                 return 0xffffffff; // OK?
1700         }
1701         if(toc_table[trk].is_audio) {
1702                 return 0x10;
1703         }
1704         return 0x14; // return as data
1705 }
1706
1707 const int TOWNS_CDROM::physical_block_size()
1708 {
1709         if(current_track <= 0) return 2352; // PAD
1710         if(!mounted()) return 2352; // PAD
1711         if(is_iso) return 2352;
1712         switch(toc_table[current_track].type) {
1713         case MODE_AUDIO:
1714                 return 2352;
1715         case MODE_MODE1_2048:
1716                 return 2048;
1717         case MODE_MODE1_2352:
1718         case MODE_MODE2_2352:
1719         case MODE_CDI_2352:
1720                 return 2352;
1721         case MODE_MODE2_2336:
1722         case MODE_CDI_2336:
1723                 return 2336;
1724         case MODE_CD_G:
1725                 return 2448;
1726         default:
1727                 break;
1728         }
1729         // OK?
1730         return 2352;
1731 }
1732
1733 const int TOWNS_CDROM::logical_block_size()
1734 {
1735         if(current_track <= 0) return 2352; // PAD
1736         if(!mounted()) return 2352; // PAD
1737         if(is_iso) return 2048;
1738         switch(toc_table[current_track].type) {
1739         case MODE_AUDIO:
1740                 return 2352;
1741         case MODE_MODE1_2048:
1742         case MODE_MODE1_2352:
1743                 return 2048;
1744         case MODE_MODE2_2336:
1745         case MODE_MODE2_2352:
1746         case MODE_CDI_2336:
1747         case MODE_CDI_2352:
1748                 return 2336;
1749         case MODE_CD_G:
1750                 return 2448;
1751         default:
1752                 break;
1753         }
1754         // OK?
1755         return 2048;
1756 }
1757
1758 bool TOWNS_CDROM::start_to_play_cdda()
1759 {
1760         status_seek = false;
1761         access = false;
1762
1763         //stop_time_out();
1764         databuffer->clear();
1765         current_track = get_track(cdda_start_frame);
1766         set_subq(cdda_start_frame);
1767
1768         if((current_track <= 0) || (current_track >= track_num)) {
1769                 set_cdda_status(CDDA_OFF);
1770                 return false; // SEEK ERROR;
1771         }
1772         if(!(toc_table[current_track].is_audio)) {
1773                 // NOT AUDIO
1774                 set_cdda_status(CDDA_OFF);
1775                 return false; //;
1776         }
1777
1778         cdda_playing_frame = cdda_start_frame;
1779         read_sector = cdda_start_frame;
1780         seek_relative_frame_in_image(cdda_playing_frame);
1781         //if(cdda_status != CDDA_PLAYING) {
1782                 set_cdda_status(CDDA_PLAYING);
1783         //}
1784         if(prefetch_audio_sectors(1) < 1) {
1785                 set_cdda_status(CDDA_OFF);
1786                 return false; // READ ERROR
1787         }
1788         return true;
1789 }
1790
1791 void TOWNS_CDROM::event_callback(int event_id, int err)
1792 {
1793         switch (event_id) {
1794         case EVENT_CDROM_DELAY_COMMAND:
1795                 if((command_execute_phase) /*|| !(mcu_ready)*/) {
1796                         return;
1797                 }
1798                 clear_event(this, event_execute);
1799                 // Backup previous command.
1800                 prev_command = latest_command;
1801                 for(int i = 0; i < 8; i++) {
1802                         prev_params[i] = exec_params[i];
1803                 }
1804                 command_execute_phase = true;
1805                 execute_command(reserved_command);
1806                 break;
1807         case EVENT_CDROM_DELAY_INTERRUPT_ON: // DELAY INTERRUPT ON
1808                 event_delay_interrupt = -1;
1809                 mcu_ready = true;
1810                 set_mcu_intr(true);
1811                 break;
1812         case EVENT_CDROM_DELAY_INTERRUPT_OFF: // DELAY INTERRUPT OFF
1813                 event_delay_interrupt = -1;
1814                 mcu_ready = true;
1815                 set_mcu_intr(false);
1816                 break;
1817         case EVENT_CDROM_DELAY_READY: // CALL READY TO ACCEPT COMMAND WITH STATUS
1818                 event_delay_ready = -1;
1819                 media_changed = false;
1820                 media_ejected = false;
1821                 stop_time_out();
1822                 send_mcu_ready(); // OK? 20230127 K.O
1823                 break;
1824         case EVENT_CDROM_DELAY_READY_FORCEINT: // CALL READY TO ACCEPT COMMAND WITH STATUS
1825                 event_delay_ready = -1;
1826                 media_changed = false;
1827                 media_ejected = false;
1828                 stop_time_out();
1829                 mcu_ready = true;
1830                 set_mcu_intr(true);
1831                 //stat_reply_intr = false;
1832                 break;
1833         case EVENT_CDROM_DELAY_NOT_READY: // CALL READY TO ACCEPT COMMAND WITH STATUS
1834                 event_delay_ready = -1;
1835                 stop_time_out();
1836                 media_changed = false;
1837                 media_ejected = false;
1838                 command_execute_phase = false;
1839                 mcu_ready = true;
1840                 if(stat_reply_intr) {
1841                         set_mcu_intr(true);
1842                 }
1843                 break;
1844         case EVENT_CDROM_DELAY_NOT_READY_FORCEINT: // CALL READY TO ACCEPT COMMAND WITH STATUS
1845                 event_delay_ready = -1;
1846                 stop_time_out();
1847                 media_changed = false;
1848                 media_ejected = false;
1849                 command_execute_phase = false;
1850                 mcu_ready = true;
1851                 set_mcu_intr(true);
1852                 break;
1853         case EVENT_CDROM_READY_EOT:  // CALL END-OF-TRANSFER FROM CDC.
1854                 event_delay_ready = -1;
1855                 stop_time_out();
1856                 mcu_ready = true;
1857                 media_changed = false;
1858                 media_ejected = false;
1859                 command_execute_phase = false;
1860                 if(req_status) {
1861                         mcu_intr = true;
1862                         if(stat_reply_intr) {
1863                                 set_mcu_intr(true);
1864                         }
1865                 }
1866                 break;
1867         case EVENT_CDROM_READY_EOT_FORCEINT:  // CALL END-OF-TRANSFER FROM CDC.
1868                 event_delay_ready = -1;
1869                 stop_time_out();
1870                 mcu_ready = true;
1871                 media_changed = false;
1872                 media_ejected = false;
1873                 command_execute_phase = false;
1874                 if(req_status) {
1875                         mcu_intr = true;
1876                         set_mcu_intr(true);
1877                 }
1878                 break;
1879         case EVENT_CDROM_DELAY_EOT_PIO:
1880                 event_delay_ready = -1;
1881                 media_changed = false;
1882                 media_ejected = false;
1883                 command_execute_phase = false;
1884                 pio_transfer_epilogue();
1885                 break;
1886         case EVENT_CDDA_DELAY_PLAY: // DELAY STARTING TO PLAY CDDA
1887                 event_cdda_delay_play = -1;
1888                 start_to_play_cdda();
1889                 /*!
1890                  * @note This may solve halt incident of Kyukyoku Tiger, but something are wrong.
1891                  * @note 20201113 K.O
1892                  */
1893                 set_status_cddareply(false, 1, 0x00, 0x00);
1894                 break;
1895         case EVENT_CDDA_REPEAT: // DELAY STARTING TO PLAY CDDA
1896                 event_cdda_delay_play = -1;
1897                 clear_event(this, event_cdda);
1898                 if(cdda_status != CDDA_PLAYING) {
1899                         return;
1900                 }
1901                 {
1902                         cdda_buffer_ptr = 0;
1903                         access = false;
1904                         int track = get_track(cdda_start_frame);
1905                         if((track > 0) && (track < track_num)) {
1906                                 cdda_playing_frame = cdda_start_frame;
1907                                 read_sector = cdda_playing_frame;
1908                                 current_track = track;
1909                                 seek_relative_frame_in_image(cdda_playing_frame);
1910                                 cdda_stopped = false;
1911                                 if(prefetch_audio_sectors(1) < 1) {
1912                                         //set_cdda_status(CDDA_OFF);
1913                                         return; // READ ERROR
1914                                 }
1915                         } else {
1916                                 // ERROR
1917                                 current_track = get_track(0);
1918                                 cdda_playing_frame = 0;
1919                                 read_sector = 0;
1920                                 cdda_start_frame = 0;
1921                                 cdda_end_frame = 0;
1922                                 cdda_stopped = true;
1923                                 //set_cdda_status(CDDA_OFF);
1924                                 return;
1925                         }
1926                         if(mix_loop_num == 0) {
1927                                 if(event_cdda < 0) {
1928                                         register_event(this, EVENT_CDDA, 1.0e6 / 44100.0, true, &event_cdda);
1929                                 }
1930                         }
1931                         touch_sound();
1932                         set_realtime_render(this, true);
1933                         const _TCHAR *pp = get_cdda_status_name(cdda_status);
1934                         cdrom_debug_log(_T("REPEAT CDDA from %s.\n"), pp);
1935                 }
1936                 break;
1937         case EVENT_CDROM_CDDA_PLAY_STATUS: // READY TO ACCEPT A COMMAND FROM CDC.
1938                 event_delay_ready = -1;
1939                 send_mcu_ready(); // OK? 20230127 K.O
1940                 break;
1941         case EVENT_CDDA:  // READ A PAIR OF CDDA SAMPLE
1942                 read_a_cdda_sample();
1943                 return;
1944                 break;
1945         case EVENT_CDDA_DELAY_STOP:  // DELAY STOP
1946                 event_cdda_delay_stop = -1;
1947                 stop_cdda_from_cmd();
1948                 break;
1949         case EVENT_CDROM_RESTORE: // Restore to LBA 0.
1950                 // Seek0
1951                 event_seek = -1;
1952                 // 20231001 Backport from Tsugaru.
1953                 //mcu_ready = true;
1954                 //status_accept(0, 0, 0, true, true); // Say reply.
1955                 status_seek = true;
1956                 {
1957                         current_track = get_track(0);
1958                         //if(next_seek_lba == 0) { // Inside of pregap
1959                         //      event_callback(EVENT_CDROM_SEEK, 0);
1960                         //      break;
1961                         //}
1962                         double usec = 50.0e3; // From Tsugaru.
1963                         stop_time_out();
1964                         //double usec = get_seek_time(next_seek_lba);
1965                         //if(usec < 1.0e3) usec = 1.0e3;
1966                         cdrom_debug_log(_T("RESTORE to SECTOR 0: NEXT is %d after %f"), next_seek_lba, usec);
1967                         set_subq(0);
1968                         register_event(this,
1969                                                    EVENT_CDROM_SEEK,
1970                                                    usec, false, &event_seek);
1971                 }
1972                 break;
1973         case EVENT_CDROM_SEEK: // SEEK TO TARGET LBA (only for command 00h)
1974                 event_seek = -1;
1975                 status_seek = false;
1976                 current_track = get_track(next_seek_lba);
1977                 set_subq(next_seek_lba);
1978                 cdrom_debug_log(_T("SEEK COMPLETED to SECTOR %d"), next_seek_lba);
1979                 stop_time_out();
1980                 command_execute_phase = false;
1981                 status_accept(1, 0, 0, false, true); // Say reply. Force to interrupt.
1982                 break;
1983         case EVENT_CDROM_TIMEOUT:  // CDC TIMEOUT (mostly READ BUFFER OVERRUN)
1984                 event_time_out = -1;
1985                 status_time_out(false);
1986                 cdrom_debug_log(_T("READ TIME OUT"));
1987                 break;
1988         case EVENT_CDROM_READ_PRE_SEEK:
1989                 event_seek = -1;
1990                 current_track = get_track(next_seek_lba);
1991                 read_sector = next_seek_lba;
1992                 set_subq(next_seek_lba);
1993                 status_seek = false;
1994                 if((read_length > 0) && (current_track > 0) && (current_track < track_num)) {
1995                         // OK, NEXT
1996                         event_callback(EVENT_CDROM_READY_TO_READ, 1);
1997                 } else {
1998                         status_illegal_lba(0, TOWNS_CD_ABEND_PARAMETER_ERROR, 0, 0); // OK?
1999                 }
2000                 break;
2001         case EVENT_CDROM_READY_TO_READ: // SEEK TO TARGET LBA FOR READING (A) SECTOR(S)
2002                 event_next_sector = -1;
2003                 //read_pos = 0;
2004                 status_seek = false;
2005                 // ToDo: Prefetch 20201116
2006                 if(read_length > 0) {
2007                         bool stat = false;
2008                         //status_seek = true;
2009 //                      cdrom_debug_log(_T("READ DATA SIZE=%d BUFFER COUNT=%d"), logical_block_size(), databuffer->count());
2010                         /// Below has already resolved! Issue of DMAC.20201114 K.O
2011                         // Note: Still error with reading D000h at TownsOS v1.1L30.
2012                         // Maybe data has changed to 1Fh from 8Eh.
2013                         /// 20200926 K.O
2014                         // ToDo: Prefetch Sectors.
2015                         int logical_size = logical_block_size();
2016                         //if(databuffer->left() < logical_size) {
2017                         if(!(databuffer->empty())) { // ToDO: CACHING.
2018                                 // BE RETRY WHEN BUFFER FULL.
2019                                 register_event(this, EVENT_CDROM_READY_TO_READ,
2020                                                    (1.0e6 / ((double)transfer_speed * 150.0e3)) *
2021                                                    8.0,
2022                                                    false,
2023                                                    &event_next_sector);
2024                                 break;
2025                         }
2026                         set_subq(read_sector);
2027                         stat = read_buffer(1);
2028                         //stop_time_out();
2029                         if(stat) {
2030                                 // Note: EMULATE NONE BUFFER, move belows from EVENT_CDROM_NEXT_SECTOR. 20230531 K.O
2031                                 //status_data_ready(true);
2032                                 //set_dma_intr(true);
2033                                 register_event(this, EVENT_CDROM_NEXT_SECTOR,
2034                                                            (1.0e6 / ((double)transfer_speed * 150.0e3)) *
2035                                                            (double)logical_size *
2036                                                            1.0, // OK?
2037                                                            false, &event_next_sector);
2038                                 stop_time_out();
2039                         }
2040                 }
2041                 break;
2042         case EVENT_CDROM_NEXT_SECTOR:  // READY TO READ (A) NEXT SECTOR(S).
2043                 event_next_sector = -1;
2044                 // BIOS FDDFCh(0FC0h:01FCh)-
2045                 status_seek = false;
2046                 // Workaround for dma_interrupt hasn't cleared.
2047                 // This is from Tsugaru, commit 95afde8c, "Support CD-ROM CPU Data Transfer." .
2048                 status_data_ready(false);
2049                 start_time_out();
2050                 if(read_length > 0) {
2051                         status_seek = true;
2052                         int physical_size = physical_block_size();
2053                         int l = physical_size - logical_block_size();
2054                         if(l <= 2) l = 1;
2055                         register_event(this, EVENT_CDROM_READY_TO_READ,
2056                                                    (1.0e6 / ((double)transfer_speed * 150.0e3)) *
2057                                                    (double)l,
2058                                                    false,
2059                                                    &event_next_sector);
2060                 }
2061                 break;
2062         case EVENT_CDROM_DELAY_START_DRQ:  // DELAY START DRQ
2063                 do_drq();  // First, may (sould) delay from rise up.
2064                 break;
2065         default:
2066                 // ToDo: Another events.
2067                 //SCSI_DEV::event_callback(event_id, err);
2068                 break;
2069         }
2070 }
2071
2072 int TOWNS_CDROM::read_sectors_image(int sectors, uint32_t& transferred_bytes)
2073 {
2074
2075         cdimage_buffer_t tmpbuf;
2076         size_t _read_size;              //!< read size from image file.
2077         size_t _transfer_size;  //!< transfer size to data buffer.
2078         size_t _offset = sizeof(cd_data_head_t); //!< Data offset from head of sector.
2079
2080         uint8_t* startp;
2081         uint8_t* datap;
2082
2083         transferred_bytes = 0;
2084
2085         switch(read_mode) {
2086         case CDROM_READ_MODE1:
2087                 _transfer_size = 2048;
2088                 if(is_iso) {
2089                         _read_size = 2048;
2090                         startp = &(tmpbuf.mode1.data[0]);
2091                 } else {
2092                         _read_size = 2352;
2093                         startp = (uint8_t*)(&tmpbuf);
2094                 }
2095                 datap = &(tmpbuf.mode1.data[0]);
2096                 break;
2097         case CDROM_READ_MODE2:
2098                 _transfer_size = 2336;
2099                 if(is_iso) {
2100                         _read_size = 2336;
2101                         startp = &(tmpbuf.mode2.data[0]);
2102                 } else {
2103                         _read_size = 2352;
2104                         startp = (uint8_t*)(&tmpbuf);
2105                 }
2106                 datap = &(tmpbuf.mode2.data[0]);
2107                 break;
2108         case CDROM_READ_RAW:
2109         case CDROM_READ_AUDIO:
2110                 _offset = 0;
2111                 _read_size = 2352;
2112                 _transfer_size = 2352;
2113                 startp = (uint8_t*)(&tmpbuf);
2114                 datap = (uint8_t*)(&tmpbuf);
2115                 break;
2116         default:
2117                 // ToDo: Implement for unexpected type.
2118                 return -1; // None sectors.
2119                 break;
2120         }
2121         int seccount = 0;
2122         while(sectors > 0) {
2123                 //cdrom_debug_log(_T("TRY TO READ SECTOR:LBA=%d"), read_sector);
2124                 memset(&tmpbuf, 0x00, sizeof(tmpbuf));
2125                 int _trk = check_cdda_track_boundary(read_sector);
2126                 if(_trk <= 0) { // END
2127                         status_illegal_lba(0, 0x00, 0x00, 0x00);
2128                         return seccount;
2129                 }
2130                 if(_trk != current_track) { // END
2131                         get_track_by_track_num(_trk);
2132                 }
2133                 if(!(seek_relative_frame_in_image(read_sector))) {
2134                         status_illegal_lba(0, 0x00, 0x00, 0x00);
2135                         return seccount;
2136                 }
2137                 // Phase 1: Check whether buffer remains.
2138                 // Phase 2: Read data from image.
2139                 if(!(fio_img->IsOpened())) {
2140                         status_illegal_lba(0, 0x00, 0x00, 0x00); //<! OK? Maybe read error.
2141                         return seccount;
2142                 }
2143                 // Read data from Image, maybe includes (or doed not include) header and footer.
2144                 if(fio_img->Fread(startp, _read_size, 1) != 1) {
2145                         status_illegal_lba(0, 0x00, 0x00, 0x00);
2146                         return seccount;
2147                 }
2148                 // ToDo: Make pseudo header for ISO images.
2149                 // ToDo: Read or Make sub-channel field.
2150
2151                 // Phase 3: Transfer main data to buffers.
2152                 __UNLIKELY_IF(read_length < _transfer_size) {
2153                         // Buffer over flow
2154                         status_illegal_lba(0, 0x00, 0x00, 0x00);
2155                         return seccount;
2156                 }
2157                 uint32_t tbytes_bak = transferred_bytes;
2158                 int rlen_bak = read_length;
2159
2160                 for(int i = 0; i < _transfer_size; i++) {
2161                         __UNLIKELY_IF(databuffer->full()) {
2162                                 // Buffer over flow
2163                                 // ToDo: Re-Scheduling data transfer.
2164                                 access = false;
2165                                 transferred_bytes = tbytes_bak;
2166                                 read_length = rlen_bak;
2167                                 int _dummy;
2168                                 for(int j = 0; j < i; j++) {
2169                                         _dummy = databuffer->read();
2170                                 }
2171                                 if(!(seek_relative_frame_in_image(read_sector))) {
2172                                         // Try to restore before sector.
2173                                         status_illegal_lba(0, 0x00, 0x00, 0x00);
2174                                 }
2175                                 return seccount;
2176                         }
2177                         write_a_byte(datap[i]);
2178                         transferred_bytes++;
2179                         read_length--;
2180                 }
2181                 read_sector++; // ToDo: Check boundary.
2182                 seccount++;
2183                 sectors--;
2184         }
2185         return seccount; // OK.
2186 }
2187
2188 bool TOWNS_CDROM::read_buffer(int sectors)
2189 {
2190         if(status_media_changed_or_not_ready(false)) {
2191                 // @note ToDo: Make status interrupted.
2192                 access = false;
2193                 return false;
2194         }
2195
2196         uint32_t nbytes; // transferred_bytes
2197         int rsectors = read_sectors_image(sectors, nbytes);
2198         if(rsectors > 0) {
2199                 access = true;
2200         } else {
2201                 access = false;
2202         }
2203         if(rsectors != sectors) {
2204                 // ToDo: Partly reading error.
2205                 return false;
2206         } else {
2207                 return true;
2208         }
2209 }
2210
2211 int TOWNS_CDROM::dequeue_audio_data(pair16_t& left, pair16_t& right)
2212 {
2213         uint8_t data[4];
2214         if(databuffer->count() < 4) {
2215                 left.w = 0;
2216                 right.w = 0;
2217                 return 0;
2218         }
2219
2220         for(int i = 0; i < 4; i++) {
2221                 data[i] = (uint8_t)(databuffer->read() & 0xff);
2222         }
2223         __UNLIKELY_IF(config.swap_audio_byteorder[0]) {
2224                 left.read_2bytes_be_from(&(data[0]));
2225                 right.read_2bytes_be_from(&(data[2]));
2226         } else {
2227                 left.read_2bytes_le_from(&(data[0]));
2228                 right.read_2bytes_le_from(&(data[2]));
2229         }
2230         return 4;
2231 }
2232
2233 void TOWNS_CDROM::read_a_cdda_sample()
2234 {
2235         __UNLIKELY_IF(event_cdda_delay_play > -1) {
2236                 // Post process
2237                 if(((cdda_buffer_ptr % 2352) == 0) && (cdda_status == CDDA_PLAYING)) {
2238                         //set_subq(cdda_start_frame);
2239 //                      return; // WAIT for SEEK COMPLETED
2240                 }
2241                 return; // WAIT for SEEK COMPLETED
2242         }
2243         // read 16bit 2ch samples in the cd-da buffer, called 44100 times/sec
2244         pair16_t sample_l, sample_r;
2245         int rlen = dequeue_audio_data(sample_l, sample_r);
2246         #if 0
2247         __UNLIKELY_IF(rlen != 4) {
2248                 // May recover buffer.
2249                 if(rlen <= 0) return; // None dequeued.
2250                 // ToDo: Recover queue.
2251                 return; //
2252         }
2253         #endif
2254         cdda_sample_l = sample_l.sw;
2255         cdda_sample_r = sample_r.sw;
2256         cdda_buffer_ptr = cdda_buffer_ptr + 4;
2257         bool force_seek = false;
2258         __UNLIKELY_IF((cdda_buffer_ptr % 2352) == 0) {
2259                 // one frame finished
2260                 set_subq(cdda_playing_frame); // First
2261                 cdda_playing_frame++;
2262                 cdda_buffer_ptr = 0;
2263
2264                 __UNLIKELY_IF(cdda_playing_frame > cdda_end_frame) {
2265                         clear_event(this, event_cdda);
2266                         if(cdda_repeat_count < 0) {
2267                                 // Infinity Loop (from Towns Linux v2.2.26)
2268                                 force_seek = true;
2269                         } else if(cdda_repeat_count == 0) {
2270                                 status_seek = false;
2271                                 set_cdda_status(CDDA_ENDED);
2272                                 access = false;
2273                                 return;
2274                         } else {
2275                                 force_seek = true;
2276                                 cdda_repeat_count--;
2277                                 if(cdda_repeat_count == 0) {
2278                                         set_cdda_status(CDDA_ENDED);
2279                                         access = false;
2280                                         status_seek = false;
2281                                         return;
2282                                 }
2283                         }
2284                 }
2285 /*              int _ntrk =     _ntrk = check_cdda_track_boundary(read_sector);
2286                 __UNLIKELY_IF((_ntrk != current_track) && (_ntrk < track_num) && (_ntrk > 0)) {
2287                         current_track = get_track(read_sector);
2288                         seek_relative_frame_in_image(read_sector);
2289                 } else */if(force_seek) {
2290                         double usec = get_seek_time(cdda_start_frame);
2291                         if(usec < 10.0) usec = 10.0;
2292                         force_register_event(this, EVENT_CDDA_REPEAT, usec, false, event_cdda_delay_play);
2293                         status_seek = true;
2294                         return;
2295                 }
2296                 #if 0
2297                 if(databuffer->count() <= sizeof(cd_audio_sector_t)) {
2298                         // Kick prefetch
2299                         //(event_next_sector < 0) {
2300                                 // TMP: prefetch 2 sectors
2301                                 prefetch_audio_sectors(2);
2302                         //
2303                 }
2304                 #else
2305                 prefetch_audio_sectors(1);
2306                 #endif
2307         }
2308 }
2309
2310 // -1 = End of sector.
2311 int TOWNS_CDROM::prefetch_audio_sectors(int sectors)
2312 {
2313         if(sectors < 1) {
2314                 return -1;
2315         }
2316         if(status_media_changed_or_not_ready(false)) {
2317                 // @note ToDo: Make status interrupted.
2318                 return -1;
2319         }
2320         uint8_t tmpbuf[sectors * 2448 + 8];
2321         if((read_sector > cdda_end_frame) || (read_sector >= max_logical_block)) {
2322                 return 0; // OK?
2323         }
2324         if((current_track >= track_num) || (current_track <= 0)) {
2325                 return 0;
2326         }
2327         int track = get_track_noop(read_sector);
2328         if(track != current_track) {
2329                 // BEYOND BOUNDARY OF TRACK.
2330                 if((track >= track_num) || (track <= 0)) {
2331                         status_parameter_error(false); // OK?
2332                         return 0;
2333                 }
2334                 if(!(toc_table[track].is_audio)) {
2335                         status_parameter_error(false); // OK?
2336                         return 0;
2337                 }
2338                 current_track = get_track(read_sector);
2339                 seek_relative_frame_in_image(read_sector);
2340         }
2341         if((read_sector + sectors) > cdda_end_frame) {
2342                 sectors = cdda_end_frame - read_sector + 1;
2343         }
2344         if((read_sector + sectors) > max_logical_block) {
2345                 sectors = max_logical_block - read_sector;
2346         }
2347         #if 0
2348         __UNLIKELY_IF(databuffer->left() < read_length) {
2349                 int tl = databuffer->left();
2350                 if(tl < sizeof(cd_audio_sector_t)) return 0; // Pending
2351                 int _s = tl / sizeof(cd_audio_sector_t);
2352                 if(_s < 1) return 0; // Pending
2353                 if(sectors > _s) {
2354                         sectors = _s;
2355                 }
2356         }
2357         if(get_track_noop(read_sector + sectors) != current_track) {
2358                 sectors = toc_table[current_track].index0 - read_sector;
2359         }
2360         #endif
2361         if(sectors <= 0) {
2362                 return 0; // NOP.
2363         }
2364         read_length = sectors * sizeof(cd_audio_sector_t); // Hack.
2365         read_mode = CDROM_READ_AUDIO;
2366
2367         uint32_t nbytes; // transferred_bytes
2368         int _sectors = 0;
2369         while(sectors > 0) {
2370                 int rsectors = read_sectors_image(sectors, nbytes);
2371                 //cdrom_debug_log(_T("READ AUDIO SECTOR(s) LBA=%d SECTORS=%d -> %d bytes=%d"),
2372                 //                              read_sector, sectors, rsectors, nbytes);
2373                 if(rsectors <= 0) {
2374                         // Error
2375                         //set_cdda_status(CDDA_ENDED);
2376                         access = false;
2377                         return _sectors; // OK?
2378                 }
2379                 sectors -= rsectors;
2380                 _sectors += rsectors;
2381         }
2382         return _sectors;
2383 }
2384
2385 void TOWNS_CDROM::set_cdda_status(uint8_t status)
2386 {
2387         if(status == CDDA_PLAYING) {
2388                 if(mix_loop_num == 0) {
2389                         if(event_cdda < 0) {
2390                                 register_event(this, EVENT_CDDA, 1.0e6 / 44100.0, true, &event_cdda);
2391                         }
2392                 }
2393                 if(cdda_status != CDDA_PLAYING) {
2394                         //// Notify to release bus.
2395                         write_mcuint_signals(false);
2396                         if((cdda_status == CDDA_OFF) || (cdda_status == CDDA_ENDED)) {
2397                                 //get_track_by_track_num(current_track); // Re-Play
2398                                 int track = get_track(cdda_start_frame);
2399                                 if((track > 0) && (track < track_num)) {
2400                                         cdda_playing_frame = cdda_start_frame;
2401                                         read_sector = cdda_playing_frame;
2402                                         current_track = track;
2403                                         seek_relative_frame_in_image(cdda_playing_frame);
2404                                         cdda_stopped = false;
2405                                 } else {
2406                                         // ERROR
2407                                         current_track = get_track(0);
2408                                         cdda_playing_frame = 0;
2409                                         read_sector = 0;
2410                                         cdda_start_frame = 0;
2411                                         cdda_end_frame = 0;
2412                                         cdda_stopped = true;
2413                                 }
2414                                 cdda_buffer_ptr = 0;
2415                                 access = false;
2416                         } else if(cdda_status == CDDA_PAUSED) {
2417                                 // Unpause
2418                                 //access = true;
2419                                 cdda_stopped = false;
2420                         } else {
2421                                 cdda_stopped = false;
2422                         }
2423                         touch_sound();
2424                         set_realtime_render(this, true);
2425                         const _TCHAR *pp = get_cdda_status_name(cdda_status);
2426                         cdrom_debug_log(_T("Play CDDA from %s.\n"), pp);
2427                 }
2428         } else {
2429                 //clear_event(this, event_cdda);
2430 //              if((cdda_status == CDDA_PLAYING) || (cdda_status == CDDA_ENDED)) {
2431                 if(cdda_status != status) {
2432                         // Notify to release bus.
2433                         write_mcuint_signals(false);
2434                         if(status == CDDA_OFF) {
2435                                 databuffer->clear();
2436                                 cdda_buffer_ptr = 0;
2437                                 cdda_repeat_count = -1; // OK?
2438                                 #if 1
2439                                 if((current_track <= 0) || (current_track >= track_num)) {
2440                                         current_track = get_track(0);
2441                                         read_sector = 0;
2442                                         cdda_start_frame = 0;
2443                                         cdda_end_frame = 0;
2444                                         cdda_playing_frame = 0;
2445                                 } else {
2446                                         read_sector = toc_table[current_track].index0;
2447                                         cdda_start_frame = read_sector;
2448                                         cdda_playing_frame = read_sector;
2449                                         cdda_end_frame = toc_table[current_track + 1].index0 - 1; // ToDo.
2450                                 }
2451                                 #else
2452                                 read_sector = 0;
2453                                 get_track_by_track_num(0);
2454                                 #endif
2455                                 cdda_stopped = true;
2456                         }
2457                         touch_sound();
2458                         set_realtime_render(this, false);
2459                         const _TCHAR *sp = get_cdda_status_name(status);
2460                         const _TCHAR *pp = get_cdda_status_name(cdda_status);
2461                         cdrom_debug_log(_T("Change CDDA status: %s->%s"), pp, sp);
2462                 }
2463         }
2464         cdda_status = status;
2465 }
2466
2467
2468 bool TOWNS_CDROM::is_device_ready()
2469 {
2470         return mounted();
2471 }
2472
2473
2474 void TOWNS_CDROM::get_track_by_track_num(int track)
2475 {
2476         if((track <= 0) || (track >= track_num)) {
2477                 if(is_cue) {
2478                         if(fio_img->IsOpened()) fio_img->Fclose();
2479                 }
2480                 current_track = 0;
2481                 return;
2482         }
2483         if(is_cue) {
2484                 // ToDo: Apply audio with some codecs.
2485                 if((current_track != track) || !(fio_img->IsOpened())){
2486                         if(fio_img->IsOpened()) {
2487                                 fio_img->Fclose();
2488                         }
2489                         cdrom_debug_log(_T("LOAD TRK #%02d from %s\n"), track, track_data_path[track - 1]);
2490
2491                         if((track > 0) && (track < 100) && (track < track_num)) {
2492                                 if((strlen(track_data_path[track - 1]) <= 0) ||
2493                                    !(fio_img->Fopen(track_data_path[track - 1], FILEIO_READ_BINARY))) {
2494                                         track = 0;
2495                                 }
2496                         } else {
2497                                 track = 0;
2498                         }
2499                 }
2500         }
2501         current_track = track;
2502 }
2503
2504 // Detect only track num.
2505 int TOWNS_CDROM::get_track_noop(uint32_t lba)
2506 {
2507         int track = 0;
2508         for(int i = 0; i < track_num; i++) {
2509                 if(lba >= toc_table[i].index0) {
2510                         track = i;
2511                 } else {
2512                         break;
2513                 }
2514         }
2515         return track;
2516 }
2517
2518 int TOWNS_CDROM::get_track(uint32_t lba)
2519 {
2520         int track = 0;
2521         track = get_track_noop(lba);
2522         get_track_by_track_num(track);
2523         return track;
2524 }
2525
2526 double TOWNS_CDROM::get_seek_time(uint32_t lba)
2527 {
2528         uint32_t cur_lba = get_image_cur_position();
2529         int distance;
2530         if(lba > max_logical_block) lba = max_logical_block;
2531         if(lba > cur_lba) {
2532                 distance = lba - cur_lba;
2533         } else {
2534                 distance = cur_lba - lba;
2535         }
2536         if((cur_lba < 150) && (lba < 150)) {
2537                 // Seek not effective.
2538                 distance = 0;
2539         }
2540         double _seek = (double)distance / 333000.0 ; // 333000: sectors in media
2541         _seek = 400.0e3 *  _seek;
2542         return _seek;
2543 }
2544
2545 uint32_t TOWNS_CDROM::lba_to_msf(uint32_t lba)
2546 {
2547         uint8_t m = lba / (60 * 75);
2548         lba -= m * (60 * 75);
2549         uint8_t s = lba / 75;
2550         uint8_t f = lba % 75;
2551
2552         return ((m / 10) << 20) | ((m % 10) << 16) | ((s / 10) << 12) | ((s % 10) << 8) | ((f / 10) << 4) | ((f % 10) << 0);
2553 }
2554
2555 uint32_t TOWNS_CDROM::get_image_cur_position()
2556 {
2557         uint32_t frame = 0;
2558         int track = current_track;
2559         if(is_device_ready()) {
2560                 if(fio_img->IsOpened()) {
2561                         uint32_t cur_position = (uint32_t)(fio_img->Ftell());
2562                         frame = (cur_position / ((is_iso) ? 2048 : physical_block_size()));
2563                         if(is_cue) {
2564                                 frame = frame + toc_table[track].lba_offset;
2565                         }
2566                 } else {
2567                         frame = 0;
2568                 }
2569         }
2570         return frame;
2571 }
2572 uint32_t TOWNS_CDROM::lba_to_msf_alt(uint32_t lba)
2573 {
2574         uint32_t ret = 0;
2575         ret |= ((lba / (60 * 75)) & 0xff) << 16;
2576         ret |= (((lba / 75) % 60) & 0xff) <<  8;
2577         ret |= ((lba % 75)        & 0xff) <<  0;
2578         return ret;
2579 }
2580
2581 void TOWNS_CDROM::pause_cdda_from_cmd()
2582 {
2583         set_cdda_status(CDDA_PAUSED);
2584         /*!
2585          * @note This may solve halt incident of Kyukyoku Tiger, but something are wrong.
2586          * @note 20201113 K.O
2587          */
2588         set_subq(cdda_playing_frame); // First
2589         if(!(status_media_changed_or_not_ready(false))) {
2590                 set_status(req_status, 1, TOWNS_CD_STATUS_ACCEPT, TOWNS_CD_ACCEPT_CDDA_PAUSED, 0x00, 0x00, true);
2591         }
2592 }
2593
2594 void TOWNS_CDROM::unpause_cdda_from_cmd()
2595 {
2596         set_cdda_status(CDDA_PLAYING);
2597         /*!
2598          * @note This may solve halt incident of Kyukyoku Tiger, but something are wrong.
2599          * @note 20201113 K.O
2600          */
2601         set_subq(cdda_playing_frame); // First
2602         if(!(status_media_changed_or_not_ready(false))) {
2603                 set_status(req_status, 1, TOWNS_CD_STATUS_ACCEPT, TOWNS_CD_ACCEPT_NOERROR, 0x00, 0x00, true);
2604         }
2605 }
2606
2607 void TOWNS_CDROM::stop_cdda_from_cmd()
2608 {
2609         /// @note Even make additional status even stop.Workaround for RANCEIII.
2610         /// @note - 20201110 K.O
2611         set_cdda_status(CDDA_ENDED);
2612         set_subq(cdda_playing_frame); // First
2613         if(!(status_media_changed_or_not_ready(false))) {
2614                 set_status(req_status, 1, TOWNS_CD_STATUS_ACCEPT, TOWNS_CD_ACCEPT_NOERROR, 0x00, 0x00, true);
2615         }
2616         return;
2617 }
2618
2619
2620 bool TOWNS_CDROM::seek_relative_frame_in_image(uint32_t frame_no)
2621 {
2622         int phys_size = (is_iso) ? 2048 : physical_block_size();
2623         if(frame_no >= toc_table[current_track].lba_offset) {
2624                 if(fio_img->IsOpened()) {
2625                         if(fio_img->Fseek(
2626                                    (frame_no - toc_table[current_track].lba_offset) * phys_size,
2627                                    FILEIO_SEEK_SET) != 0) {
2628                                 return false;
2629                         }
2630                         return true;
2631                 }
2632         }
2633         return false;
2634 }
2635
2636
2637 int TOWNS_CDROM::check_cdda_track_boundary(uint32_t frame_no)
2638 {
2639         if((frame_no >= toc_table[current_track + 1].index0) ||
2640            (frame_no < toc_table[current_track].index0)) {
2641                 int trk = get_track_noop(frame_no);
2642                 if((trk <= 0) || (trk >= track_num)) {
2643                         cdrom_debug_log(_T("CDDA: BEYOND OF TRACK BOUNDARY AND TO THE END, FRAME=%d"), frame_no);
2644                         return track_num;
2645                 }
2646                 cdrom_debug_log(_T("CDDA: BEYOND OF TRACK BOUNDARY, FRAME=%d"), frame_no);
2647                 //if(frame_no < toc_table[current_track].index0) {
2648                 //      frame_no = toc_table[current_track].index0;
2649                 //}
2650                 return trk;
2651         }
2652         return current_track;
2653 }
2654
2655 void TOWNS_CDROM::play_cdda_from_cmd()
2656 {
2657         uint8_t m_start      = exec_params[0];
2658         uint8_t s_start      = exec_params[1];
2659         uint8_t f_start      = exec_params[2];
2660         uint8_t m_end        = exec_params[3];
2661         uint8_t s_end        = exec_params[4];
2662         uint8_t f_end        = exec_params[5];
2663         uint8_t is_repeat    = exec_params[6]; // From Towns Linux v1.1/towns_cd.c
2664         uint8_t repeat_count = exec_params[7];
2665
2666         cdda_repeat_count = -1;
2667         uint32_t start_tmp = FROM_BCD(f_start) + (FROM_BCD(s_start) + FROM_BCD(m_start) * 60) * 75;
2668         uint32_t end_tmp = FROM_BCD(f_end)   + (FROM_BCD(s_end)   + FROM_BCD(m_end) * 60) * 75;
2669         /*!
2670          * @note Workaround for command SPAM, i.e. Puyo Puyo.
2671          * @note 20201115 K.O
2672          */
2673         {
2674                 int track;
2675                 track = get_track_noop(start_tmp);
2676                 if(start_tmp >= toc_table[track].pregap) {
2677                         start_tmp -= toc_table[track].pregap;
2678                 }
2679                 if(start_tmp < toc_table[track].index1) {
2680                         start_tmp = toc_table[track].index1; // don't play pregap
2681                 } else if(start_tmp >= max_logical_block) {
2682                         start_tmp = max_logical_block - 1;
2683                 }
2684                 /* if(end_tmp >= toc_table[track + 1].index0) {
2685                         end_tmp = toc_table[track + 1].index0 - 1;
2686                 } else */if(end_tmp >= max_logical_block) {
2687                         end_tmp = max_logical_block - 1;
2688                 } else if(end_tmp == 0) { //! Workaround of Puyo Puyo 20201116 K.O
2689                         end_tmp = toc_table[track + 1].index0 - 1;
2690                 }
2691                 if(cdda_status == CDDA_PLAYING) {
2692                         int track_tmp_s = get_track_noop(start_tmp);
2693                         int track_tmp_e = get_track_noop(end_tmp);
2694                         if((start_tmp == cdda_start_frame) && (end_tmp == cdda_end_frame)) {
2695                                 // Dummy
2696                                 set_status_cddareply(false, 1, 0x00, 0x00);
2697                                 return;
2698                         }
2699                         // Workaround for Puyo Puyo, Interval stage.
2700                         if((track_tmp_s != current_track) || (track_tmp_e != current_track)) {
2701                                 if(cdda_status == CDDA_PLAYING) {
2702                                         set_cdda_status(CDDA_OFF);
2703                                 }
2704                                 if(!(toc_table[track_tmp_s].is_audio)) {
2705                                         // If target LBA is not CDDA, reject command.
2706                                         set_status_cddareply(false, 1, 0x00, 0x00);
2707                                         return;
2708                                 }
2709                         }
2710                 }
2711                 cdda_start_frame = start_tmp;
2712                 cdda_end_frame   = end_tmp;
2713                 // Check target track is *not* audio.
2714                 int track2 = get_track_noop(cdda_start_frame);
2715                 if(!(toc_table[track2].is_audio)) {
2716                         //if(cdda_status == CDDA_PLAYING) {
2717                                 set_cdda_status(CDDA_OFF);
2718                         //}
2719                         status_hardware_error(false); // OK?
2720                         return;
2721                 }
2722                 if(is_repeat == 1) {
2723                         cdda_repeat_count = -1;
2724                 } else {
2725                         // Maybe is_repeat == 9
2726                         cdda_repeat_count = repeat_count;
2727                         cdda_repeat_count++;
2728                 }
2729                 uint32_t cur_lba = get_image_cur_position();
2730                 set_subq(cur_lba);
2731                 //cdda_playing_frame = cdda_start_frame;
2732                 //read_sector = cdda_start_frame;
2733                 status_seek = true;
2734                 //seek_relative_frame_in_image(cdda_playing_frame);
2735                 cdrom_debug_log(_T("PLAY_CDROM TRACK=%d START=%02X:%02X:%02X(%d) END=%02X:%02X:%02X(%d) IS_REPEAT=%d REPEAT_COUNT=%d"),
2736                                           track,
2737                                           m_start, s_start, f_start, cdda_start_frame,
2738                                           m_end, s_end, f_end, cdda_end_frame,
2739                                           is_repeat, repeat_count);
2740                 double usec = get_seek_time(cdda_start_frame);
2741                 //get_track(cdda_playing_frame);
2742                 if(usec < 10.0) usec = 10.0;
2743
2744                 //set_cdda_status(CDDA_PLAYING);
2745                 force_register_event(this, EVENT_CDDA_DELAY_PLAY, usec, false, event_cdda_delay_play);
2746                 return;
2747         }
2748         /*!
2749          * @note This may solve halt incident of Kyukyoku Tiger, but something are wrong.
2750          * @note 20201113 K.O
2751          */
2752         set_status_cddareply(false, 1, 0x00, 0x00);
2753 }
2754
2755 void TOWNS_CDROM::make_bitslice_subc_q(uint8_t *data, int bitwidth)
2756 {
2757         int nbit = 0;
2758         if(bitwidth > (sizeof(subq_buffer) / sizeof(SUBC_t))) {
2759                 bitwidth = (sizeof(subq_buffer) / sizeof(SUBC_t));
2760         } else if(bitwidth < 0) {
2761                 bitwidth = 0;
2762         }
2763         // Set Q field
2764         // Q: IS set SYNC CODE?.
2765         for(int bp = 0; bp < bitwidth; bp++) {
2766                 subq_buffer[bp].bit.Q =
2767                         ((data[nbit >> 3] & (1 << (7 - (nbit & 7)))) != 0) ? 1 : 0;
2768                 nbit++;
2769         }
2770 }
2771
2772 void TOWNS_CDROM::set_subq(uint32_t lba)
2773 {
2774         memset(subq_bytes, 0x00, sizeof(subq_bytes));
2775         if(subq_bitptr < subq_bitwidth) {
2776                 subq_overrun = true;
2777         }
2778         int track = get_track_noop(lba);
2779         if((is_device_ready()) && (track > 0) && (track < track_num)) {
2780                 // create track info
2781                 uint32_t frame;
2782                 uint32_t msf_abs;
2783                 uint32_t msf_rel;
2784                 // ToDo: Process when Foo.sub (for Foo.cue or Foo.ccd), this may be sub-channel data.
2785                 if(toc_table[track].is_audio) { // OK? (or force ERROR) 20181120 K.O
2786                         frame = ((cdda_status == CDDA_OFF) || (cdda_status == CDDA_ENDED)) ? toc_table[track].index0 : lba;
2787                 } else { // Data
2788                         frame = lba;
2789                 }
2790                 if(frame > toc_table[track].index1) {
2791                         msf_rel = lba_to_msf_alt(frame - toc_table[track].index1);
2792                 } else {
2793                         msf_rel = lba_to_msf_alt(0);
2794                 }
2795                 msf_abs = lba_to_msf_alt(frame + 75 * 2); // OK?
2796
2797                 // ToDo: POINT=0xA0-0xA2
2798                 {
2799                         subq_bytes[0] = ((toc_table[track].is_audio) ? 0x40 : 0x00) | 0x01;                     // (CNT << 4) | ADR
2800                         subq_bytes[1] = 0x00;                                                   // TNO
2801                         subq_bytes[2] = TO_BCD(track);                                  // POINT(Track)
2802                         subq_bytes[3] = TO_BCD((msf_abs >> 16) & 0xff); // M (absolute)
2803                         subq_bytes[4] = TO_BCD((msf_abs >> 8) & 0xff);  // S (absolute)
2804                         subq_bytes[5] = TO_BCD((msf_abs >> 0) & 0xff);  // F (absolute)
2805                         subq_bytes[6] = 0x00;                                                   // Zero
2806                         subq_bytes[7] = TO_BCD((msf_rel >> 16) & 0xff); // M (relative)
2807                         subq_bytes[8] = TO_BCD((msf_rel >> 8) & 0xff);  // S (relative)
2808                         subq_bytes[9] = TO_BCD((msf_rel >> 0) & 0xff);  // F (relative)
2809                 }
2810         }
2811         // Post Process1: Calculate CRC16
2812         uint16_t crc = calc_subc_crc16(subq_bytes, 10, 0xffff); // OK?
2813         subq_bytes[10] = (crc >> 8) & 0xff;
2814         subq_bytes[11] = (crc >> 0) & 0xff;
2815         // Post process 2: push bytes to Bit slice
2816         memset(subq_buffer, 0x00, sizeof(subq_buffer));
2817         subq_bitptr = 0;
2818         subq_bitwidth = 96;
2819         // ToDo: P field;
2820         make_bitslice_subc_q(subq_bytes, 96);
2821         // ToDo: R-W field (a.k.a. CD-TEXT/CD-G);
2822 //      mcu_ready = true;
2823         return;
2824 }
2825
2826 uint8_t TOWNS_CDROM::get_subq_status()
2827 {
2828         uint8_t val = 0x00;
2829         val = val | ((subq_bitwidth > 0) ? 0x01 : 0x00);
2830         val = val | ((subq_overrun) ? 0x02 : 0x00);
2831         return val;
2832 }
2833
2834 uint8_t TOWNS_CDROM::read_subq()
2835 {
2836         uint8_t val = 0x00;
2837         if(subq_bitptr < subq_bitwidth) {
2838                 val = subq_buffer[subq_bitptr].byte;
2839                 subq_bitptr++;
2840         }
2841         return val;
2842 }
2843
2844 int TOWNS_CDROM::get_frames_from_msf(const char *s)
2845 {
2846         const char *ptr = s;
2847         int frames[3] = {0};
2848         int index = 0;
2849
2850         while(1) {
2851                 if(*ptr >= '0' && *ptr <= '9') {
2852                         frames[index] = frames[index] * 10 + (*ptr - '0');
2853                 } else if(*ptr == ':') {
2854                         if(++index == 3) {
2855                                 // abnormal data
2856                                 break;
2857                         }
2858                 } else if(*ptr == '\r' || *ptr == '\n' || *ptr == '\0') {
2859                         // end of line
2860                         break;
2861                 }
2862                 ptr++;
2863         }
2864         return (frames[0] * 60 + frames[1]) * 75 + frames[2]; // 75frames/sec
2865 }
2866
2867 int64_t TOWNS_CDROM::hexatoi(const char *s)
2868 {
2869         const char *ptr = s;
2870         int64_t value = 0;
2871
2872         while(1) {
2873                 if(*ptr >= '0' && *ptr <= '9') {
2874                         value = value * 16 + (*ptr - '0');
2875                 } else if(*ptr >= 'a' && *ptr <= 'f') {
2876                         value = value * 16 + (*ptr - 'a' + 10);
2877                 } else if(*ptr >= 'A' && *ptr <= 'F') {
2878                         value = value * 16 + (*ptr - 'A' + 10);
2879                 } else if(*ptr == '\r' || *ptr == '\n' || *ptr == '\0') {
2880                         break;
2881                 }
2882                 ptr++;
2883         }
2884         return value;
2885 }
2886
2887 #include <string>
2888 #include <map>
2889
2890 int64_t TOWNS_CDROM::string_to_numeric(std::string s)
2891 {
2892         int64_t _ret = 0;
2893         if(!(s.empty())) {
2894                 std::string head;
2895                 try {
2896                         head = s.substr(0, 2);
2897                 } catch (std::out_of_range &e) {
2898                         head = s;
2899                 }
2900                 std::transform(head.begin(), head.end(), head.begin(),
2901                                            [](unsigned char c) -> unsigned char{ return std::toupper(c); });
2902
2903                 if(head == "0X") {
2904                         std::string __val;
2905                         try {
2906                                 __val = s.substr(2, s.size());
2907                         } catch (std::out_of_range &e) {
2908                                 __val = "";
2909                         }
2910                         _ret = hexatoi(__val.c_str());
2911                 } else {
2912                         _ret = atoll(s.c_str());
2913                 }
2914
2915         }
2916         return _ret;
2917 }
2918
2919 void TOWNS_CDROM::open(const _TCHAR* file_path)
2920 {
2921         open_from_cmd(file_path);
2922 }
2923
2924 void TOWNS_CDROM::open_from_cmd(const _TCHAR* file_path)
2925 {
2926         _TCHAR img_file_path[_MAX_PATH] = {0};
2927         memset(img_file_path_bak, 0x00, sizeof(img_file_path_bak));
2928
2929         close_from_cmd();
2930         access = false;
2931
2932         if(check_file_extension(file_path, _T(".cue"))) {
2933                 is_cue = false;
2934                 current_track = 0;
2935                 if(open_cue_file(file_path)) {
2936                         strncpy(img_file_path_bak, file_path, _MAX_PATH - 1);
2937                 }
2938         } else if(check_file_extension(file_path, _T(".iso"))) {
2939                 is_cue = false;
2940                 current_track = 0;
2941                 if(open_iso_file(file_path)) {
2942                         strncpy(img_file_path, file_path, _MAX_PATH - 1);
2943                         strncpy(img_file_path_bak, file_path, _MAX_PATH - 1);
2944                 }
2945                 if(fio_img->Fopen(img_file_path, FILEIO_READ_BINARY)) {
2946                         is_cue = false;
2947                         current_track = 0;
2948                         is_iso = true;
2949                 }
2950         } else if(check_file_extension(file_path, _T(".ccd"))) {
2951                 // get image file name
2952                 if(open_ccd_file(file_path, img_file_path)) {
2953                         strncpy(img_file_path_bak, img_file_path, _MAX_PATH - 1);
2954 //                      strncpy(img_file_path_bak, file_path, _MAX_PATH - 1);
2955                 }
2956         }
2957         if(mounted()) {
2958                 if(media_ejected) {
2959                         media_changed = true;
2960                         media_ejected = false;
2961                         // Temporally answer value.
2962                         // TOWNS_CD_STATUS_DOOR_CLOSE_DONE ?
2963                 }
2964                 /* if(__SCSI_DEBUG_LOG)*/ {
2965                         for(int i = 1; i < track_num + 1; i++) {
2966                                 uint32_t idx0_msf = lba_to_msf(toc_table[i].index0);
2967                                 uint32_t idx1_msf = lba_to_msf(toc_table[i].index1);
2968                                 uint32_t pgap_msf = lba_to_msf(toc_table[i].pregap);
2969                                 cdrom_debug_log(_T("Track%02d: Index0=%02x:%02x:%02x Index1=%02x:%02x:%02x PreGap=%02x:%02x:%02x\n"), i,
2970                                           (idx0_msf >> 16) & 0xff, (idx0_msf >> 8) & 0xff, idx0_msf & 0xff,
2971                                           (idx1_msf >> 16) & 0xff, (idx1_msf >> 8) & 0xff, idx1_msf & 0xff,
2972                                           (pgap_msf >> 16) & 0xff, (pgap_msf >> 8) & 0xff, pgap_msf & 0xff);
2973                         }
2974                 }
2975         }
2976 }
2977
2978 void TOWNS_CDROM::close()
2979 {
2980         close_from_cmd();
2981 }
2982
2983 void TOWNS_CDROM::close_from_cmd()
2984 {
2985         bool _b = mounted();
2986         if(_b) {
2987                 media_ejected = true;
2988         }
2989         if(fio_img->IsOpened()) {
2990                 fio_img->Fclose();
2991         }
2992         is_cue = false;
2993         is_iso = false;
2994         memset(toc_table, 0, sizeof(toc_table));
2995         memset(img_file_path_bak, 0x00, sizeof(img_file_path_bak));
2996
2997         access = false;
2998         status_seek = false;
2999         media_changed = false;
3000
3001         read_mode = CDROM_READ_NONE;
3002         track_num = 0;
3003
3004         current_track = 0;
3005         stat_track = 0;
3006         set_subq(0);
3007
3008         next_seek_lba = 0;
3009         read_length = 0;
3010         read_sector = 0;
3011         databuffer->clear();
3012
3013         cdda_start_frame = 0;
3014         cdda_end_frame = 150;
3015         cdda_playing_frame = 0;
3016         cdda_buffer_ptr = 0;
3017
3018         cdda_repeat_count = -1; // OK?
3019
3020         cdda_stopped = true;
3021         cdda_status = CDDA_OFF;
3022
3023         touch_sound();
3024         set_realtime_render(this, false);
3025
3026         if(_b) {
3027                 if(command_execute_phase) {
3028                         command_execute_phase = false;
3029                         // Temporally answer value.
3030                         // TOWNS_CD_STATUS_DOOR_OPEN_DONE ?
3031                         set_status_immediate(req_status, false, 0,
3032                                                                  TOWNS_CD_STATUS_CMD_ABEND,
3033                                                                  TOWNS_CD_ABEND_DRIVE_NOT_READY, 0, 0);
3034                 }
3035         }
3036 }
3037
3038 bool TOWNS_CDROM::mounted()
3039 {
3040         __LIKELY_IF((is_cue) || (fio_img->IsOpened())) {
3041                 __UNLIKELY_IF(track_num <= 0) {
3042                         return false;
3043                 }
3044                 return true;
3045         }
3046         return false;
3047 }
3048
3049 bool TOWNS_CDROM::accessed()
3050 {
3051         bool value = access;
3052         access = false;
3053         return value;
3054 }
3055
3056 void TOWNS_CDROM::mix(int32_t* buffer, int cnt)
3057 {
3058         if(cdda_status == CDDA_PLAYING) {
3059                 if(mix_loop_num != 0) {
3060                         int tmp_l = 0, tmp_r = 0;
3061                         for(int i = 0; i < mix_loop_num; i++) {
3062                                 event_callback(EVENT_CDDA, 0);
3063                                 tmp_l += cdda_sample_l;
3064                                 tmp_r += cdda_sample_r;
3065                         }
3066                         cdda_sample_l = tmp_l / mix_loop_num;
3067                         cdda_sample_r = tmp_r / mix_loop_num;
3068                 }
3069 //              int32_t val_l = apply_volume(apply_volume(cdda_sample_l, volume_m), volume_l);
3070 //              int32_t val_r = apply_volume(apply_volume(cdda_sample_r, volume_m), volume_r);
3071                 int32_t val_l = (mute_left) ? 0 : apply_volume(cdda_sample_l, volume_l);
3072                 int32_t val_r = (mute_right) ? 0 : apply_volume(cdda_sample_r, volume_r);
3073
3074                 for(int i = 0; i < cnt; i++) {
3075                         *buffer++ += val_l; // L
3076                         *buffer++ += val_r; // R
3077                 }
3078         }
3079 }
3080
3081 void TOWNS_CDROM::set_volume(int ch, int decibel_l, int decibel_r)
3082 {
3083         _decibel_l = decibel_l;
3084         _decibel_r = decibel_r;
3085         volume_l = decibel_to_volume(_decibel_l + 6.0);
3086         volume_r = decibel_to_volume(_decibel_r + 6.0);
3087 }
3088
3089 void TOWNS_CDROM::get_volume(int ch, int& decibel_l, int& decibel_r)
3090 {
3091         decibel_l = _decibel_l;
3092         decibel_r = _decibel_r;
3093 //      decibel_l = volume_l;
3094 //      decibel_r = volume_r;
3095 }
3096
3097 uint32_t TOWNS_CDROM::read_io16(uint32_t addr)
3098 {
3099         if((addr & 0x0e) == 0x04) {
3100                 if((pio_transfer_phase) /*|| (dma_transfer_phase) */) {
3101                         int dummywait;
3102                         pair16_t n;
3103                         n.b.h = 0x00;
3104                     n.b.l = read_dma_io8w(0, &dummywait);
3105                         return n.w;
3106                 }
3107                 return 0x0000;
3108         } else {
3109                 return read_io8(addr);
3110         }
3111 }
3112
3113 uint32_t TOWNS_CDROM::read_io8(uint32_t addr)
3114 {
3115         /*
3116          * 04C0h : Master status
3117          * 04C2h : CDC status
3118          * 04C4h : DATA
3119          * 04CCh : SUBQ CODE
3120          * 04CDh : SUBQ STATUS
3121          */
3122         uint32_t val = 0xff;
3123         switch(addr & 0x0f) {
3124         case 0x00:
3125                 val = 0x00;
3126                 val = val | ((mcu_intr)                                 ? 0x80 : 0x00);
3127                 val = val | ((dma_intr)                                 ? 0x40 : 0x00);
3128                 val = val | ((pio_transfer_phase)               ? 0x20 : 0x00);
3129                 val = val | ((dma_transfer_phase)               ? 0x10 : 0x00); // USING DMAC ch.3
3130                 // ToDo: FIX to lack queueing status with some commands
3131                 // 20230207 K.O
3132 //              val = val | ((status_queue->full())             ? 0x02 : 0x00);
3133                 val = val | ((has_status)                               ? 0x02 : 0x00);
3134                 val = val | ((mcu_ready)                                ? 0x01 : 0x00);
3135                 break;
3136         case 0x02:
3137                 val = read_status();
3138                 break;
3139         case 0x04:
3140                 // Data Register
3141                 val = 0xff;
3142                 if((pio_transfer_phase) /*|| (dma_transfer_phase) */) {
3143                         int dummywait;
3144                     val = read_dma_io8w(0, &dummywait);
3145                 }
3146                 break;
3147         case 0x0c: // Subq code
3148                 //val = read_subq();
3149                 val = 0x00;
3150                 break;
3151         case 0x0d: // Subq status
3152                 //val = get_subq_status();
3153                 val = 0x00;
3154                 break;
3155         }
3156         //cdrom_debug_log(_T("READ IO8: %04X %02X"), addr, val);
3157         return val;
3158 }
3159 /*
3160 uint32_t TOWNS_CDROM::read_io16(uint32_t addr)
3161 {
3162         pair32_t v;
3163         v.d = 0xffffffff;
3164         v.b.l = read_io8(addr & 0xfffe);
3165         return v.d;
3166 }
3167 */
3168 void TOWNS_CDROM::write_io8(uint32_t addr, uint32_t data)
3169 {
3170         /*
3171          * 04C0h : Master control register
3172          * 04C2h : Command register
3173          * 04C4h : Parameter register
3174          * 04C6h : Transfer control register.
3175          */
3176         //cdrom_debug_log(_T("WRITE IO8: %04X %02X"), addr, data);
3177         w_regs[addr & 0x0f] = data;
3178         switch(addr & 0x0f) {
3179         case 0x00: // Master control register
3180                 // Note: Sync with TSUGARU.
3181                 // 20220127 K.O
3182                 //cdrom_debug_log(_T("PORT 04C0h <- %02X"), data);
3183                 if((data & 0xc0) != 0) {
3184                         if((data & 0x80) != 0) {
3185                                 mcu_intr = false;
3186                                 if(!(dma_intr)) {
3187                                         write_mcuint_signals(false); // Reset interrupt request to PIC.
3188                                 }
3189                         }
3190                         if((data & 0x40) != 0) {
3191                                 dma_intr = false;
3192                                 if(!(mcu_intr)) {
3193                                         write_mcuint_signals(false); // Reset interrupt request to PIC.
3194                                 }
3195                         }
3196                 }
3197                 if((data & 0x04) != 0) {
3198                         cdrom_debug_log(_T("RESET FROM CMDREG: 04C0h"));
3199                         reset_device();
3200                 }
3201                 mcu_intr_mask = ((data & 0x02) == 0) ? true : false;
3202                 dma_intr_mask = ((data & 0x01) == 0) ? true : false;
3203                 break;
3204         case 0x02: // Command
3205                 //cdrom_debug_log(_T("PORT 04C2h <- %02X"), data);
3206                 // Note: Sync with TSUGARU.
3207                 // 20220127 K.O
3208                 //if(mcu_intr) {
3209                 //      data = data | (latest_command & 0x60); // For FRACTAL ENGINE DEMO (from TSUGARU).
3210                 //}
3211                 //dma_transfer_phase = false;
3212                 //pio_transfer_phase = false;
3213                 //if(stat_reply_intr) {
3214                 //      data |= (latest_command & 0x60);
3215                 //}
3216                 command_received = true;
3217                 reserved_command = data;
3218                 break;
3219         case 0x04: // Param
3220                 param_queue->write(data);
3221                 break;
3222         case 0x06:
3223                 dma_transfer = ((data & 0x10) != 0) ? true : false;
3224                 pio_transfer = ((data & 0x08) != 0) ? true : false;
3225                 if(dma_transfer) {
3226                         pio_transfer = false;
3227                         pio_transfer_phase = false;
3228                         write_signals(&outputs_drq, 0x0);
3229                         double usec = 1.0e6 / ((double)transfer_speed * 150.0e3 * 2.0);
3230                         start_drq(usec);
3231                         dma_transfer_phase = true;
3232                 } else if(pio_transfer) {
3233                         dma_transfer = false;
3234                         dma_transfer_phase = false;
3235                         stop_drq();
3236                         if(!(pio_transfer_phase)) {
3237                                 pio_transfer_phase = true;
3238                         }
3239                 }
3240 //              cdrom_debug_log(_T("SET TRANSFER MODE to %02X"), data);
3241 //              cdrom_debug_log(_T("SET TRANSFER MODE to %02X"), data);
3242 //              }
3243                 break;
3244         }
3245         if((command_received) && (param_queue->full()) && (((addr & 0x0f) == 0x04) || ((addr & 0x0f) == 0x02)) && (event_execute < 0) && (mcu_ready))  {
3246                 command_received = false;
3247                 #if 0
3248                 for(int i = 0; i < 8; i++) {
3249                         exec_params[i] = param_queue->read();
3250                 }
3251                 param_queue->clear();
3252                 #endif
3253                 //prev_command = latest_command;
3254                 //execute_command(reserved_command);
3255                 // From Tsugaru 2023-08-21
3256                 mcu_ready = false;
3257                 register_event(this, EVENT_CDROM_DELAY_COMMAND, 50.0, true, &event_execute);
3258         }
3259 }
3260 /*
3261 void TOWNS_CDROM::write_io16(uint32_t addr, uint32_t data)
3262 {
3263         pair32_t v;
3264         v.d = data;
3265         write_io8w(addr & 0xfffe, v.b.l)
3266 }
3267 */
3268 void TOWNS_CDROM::write_debug_data8(uint32_t addr, uint32_t data)
3269 {
3270         databuffer->write_not_push(addr % max_fifo_length, data & 0xff);
3271 }
3272
3273 uint32_t TOWNS_CDROM::read_debug_data8(uint32_t addr)
3274 {
3275         return databuffer->read_not_remove(addr % max_fifo_length) & 0xff;
3276 }
3277
3278
3279 bool TOWNS_CDROM::write_debug_reg(const _TCHAR *reg, uint32_t data)
3280 {
3281         return false;
3282 }
3283
3284
3285 bool TOWNS_CDROM::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
3286 {
3287         if(buffer == NULL) return false;
3288         _TCHAR regs[256] = {0};
3289         for(int i = 0; i < 16; i += 2) {
3290                 _TCHAR tmps[16] = {0};
3291                 my_stprintf_s(tmps, 16, _T("%02X "), w_regs[i]);
3292                 my_tcscat_s(regs, sizeof(regs) / sizeof(_TCHAR), tmps);
3293         }
3294         _TCHAR stat[256] = {0};
3295         for(int i = 0; i < 4; i++) {
3296                 _TCHAR tmps[16] = {0};
3297                 my_stprintf_s(tmps, 16, _T("%02X "), status_queue->read_not_remove(i) & 0xff);
3298                 my_tcscat_s(stat, sizeof(regs) / sizeof(_TCHAR), tmps);
3299         }
3300         _TCHAR s_param[256] = {0};
3301         _TCHAR s_prev_param[256] = {0};
3302         for(int i = 0; i < 8; i++) {
3303                 _TCHAR tmps[16] = {0};
3304                 my_stprintf_s(tmps, 16, _T("%02X "), exec_params[i]);
3305                 my_tcscat_s(s_param, sizeof(s_param) / sizeof(_TCHAR), tmps);
3306         }
3307         for(int i = 0; i < 8; i++) {
3308                 _TCHAR tmps[16] = {0};
3309                 my_stprintf_s(tmps, 16, _T("%02X "), prev_params[i]);
3310                 my_tcscat_s(s_prev_param, sizeof(s_prev_param) / sizeof(_TCHAR), tmps);
3311         }
3312         bool is_audio = false;
3313         bool in_track = ((current_track > 0) && (current_track < track_num));
3314         uint32_t index0 = 0;
3315         uint32_t index1 = 0;
3316         uint32_t lba_size = 0;
3317         uint32_t lba_offset = 0;
3318         uint32_t pregap = 150;
3319         if(in_track) {
3320                 is_audio = toc_table[current_track].is_audio;
3321                 index0 = toc_table[current_track].index0;
3322                 index1 = toc_table[current_track].index1;
3323                 pregap = toc_table[current_track].pregap;
3324                 lba_size = toc_table[current_track].lba_size;
3325                 lba_offset = toc_table[current_track].lba_offset;
3326         }
3327         _TCHAR moreinfo[512] = {0};
3328         if(is_audio) {
3329                 const _TCHAR* playstatus = get_cdda_status_name(cdda_status);
3330                 my_stprintf_s(moreinfo, sizeof(moreinfo) - 1,
3331                                           _T("TYPE=AUDIO: \n")
3332                                           _T("STATUS=%s LOOP COUNT=%d \n")
3333                                           _T("START=%d END=%d CURRENT_PLAY=%d NEXT_READ=%d \n")
3334                                           ,
3335                                           playstatus, cdda_repeat_count,
3336                                           cdda_start_frame, cdda_end_frame,
3337                                           cdda_playing_frame, read_sector
3338                         );
3339         } else {
3340                 my_stprintf_s(moreinfo, sizeof(moreinfo) - 1,
3341                                           _T("TYPE=DATA: TRANSFER MODE=%s %s\n")
3342                                           , (pio_transfer) ? _T("PIO") : _T("   ")
3343                                           , (dma_transfer) ? _T("DMA") : _T("   ")
3344                         );
3345         }
3346         const _TCHAR* cmdname = get_command_name_from_command(latest_command);
3347         const _TCHAR* prev_cmdname = get_command_name_from_command(prev_command);
3348         my_stprintf_s(buffer, buffer_len,
3349                                   _T("\n%s")
3350                                   _T("MCU INT=%s DMA INT=%s TRANSFER PHASE:%s %s HAS_STATUS=%s MCU=%s\n")
3351                                   _T("TRACK=%d INDEX0=%d INDEX1=%d PREGAP=%d LBA_OFFSET=%d LBA_SIZE=%d\n")
3352                                   _T("LBA=%d READ LENGTH=%d DATA QUEUE=%d\n")
3353                                   _T("CMD=%02X(%s)          PARAM=%s\n")
3354                                   _T("PREV_COMMAND=%02X(%s) PARAM=%s\n")
3355                                   _T("EXTRA STATUS=%d STATUS COUNT=%d QUEUE_VALUE=%s\n")
3356                                   _T("REGS RAW VALUES=%s\n")
3357                                   , moreinfo
3358                                   , (mcu_intr) ? _T("ON ") : _T("OFF"), (dma_intr) ? _T("ON ") : _T("OFF")
3359                                   , (pio_transfer_phase) ? _T("PIO") : _T("   ")
3360                                   , (dma_transfer_phase) ? _T("DMA") : _T("   ")
3361                                   , (has_status) ? _T("ON ") : _T("OFF"), (mcu_ready) ? _T("ON ") : _T("OFF")
3362                                   , current_track, index0, index1, pregap, lba_size, lba_offset
3363                                   , read_sector, read_length, databuffer->count()
3364                                   , latest_command, cmdname, s_param
3365                                   , prev_command, prev_cmdname, s_prev_param
3366                                   , extra_status, status_queue->count(), stat
3367                                   , regs
3368                 );
3369         return true;
3370 }
3371
3372
3373 /*
3374  * Note: 20200428 K.O: DO NOT USE STATE SAVE, STILL don't implement completely yet.
3375  */
3376 #define STATE_VERSION   36
3377
3378 bool TOWNS_CDROM::process_state(FILEIO* state_fio, bool loading)
3379 {
3380         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3381                 return false;
3382         }
3383         if(!state_fio->StateCheckInt32(this_device_id)) {
3384                 return false;
3385         }
3386         if(!(databuffer->process_state((void *)state_fio, loading))) {
3387                 return false;
3388         }
3389         if(!(status_queue->process_state((void *)state_fio, loading))) {
3390                 return false;
3391         }
3392         state_fio->StateArray(w_regs, sizeof(w_regs), 1);
3393
3394         state_fio->StateValue(machine_id);
3395         state_fio->StateValue(cpu_id);
3396         state_fio->StateValue(max_fifo_length);
3397         state_fio->StateValue(fifo_length);
3398
3399         state_fio->StateValue(data_reg);
3400         state_fio->StateValue(req_status);
3401         state_fio->StateValue(stat_reply_intr);
3402
3403         state_fio->StateValue(mcu_intr);
3404         state_fio->StateValue(dma_intr);
3405         state_fio->StateValue(pio_transfer_phase);
3406         state_fio->StateValue(dma_transfer_phase);
3407
3408         state_fio->StateValue(mcu_ready);
3409         state_fio->StateValue(command_execute_phase);
3410
3411         state_fio->StateValue(mcu_intr_mask);
3412         state_fio->StateValue(dma_intr_mask);
3413         state_fio->StateValue(transfer_speed);
3414         state_fio->StateValue(read_length);
3415
3416         state_fio->StateValue(next_seek_lba);
3417         state_fio->StateValue(pio_transfer);
3418         state_fio->StateValue(dma_transfer);
3419         state_fio->StateValue(dmac_running);
3420
3421         state_fio->StateValue(reserved_command);
3422         if(!(param_queue->process_state((void *)state_fio, loading))) {
3423                 return false;
3424         }
3425
3426         state_fio->StateValue(prev_command);
3427         state_fio->StateArray(prev_params, sizeof(prev_params), 1);
3428
3429         state_fio->StateValue(latest_command);
3430         state_fio->StateArray(exec_params, sizeof(exec_params), 1);
3431
3432         state_fio->StateValue(extra_status);
3433
3434         state_fio->StateValue(subq_bitwidth);
3435         state_fio->StateValue(subq_bitptr);
3436         state_fio->StateValue(subq_overrun);
3437
3438         state_fio->StateArray(subq_bytes, sizeof(subq_bytes), 1);
3439         state_fio->StateArray(subq_snapshot, sizeof(subq_snapshot), 1);
3440
3441         state_fio->StateValue(stat_track);
3442         state_fio->StateValue(media_ejected);
3443         state_fio->StateValue(media_changed);
3444         state_fio->StateValue(command_received);
3445
3446
3447         state_fio->StateValue(force_logging);
3448         // CDDA
3449         uint32_t offset = 0;
3450         state_fio->StateValue(read_sector);
3451         state_fio->StateValue(mix_loop_num);
3452
3453         state_fio->StateArray(img_file_path_bak, sizeof(img_file_path_bak), 1);
3454         state_fio->StateValue(is_cue);
3455         state_fio->StateValue(current_track);
3456         state_fio->StateValue(track_num);
3457         state_fio->StateValue(status_seek);
3458
3459         state_fio->StateValue(cdrom_prefetch);
3460
3461         state_fio->StateValue(cdda_start_frame);
3462         state_fio->StateValue(cdda_end_frame);
3463         state_fio->StateValue(cdda_playing_frame);
3464         state_fio->StateValue(cdda_status);
3465         state_fio->StateValue(cdda_repeat_count);
3466         state_fio->StateValue(cdda_interrupt);
3467         state_fio->StateValue(cdda_buffer_ptr);
3468         state_fio->StateValue(cdda_sample_l);
3469         state_fio->StateValue(cdda_sample_r);
3470         state_fio->StateValue(cdda_stopped);
3471
3472         state_fio->StateValue(_decibel_l);
3473         state_fio->StateValue(_decibel_r);
3474
3475         state_fio->StateValue(mute_left);
3476         state_fio->StateValue(mute_right);
3477
3478         if(loading) {
3479                 offset = state_fio->FgetUint32_LE();
3480         } else {
3481                 if(fio_img->IsOpened()) {
3482                         offset = fio_img->Ftell();
3483                 }
3484                 state_fio->FputUint32_LE(offset);
3485         }
3486         // ToDo: Re-Open Image.20181118 K.O
3487         // post process
3488         if(loading) {
3489                 if(status_queue != NULL) {
3490                         has_status = (status_queue->empty()) ? false : true;
3491                 } else {
3492                         has_status = false;
3493                 }
3494                 if(fio_img->IsOpened()) {
3495                         close_from_cmd();
3496                 }
3497                 bool is_cue_bak = is_cue;
3498                 int track_num_bak = track_num;
3499                 if(strlen(img_file_path_bak) > 0) {
3500                         open_from_cmd(img_file_path_bak);
3501                 }
3502                 if((is_cue_bak == is_cue) && (track_num_bak == track_num)) {
3503                         if((current_track > 0) && (current_track < 100)) {
3504                                 get_track_by_track_num(current_track); // Re-Play
3505                         }
3506                         if(fio_img->IsOpened()) {
3507                                 fio_img->Fseek(offset, FILEIO_SEEK_SET);
3508                         }
3509
3510                 } else {
3511                         set_subq(0);
3512                         close_from_cmd();
3513                 }
3514                 make_bitslice_subc_q(subq_bytes, 96);
3515
3516                 volume_l = decibel_to_volume(_decibel_l + 6.0);
3517                 volume_r = decibel_to_volume(_decibel_r + 6.0);
3518
3519         }
3520         state_fio->StateValue(event_execute);
3521         state_fio->StateValue(event_seek);
3522         state_fio->StateValue(event_cdda);
3523         state_fio->StateValue(event_cdda_delay_play);
3524         state_fio->StateValue(event_delay_interrupt);
3525         state_fio->StateValue(event_drq);
3526         state_fio->StateValue(event_next_sector);
3527         state_fio->StateValue(event_delay_ready);
3528         state_fio->StateValue(event_time_out);
3529         state_fio->StateValue(event_eot);
3530
3531         // SCSI_DEV
3532         return true;
3533 }
3534
3535
3536
3537 }