#include "scsi_cdrom.h"
#include "../fifo.h"
+#include <algorithm>
+#include <cctype>
+
#define CDDA_OFF 0
#define CDDA_PLAYING 1
#define CDDA_PAUSED 2
+#define _SCSI_DEBUG_LOG
+#define _CDROM_DEBUG_LOG
+
// 0-99 is reserved for SCSI_DEV class
-#define EVENT_CDDA 100
+#define EVENT_CDDA 100
+#define EVENT_CDDA_DELAY_PLAY 101
+#define EVENT_CDROM_SEEK_SCSI 102
+#define EVENT_CDROM_DELAY_INTERRUPT_ON 103
+#define EVENT_CDROM_DELAY_INTERRUPT_OFF 104
+#define EVENT_CDDA_DELAY_STOP 105
void SCSI_CDROM::initialize()
{
mix_loop_num = 0;
}
event_cdda = -1;
+ event_cdda_delay_play = -1;
+ event_delay_interrupt = -1;
cdda_status = CDDA_OFF;
+ is_cue = false;
+ current_track = 0;
+ read_sectors = 0;
+ for(int i = 0; i < 99; i++) {
+ memset(track_data_path[i], 0x00, _MAX_PATH * sizeof(_TCHAR));
+ }
}
void SCSI_CDROM::release()
void SCSI_CDROM::reset()
{
touch_sound();
+ if(event_delay_interrupt != -1) cancel_event(this, event_delay_interrupt);
+ if(event_cdda_delay_play != -1) cancel_event(this, event_cdda_delay_play);
+ if(event_cdda != -1) cancel_event(this, event_cdda);
+ event_cdda = -1;
+ event_cdda_delay_play = -1;
+ event_delay_interrupt = -1;
SCSI_DEV::reset();
+ read_mode = false;
set_cdda_status(CDDA_OFF);
+ read_sectors = 0;
+ // Q: Does not seek to track 0? 20181118 K.O
+ //current_track = 0;
+
+}
+
+void SCSI_CDROM::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ bool _b = ((data & mask) != 0);
+ switch(id) {
+ case SIG_SCSI_CDROM_CDDA_STOP:
+ if(cdda_status != CDDA_OFF) {
+ if(_b) set_cdda_status(CDDA_OFF);
+ }
+ break;
+ case SIG_SCSI_CDROM_CDDA_PLAY:
+ if(cdda_status != CDDA_PLAYING) {
+ if(_b) set_cdda_status(CDDA_PLAYING);
+ }
+ break;
+ case SIG_SCSI_CDROM_CDDA_PAUSE:
+ if(cdda_status != CDDA_PAUSED) {
+ if(_b) set_cdda_status(CDDA_PAUSED);
+ }
+ break;
+ default:
+ SCSI_DEV::write_signal(id, data, mask);
+ break;
+ }
}
uint32_t SCSI_CDROM::read_signal(int id)
void SCSI_CDROM::event_callback(int event_id, int err)
{
switch (event_id) {
+ case EVENT_CDROM_DELAY_INTERRUPT_ON:
+ write_signals(&outputs_done, 0xffffffff);
+ event_delay_interrupt = -1;
+ break;
+ case EVENT_CDROM_DELAY_INTERRUPT_OFF:
+ write_signals(&outputs_done, 0x00000000);
+ event_delay_interrupt = -1;
+ break;
+ case EVENT_CDDA_DELAY_PLAY:
+ if(cdda_status != CDDA_PLAYING) {
+ set_cdda_status(CDDA_PLAYING);
+ }
+ event_cdda_delay_play = -1;
+ break;
+ case EVENT_CDROM_SEEK_SCSI:
+ seek_time = 10.0;
+ event_cdda_delay_play = -1;
+ SCSI_DEV::start_command();
+ break;
case EVENT_CDDA:
+ if(event_cdda_delay_play > -1) return; // WAIT for SEEK COMPLETED
// read 16bit 2ch samples in the cd-da buffer, called 44100 times/sec
+
cdda_sample_l = (int)(int16_t)(cdda_buffer[cdda_buffer_ptr + 0] + cdda_buffer[cdda_buffer_ptr + 1] * 0x100);
cdda_sample_r = (int)(int16_t)(cdda_buffer[cdda_buffer_ptr + 2] + cdda_buffer[cdda_buffer_ptr + 3] * 0x100);
-
+ // ToDo: CLEAR IRQ Line (for PCE)
if((cdda_buffer_ptr += 4) % 2352 == 0) {
// one frame finished
if(++cdda_playing_frame == cdda_end_frame) {
// reached to end frame
+ #ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("Reaches to the end of track.(FRAME %d). START_FRAME=%d END_FRAME=%d REPEAT=%s INTERRUPT=%s\n"),
+ cdda_playing_frame, cdda_start_frame, cdda_end_frame,
+ (cdda_repeat) ? _T("YES") : _T("NO"), (cdda_interrupt) ? _T("YES") : _T("NO"));
+ #endif
if(cdda_repeat) {
// reload buffer
- fio_img->Fseek(cdda_start_frame * 2352, FILEIO_SEEK_SET);
- fio_img->Fread(cdda_buffer, sizeof(cdda_buffer), 1);
+ if(is_cue) {
+ fio_img->Fclose();
+ //current_track = 0;
+ //int trk = get_track(cdda_start_frame);
+ int trk = current_track;
+ fio_img->Fseek((cdda_start_frame - toc_table[trk].lba_offset) * 2352, FILEIO_SEEK_SET);
+ } else {
+ fio_img->Fseek(cdda_start_frame * 2352, FILEIO_SEEK_SET);
+ }
+ read_sectors = fio_img->Fread(cdda_buffer, 2352 * sizeof(uint8_t) , array_length(cdda_buffer) / 2352);
cdda_buffer_ptr = 0;
cdda_playing_frame = cdda_start_frame;
access = true;
} else {
- // stop
- if(cdda_interrupt) {
- write_signals(&outputs_done, 0xffffffff);
- }
+ // Stop
+ //if(event_cdda_delay_play >= 0) cancel_event(this, event_cdda_delay_play);
set_cdda_status(CDDA_OFF);
+ //register_event(this, EVENT_CDDA_DELAY_STOP, 1000.0, false, &event_cdda_delay_play);
}
- } else if(cdda_buffer_ptr == array_length(cdda_buffer)) {
+ } else if((cdda_buffer_ptr % 2352) == 0) {
// refresh buffer
- fio_img->Fread(cdda_buffer, sizeof(cdda_buffer), 1);
- cdda_buffer_ptr = 0;
- access = true;
+ read_sectors--;
+ if(read_sectors <= 0) {
+ read_sectors = fio_img->Fread(cdda_buffer, 2352 * sizeof(uint8_t), array_length(cdda_buffer) / 2352);
+ cdda_buffer_ptr = 0;
+ access = true;
+ } else {
+ }
}
}
break;
+ case EVENT_CDDA_DELAY_STOP:
+ if(cdda_interrupt) {
+ write_signals(&outputs_done, 0xffffffff);
+ }
+ set_cdda_status(CDDA_OFF);
+ event_cdda_delay_play = -1;
+ break;
default:
SCSI_DEV::event_callback(event_id, err);
break;
}
}
if(cdda_status != CDDA_PLAYING) {
+ //// Notify to release bus.
+ write_signals(&outputs_done, 0x00000000);
+ if(cdda_status == CDDA_OFF) {
+ //get_track_by_track_num(current_track); // Re-Play
+ //memset(cdda_buffer, 0x00, sizeof(cdda_buffer));
+ cdda_playing_frame = cdda_start_frame;
+ get_track(cdda_playing_frame);
+ cdda_buffer_ptr = 0;
+ } else if(cdda_status == CDDA_PAUSED) {
+ // Unpause
+ access = true;
+ }
touch_sound();
set_realtime_render(this, true);
+ #ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("Play CDDA from %s.\n"), (cdda_status == CDDA_PAUSED) ? _T("PAUSED") : _T("STOPPED"));
+ #endif
}
} else {
if(event_cdda != -1) {
event_cdda = -1;
}
if(cdda_status == CDDA_PLAYING) {
+ // Notify to release bus.
+ write_signals(&outputs_done, 0x00000000);
+ //if(event_delay_interrupt >= 0) cancel_event(this, event_delay_interrupt);
+ //register_event(this, EVENT_CDROM_DELAY_INTERRUPT_OFF, 1.0e6 / (44100.0 * 2352), false, &event_delay_interrupt);
+ if(status == CDDA_OFF) {
+ memset(cdda_buffer, 0x00, sizeof(cdda_buffer));
+ cdda_buffer_ptr = 0;
+ read_sectors = 0;
+ //if(is_cue) {
+ // if(fio_img->IsOpened()) fio_img->Fclose();
+ //}
+ //current_track = 0;
+ }
touch_sound();
set_realtime_render(this, false);
+ #ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("%s playing CDDA.\n"), (status == CDDA_PAUSED) ? _T("PAUSE") : _T("STOP"));
+ #endif
}
}
cdda_status = status;
return SCSI_DEV::get_command_length(value);
}
-int SCSI_CDROM::get_track(uint32_t lba)
+void SCSI_CDROM::get_track_by_track_num(int track)
+{
+ if((track <= 0) || (track >= track_num)) {
+ if(is_cue) {
+ if(fio_img->IsOpened()) fio_img->Fclose();
+ }
+ //if(track <= 0) current_track = 0;
+ //if(track >= track_num)current_track = track_num;
+ current_track = 0;
+ return;
+ }
+ if(is_cue) {
+ // ToDo: Apply audio with some codecs.
+ if((current_track != track) || !(fio_img->IsOpened())){
+ if(fio_img->IsOpened()) {
+ fio_img->Fclose();
+ }
+ #ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("LOAD TRK #%02d from %s\n"), track, track_data_path[track - 1]);
+ #endif
+
+ if((track > 0) && (track < 100) && (track < track_num)) {
+ if((strlen(track_data_path[track - 1]) <= 0) ||
+ !(fio_img->Fopen(track_data_path[track - 1], FILEIO_READ_BINARY))) {
+ track = 0;
+ }
+ } else {
+ track = 0;
+ }
+ }
+ }
+ current_track = track;
+}
+
+// Detect only track num.
+int SCSI_CDROM::get_track_noop(uint32_t lba)
{
int track = 0;
-
for(int i = 0; i < track_num; i++) {
if(lba >= toc_table[i].index0) {
track = i;
}
}
return track;
+}
+
+int SCSI_CDROM::get_track(uint32_t lba)
+{
+ int track = 0;
+ track = get_track_noop(lba);
+ if(is_cue) {
+ get_track_by_track_num(track);
+ } else {
+ current_track = track;
+ }
+ return track;
}
double SCSI_CDROM::get_seek_time(uint32_t lba)
{
if(fio_img->IsOpened()) {
- uint32_t cur_position = (int)fio_img->Ftell();
- int distance = abs((int)(lba * physical_block_size()) - (int)cur_position);
- double ratio = (double)distance / 333000 / physical_block_size(); // 333000: sectors in media
+ uint32_t cur_position = (uint32_t)fio_img->Ftell();
+ int distance;
+ if(is_cue) {
+ int track = 0;
+ for(int i = 0; i < track_num; i++) {
+ if(lba >= toc_table[i].index0) {
+ track = i;
+ } else {
+ break;
+ }
+ }
+ distance = abs((int)(lba * physical_block_size()) - (int)(cur_position + toc_table[current_track].lba_offset * physical_block_size()));
+ if(track != current_track) {
+ current_track = get_track(lba);
+ }
+ } else {
+ distance = abs((int)(lba * physical_block_size()) - (int)cur_position);
+ }
+ double ratio = ((double)distance / 333000.0) / physical_block_size(); // 333000: sectors in media
return max(10, (int)(400000 * 2 * ratio));
} else {
return 400000; // 400msec
}
}
-uint32_t lba_to_msf(uint32_t lba)
+uint32_t SCSI_CDROM::lba_to_msf(uint32_t lba)
{
uint8_t m = lba / (60 * 75);
lba -= m * (60 * 75);
return ((m / 10) << 20) | ((m % 10) << 16) | ((s / 10) << 12) | ((s % 10) << 8) | ((f / 10) << 4) | ((f % 10) << 0);
}
-uint32_t lba_to_msf_alt(uint32_t lba)
+uint32_t SCSI_CDROM::lba_to_msf_alt(uint32_t lba)
{
uint32_t ret = 0;
ret |= ((lba / (60 * 75)) & 0xff) << 16;
void SCSI_CDROM::start_command()
{
touch_sound();
+ #ifdef _SCSI_DEBUG_LOG
+// this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: #%02x %02x %02x %02x %02x %02x\n"), scsi_id, command[0], command[1], command[2], command[3], command[4], command[5]);
+ #endif
switch(command[0]) {
case SCSI_CMD_READ6:
- seek_time = 10;//get_seek_time((command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]);
+ //seek_time = 10;//get_seek_time((command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]);
+ seek_time = get_seek_time((command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]);
set_cdda_status(CDDA_OFF);
+ if(seek_time > 10.0) {
+ if(event_cdda_delay_play >= 0) {
+ cancel_event(this, event_cdda_delay_play);
+ event_cdda_delay_play = -1;
+ }
+ register_event(this, EVENT_CDROM_SEEK_SCSI, seek_time - 10.0, false, &event_cdda_delay_play);
+ return;
+ } else {
+ seek_time = 10.0;
+ }
break;
-
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
- seek_time = 10;//get_seek_time(command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5]);
+ seek_time = get_seek_time((command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]);
set_cdda_status(CDDA_OFF);
+ if(seek_time > 10.0) {
+ if(event_cdda_delay_play >= 0) {
+ cancel_event(this, event_cdda_delay_play);
+ event_cdda_delay_play = -1;
+ }
+ register_event(this, EVENT_CDROM_SEEK_SCSI, seek_time - 10.0, false, &event_cdda_delay_play);
+ return;
+ } else {
+ seek_time = 10.0;
+ }
break;
+ case SCSI_CMD_MODE_SEL6:
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: NEC Read Mode Select 6-byte\n"), scsi_id);
+ #endif
+ // start position
+// position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
+// position *= physical_block_size();
+ position = 0;
+ // transfer length
+// remain = command[4];// * logical_block_size();
+ remain = 11;
+ if(remain != 0) {
+ // clear data buffer
+ buffer->clear();
+ // change to data in phase
+ set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
+ } else {
+ // transfer length is zero, change to status phase
+ set_dat(SCSI_STATUS_GOOD);
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ set_phase_delay(SCSI_PHASE_STATUS, 10.0);
+ }
+ return;
+
case 0xd8:
#ifdef _SCSI_DEBUG_LOG
- this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: NEC Set Audio Playback Start Position\n"), scsi_id);
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: NEC Set Audio Playback Start Position CMD=%02x ARG=%02x %02x %02x %02x\n"), scsi_id, command[9], command[2], command[3], command[4], command[5]);
#endif
if(is_device_ready()) {
if(command[2] == 0 && command[3] == 0 && command[4] == 0) {
// stop cd-da if all params are zero
cdda_start_frame = 0;
cdda_end_frame = toc_table[track_num].index0; // end of disc
- set_cdda_status(CDDA_OFF);
+ double seek_time = get_seek_time(cdda_end_frame);
+ if(is_cue) {
+ get_track_by_track_num(track_num);
+ }
+ //set_cdda_status(CDDA_OFF);
+ if(event_cdda_delay_play >= 0) cancel_event(this, event_cdda_delay_play);
+ register_event(this, EVENT_CDDA_DELAY_STOP, (seek_time > 10.0) ? seek_time : 10.0, false, &event_cdda_delay_play);
} else {
+ uint32_t seek_offset = 0;
switch(command[9] & 0xc0) {
case 0x00:
cdda_start_frame = (command[2] << 16) | (command[3] << 8) | command[4];
// PCE tries to be clever here and set (start of track + track pregap size) to skip the pregap
// (I guess it wants the TOC to have the real start sector for data tracks and the start of the pregap for audio?)
- int track =get_track(cdda_start_frame);
- cdda_start_frame -= toc_table[track].pregap;
-
- if(cdda_start_frame < toc_table[track].index1) {
- cdda_start_frame = toc_table[track].index1; // don't play pregap
+ int track = get_track(cdda_start_frame);
+ if(cdda_start_frame >= toc_table[track].pregap) {
+ cdda_start_frame -= toc_table[track].pregap;
+ }
+ if(cdda_start_frame < toc_table[track].index0) {
+ cdda_start_frame = toc_table[track].index0; // don't play pregap
} else if(cdda_start_frame > max_logical_block) {
cdda_start_frame = 0;
}
}
break;
case 0x80:
- cdda_start_frame = toc_table[FROM_BCD(command[2]) - 1].index1;
+ {
+ int8_t track = FROM_BCD(command[2] - 1);
+ cdda_start_frame = toc_table[track].index1;
+ if(cdda_start_frame >= toc_table[track].pregap) {
+ cdda_start_frame -= toc_table[track].pregap;
+ }
+ }
break;
default:
cdda_start_frame = 0;
// cdda_end_frame = toc_table[track_num].index0; // end of disc
// set_cdda_status(CDDA_OFF);
// } else
+ double delay_time = get_seek_time(cdda_start_frame);
if((command[1] & 3) != 0) {
+ if((is_cue) && (current_track != track_num)){
+ get_track_by_track_num(track_num);
+ }
cdda_end_frame = toc_table[track_num].index0; // end of disc
- set_cdda_status(CDDA_PLAYING);
+ double seek_time = get_seek_time(cdda_start_frame);
+ if(event_cdda_delay_play >= 0) {
+ cancel_event(this, event_cdda_delay_play);
+ event_cdda_delay_play = -1;
+ }
+ //set_cdda_status(CDDA_PLAYING);
+ register_event(this, EVENT_CDROM_SEEK_SCSI, seek_time, false, &event_cdda_delay_play);
} else {
- cdda_end_frame = toc_table[get_track(cdda_start_frame) + 1].index1; // end of this track
+ uint32_t _sframe = cdda_start_frame;
+ //cdda_end_frame = toc_table[get_track(_sframe) + 1].index1; // end of this track
+ //cdda_end_frame = toc_table[get_track(_sframe)].index1; // end of this track
set_cdda_status(CDDA_PAUSED);
}
cdda_repeat = false;
cdda_interrupt = ((command[1] & 3) == 2);
// read buffer
- double seek_time = get_seek_time(cdda_start_frame);
- fio_img->Fseek(cdda_start_frame * 2352, FILEIO_SEEK_SET);
- fio_img->Fread(cdda_buffer, sizeof(cdda_buffer), 1);
+ //double delay_time = 10.0;
+#if 1
+ if(is_cue) {
+ //if(cdda_start_frame > 150) cdda_start_frame = cdda_start_frame - 150;
+ fio_img->Fseek((cdda_start_frame - toc_table[current_track].index0) * 2352, FILEIO_SEEK_SET);
+ } else {
+ fio_img->Fseek(cdda_start_frame * 2352, FILEIO_SEEK_SET);
+ }
+#endif
+ read_sectors = fio_img->Fread(cdda_buffer, 2352 * sizeof(uint8_t), array_length(cdda_buffer) / 2352);
cdda_buffer_ptr = 0;
cdda_playing_frame = cdda_start_frame;
access = true;
// change to status phase
set_dat(SCSI_STATUS_GOOD);
- set_phase_delay(SCSI_PHASE_STATUS, seek_time);
+ // From Mame 0.203
+ if(event_delay_interrupt >= 0) cancel_event(this, event_delay_interrupt);
+ register_event(this, EVENT_CDROM_DELAY_INTERRUPT_ON, delay_time, false, &event_delay_interrupt);
+ //set_phase_delay(SCSI_PHASE_STATUS, delay_time + 10.0);
+ //write_signals(&outputs_done, 0xffffffff);
+ set_phase_delay(SCSI_PHASE_STATUS, 10.0);
return;
}
}
// change to status phase
set_dat(is_device_ready() ? SCSI_STATUS_GOOD : SCSI_STATUS_CHKCOND);
+ // From Mame 0.203
+ //if(is_device_ready()) write_signals(&outputs_done, 0xffffffff);
set_phase_delay(SCSI_PHASE_STATUS, 10.0);
+
return;
case 0xd9:
#ifdef _SCSI_DEBUG_LOG
- this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: NEC Set Audio Playback End Position\n"), scsi_id);
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: NEC Set Audio Playback End Position CMD=%02x ARG=%02x %02x %02x %02x\n"), scsi_id, command[9], command[2], command[3], command[4], command[5]);
#endif
if(is_device_ready()) {
+
switch(command[9] & 0xc0) {
case 0x00:
cdda_end_frame = (command[3] << 16) | (command[4] << 8) | command[5];
// PCE tries to be clever here and set (start of track + track pregap size) to skip the pregap
// (I guess it wants the TOC to have the real start sector for data tracks and the start of the pregap for audio?)
- int track =get_track(cdda_end_frame);
- if(cdda_end_frame > toc_table[track].index1 && (cdda_end_frame - toc_table[track].pregap) <= toc_table[track].index1) {
- cdda_end_frame = toc_table[track].index1;
+// int track = get_track(cdda_start_frame);
+ int track = current_track;
+ cdda_playing_frame = cdda_start_frame;
+// if(is_cue) {
+// fio_img->Fseek((cdda_start_frame - toc_table[current_track].lba_offset) * 2352, FILEIO_SEEK_SET);
+// } else {
+// fio_img->Fseek(cdda_start_frame * 2352, FILEIO_SEEK_SET);
+// }
+ //read_sectors = fio_img->Fread(cdda_buffer, 2352 * sizeof(uint8_t), array_length(cdda_buffer) / 2352);
+
+ if(cdda_end_frame > toc_table[track + 1].index1 && (cdda_end_frame - toc_table[track].pregap) <= toc_table[track + 1].index1) {
+ cdda_end_frame = toc_table[track + 1].index1;
}
+ cdda_buffer_ptr = 0;
}
break;
case 0x80:
- cdda_end_frame = toc_table[FROM_BCD(command[2]) - 1].index1;
+ {
+ int _track = FROM_BCD(command[2]) - 1;
+ if(_track >= 0) {
+ cdda_end_frame = toc_table[_track].index0;
+ if(is_cue) {
+ if(current_track != _track) {
+ get_track_by_track_num(_track);
+ cdda_start_frame = toc_table[_track].index0;
+ cdda_end_frame = toc_table[_track].lba_size + toc_table[_track].lba_offset;
+ cdda_playing_frame = cdda_start_frame;
+ if(is_cue) {
+ fio_img->Fseek((cdda_start_frame - toc_table[current_track].lba_offset) * 2352, FILEIO_SEEK_SET);
+ } else {
+ fio_img->Fseek(cdda_start_frame * 2352, FILEIO_SEEK_SET);
+ }
+ read_sectors = fio_img->Fread(cdda_buffer, 2352 * sizeof(uint8_t), array_length(cdda_buffer) / 2352);
+ cdda_buffer_ptr = 0;
+ }
+ }
+ }
+ }
break;
+ default:
+ break; // ToDo
}
if((command[1] & 3) != 0) {
- set_cdda_status(CDDA_PLAYING);
cdda_repeat = ((command[1] & 3) == 1);
cdda_interrupt = ((command[1] & 3) == 2);
+
+ if(event_cdda_delay_play >= 0) cancel_event(this, event_cdda_delay_play);
+ register_event(this, EVENT_CDDA_DELAY_PLAY, 10.0, false, &event_cdda_delay_play);
+ //set_cdda_status(CDDA_PLAYING);
} else {
set_cdda_status(CDDA_OFF);
+ cdda_start_frame = toc_table[track_num].index0;;
+ cdda_end_frame = toc_table[track_num].index1; // end of disc
+ double seek_time = get_seek_time(cdda_start_frame);
+ //double seek_time = 10.0;
+ get_track_by_track_num(track_num); // END OF DISC
+
+ set_dat(is_device_ready() ? SCSI_STATUS_GOOD : SCSI_STATUS_CHKCOND);
+// if(event_cdda_delay_play >= 0) cancel_event(this, event_cdda_delay_play);
+// register_event(this, EVENT_CDDA_DELAY_STOP, (seek_time > 10.0) ? seek_time : 10.0, false, &event_cdda_delay_play);
+ if(is_device_ready()) {
+ if(event_delay_interrupt >= 0) {
+ cancel_event(this, event_delay_interrupt);
+ event_delay_interrupt = -1;
+ }
+ register_event(this, EVENT_CDROM_DELAY_INTERRUPT_ON, (seek_time > 10.0) ? (seek_time + 10.0) : (10.0 + 10.0), false, &event_delay_interrupt);
+ }
+ set_phase_delay(SCSI_PHASE_STATUS, (seek_time > 10.0) ? (seek_time + 10.0) : (10.0 + 10.0));
+ return;
}
}
// change to status phase
set_dat(is_device_ready() ? SCSI_STATUS_GOOD : SCSI_STATUS_CHKCOND);
+ if(is_device_ready()) {
+ write_signals(&outputs_done, 0xffffffff);
+ //if(event_delay_interrupt >= 0) cancel_event(this, event_delay_interrupt);
+ //register_event(this, EVENT_CDROM_DELAY_INTERRUPT_ON, 10.0, false, &event_delay_interrupt);
+
+ }
set_phase_delay(SCSI_PHASE_STATUS, 10.0);
return;
#endif
if(is_device_ready()) {
if(cdda_status == CDDA_PLAYING) {
- set_cdda_status(CDDA_OFF);
+ set_cdda_status(CDDA_PAUSED);
}
}
// change to status phase
set_dat(is_device_ready() ? SCSI_STATUS_GOOD : SCSI_STATUS_CHKCOND);
+ if(is_device_ready()) write_signals(&outputs_done, 0xffffffff);
set_phase_delay(SCSI_PHASE_STATUS, 10.0);
return;
// create track info
uint32_t frame = (cdda_status == CDDA_OFF) ? cdda_start_frame : cdda_playing_frame;
uint32_t msf_abs = lba_to_msf_alt(frame);
- int track = get_track(frame);
+ int track;
+ double delay_time = 10.0;
+ track = current_track;
+ if((cdda_status == CDDA_OFF) && (toc_table[track].is_audio)) { // OK? (or force ERROR) 20181120 K.O
+ //set_cdda_status(CDDA_PLAYING);
+ delay_time = get_seek_time(frame);
+ //delay_time = 10.0;
+ if(event_cdda_delay_play >= 0) {
+ cancel_event(this, event_cdda_delay_play);
+ event_cdda_delay_play = -1;
+ }
+ register_event(this, EVENT_CDDA_DELAY_PLAY, delay_time, false, &event_cdda_delay_play);
+ }
uint32_t msf_rel = lba_to_msf_alt(frame - toc_table[track].index0);
buffer->clear();
buffer->write((cdda_status == CDDA_PLAYING) ? 0x00 : (cdda_status == CDDA_PAUSED) ? 0x02 : 0x03);
#endif
if(is_device_ready()) {
buffer->clear();
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] CMD=%02x ARG=%02x \n"), scsi_id, command[1], command[2]);
+ #endif
switch(command[1]) {
case 0x00: /* Get first and last track numbers */
buffer->write(TO_BCD(1));
buffer->write(TO_BCD(track_num));
+ // PC-8801 CD BIOS invites 4 bytes ?
+ buffer->write(0);
+ buffer->write(0);
break;
case 0x01: /* Get total disk size in MSF format */
{
buffer->write((msf >> 16) & 0xff);
buffer->write((msf >> 8) & 0xff);
buffer->write((msf >> 0) & 0xff);
+ // PC-8801 CD BIOS invites 4 bytes ?
+ buffer->write(0);
}
break;
case 0x02: /* Get track information */
buffer->write(0x04); // correct ?
} else {
int track = max(FROM_BCD(command[2]), 1);
- uint32_t frame = toc_table[track - 1].index0;
+ uint32_t frame = toc_table[track].index0;
// PCE wants the start sector for data tracks to *not* include the pregap
- if(!toc_table[track - 1].is_audio) {
- frame += toc_table[track - 1].pregap;
+ if(!toc_table[track].is_audio) {
+ frame += toc_table[track].pregap;
}
- uint32_t msf = lba_to_msf(toc_table[track - 1].index1 + 150);
+ get_track_by_track_num(track);
+
+ uint32_t msf = lba_to_msf(toc_table[track].index1 + 150);
buffer->write((msf >> 16) & 0xff); // M
buffer->write((msf >> 8) & 0xff); // S
buffer->write((msf >> 0) & 0xff); // F
- buffer->write(toc_table[track - 1].is_audio ? 0x00 : 0x04);
+ buffer->write(toc_table[track].is_audio ? 0x00 : 0x04);
}
break;
}
set_phase_delay(SCSI_PHASE_STATUS, 10.0);
}
return;
+ case 0xff:
+ // End of List
+ set_dat(SCSI_STATUS_CHKCOND);
+ return;
}
// start standard command
SCSI_DEV::start_command();
}
-void SCSI_CDROM::read_buffer(int length)
+bool SCSI_CDROM::read_buffer(int length)
{
- if(fio_img->IsOpened()) {
- uint32_t offset = (uint32_t)(position % 2352);
+ if(!fio_img->IsOpened()) {
+ set_sense_code(SCSI_SENSE_NOTREADY);
+ return false;
+ }
+ uint32_t offset = (uint32_t)(position % 2352);
+
+ if(is_cue) {
+ // ToDo: Need seek wait.
+ #ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("Seek to LBA %d\n"), position / 2352);
+ #endif
+ if(fio_img->Fseek(((long)position - (long)(toc_table[current_track].lba_offset * 2352)), FILEIO_SEEK_SET) != 0) {
+ set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_SEEKERR
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] Error on reading (ILLGLBLKADDR) at line %d\n"), scsi_id, __LINE__);
+ #endif
+ return false;
+ }
+ } else {
+ if(fio_img->Fseek((long)position, FILEIO_SEEK_SET) != 0) {
+ set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_SEEKERR
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] Error on reading (ILLGLBLKADDR) at line %d\n"), scsi_id, __LINE__);
+ #endif
+ return false;
+ }
+ }
+ while(length > 0) {
+ uint8_t tmp_buffer[2352];
+// int tmp_length = min(length, (int)sizeof(tmp_buffer));
+ int tmp_length = 2352 - offset;
- fio_img->Fseek((long)position, FILEIO_SEEK_SET);
- while(length > 0) {
- uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
- int tmp_length = min(length, (int)sizeof(tmp_buffer));
+ if(fio_img->Fread(tmp_buffer, tmp_length, 1) != 1) {
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] Error on reading (ILLGLBLKADDR) at line %d\n"), scsi_id, __LINE__);
+ #endif
- fio_img->Fread(tmp_buffer, tmp_length, 1);
- for(int i = 0; i < tmp_length && length > 0; i++) {
- if(offset >= 16 && offset < 16 + 2048) {
- int value = tmp_buffer[i];
- buffer->write(value);
- length--;
- }
- position++;
- offset = (offset + 1) % 2352;
+ set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
+ return false;
+ }
+ for(int i = 0; i < tmp_length; i++) {
+ if(offset >= 16 && offset < 16 + logical_block_size()) {
+ int value = tmp_buffer[i];
+ buffer->write(value);
+ length--;
+ }
+ position++;
+ offset = (offset + 1) % 2352;
+ }
+ access = true;
+ }
+ // Is This right? 20181120 K.O
+ //write_signals(&outputs_done, 0xffffffff); // Maybe don't need "DONE SIGNAL" with reading DATA TRACK. 20181207 K.O
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return true;
+}
+
+bool SCSI_CDROM::write_buffer(int length)
+{
+ for(int i = 0; i < length; i++) {
+ int value = buffer->read();
+ if(command[0] == SCSI_CMD_MODE_SEL6) {
+ if(i == 4) {
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] NEC Read Mode = %02X\n"), scsi_id, value);
+ #endif
+ read_mode = (value != 0);
+ } else if(i == 10) {
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SCSI_DEV:ID=%d] NEC Retry Count = %02X\n"), scsi_id, value);
+ #endif
}
- access = true;
}
+ position++;
}
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return true;
}
int get_frames_from_msf(const char *string)
return value;
}
+#include <string>
+
+bool SCSI_CDROM::open_cue_file(const _TCHAR* file_path)
+{
+ std::string line_buf;
+ std::string line_buf_shadow;
+ std::string image_tmp_data_path;
+
+ _TCHAR full_path_cue[_MAX_PATH];
+ size_t ptr;
+ int line_count = 0;
+ int slen;
+ int nr_current_track = 0;
+ FILEIO* fio = new FILEIO();
+ if(fio == NULL) return false;
+
+ memset(full_path_cue, 0x00, sizeof(full_path_cue));
+ image_tmp_data_path.clear();
+
+ get_long_full_path_name(file_path, full_path_cue, sizeof(full_path_cue));
+
+ _TCHAR *parent_dir = get_parent_dir(full_path_cue);
+
+ size_t _arg1_ptr;
+ size_t _arg2_ptr;
+ size_t _arg2_ptr_s;
+ size_t _arg3_ptr;
+ size_t _arg3_ptr_s;
+
+ std::string _arg1;
+ std::string _arg2;
+ std::string _arg3;
+
+ if(fio->Fopen(file_path, FILEIO_READ_ASCII)) { // ToDo: Support not ASCII cue file (i.e. SJIS/UTF8).20181118 K.O
+ line_buf.clear();
+ for(int i = 0; i < 100; i++) {
+ memset(&(track_data_path[i][0]), 0x00, _MAX_PATH * sizeof(_TCHAR));
+ }
+ int _c;
+ bool is_eof = false;
+ int sptr = 0;
+ while(1) {
+ line_buf.clear();
+ int _np = 0;
+ _c = EOF;
+ do {
+ _c = fio->Fgetc();
+ if((_c == '\0') || (_c == '\n') || (_c == EOF)) break;;
+ if(_c != '\r') line_buf.push_back((char)_c);
+ } while(1);
+ if(_c == EOF) is_eof = true;
+ slen = (int)line_buf.length();
+ if(slen <= 0) goto _n_continue;
+ // Trim head of Space or TAB
+ ptr = 0;
+ sptr = 0;
+ // Tokenize
+ _arg1.clear();
+ _arg2.clear();
+ _arg3.clear();
+
+ ptr = line_buf.find_first_not_of((const char*)" \t");
+ if(ptr == std::string::npos) {
+ goto _n_continue;
+ }
+ // Token1
+ line_buf_shadow = line_buf.substr(ptr);
+
+ _arg1_ptr = line_buf_shadow.find_first_of((const char *)" \t");
+ _arg1 = line_buf_shadow.substr(0, _arg1_ptr);
+ _arg2 = line_buf_shadow.substr(_arg1_ptr);
+ std::transform(_arg1.begin(), _arg1.end(), _arg1.begin(),
+ [](unsigned char c) -> unsigned char{ return std::toupper(c); });
+
+ _arg2_ptr = _arg2.find_first_not_of((const char *)" \t");
+
+ if(_arg2_ptr != std::string::npos) {
+ _arg2 = _arg2.substr(_arg2_ptr);
+ }
+
+ if(_arg1 == "REM") {
+ // REM
+ goto _n_continue;
+ } else if(_arg1 == "FILE") {
+ _arg2_ptr = _arg2.find_first_of((const char *)"\"") + 1;
+ if(_arg2_ptr == std::string::npos) goto _n_continue;
+
+ _arg2 = _arg2.substr(_arg2_ptr);
+ _arg3_ptr = _arg2.find_first_of((const char *)"\"");
+ if(_arg3_ptr == std::string::npos) goto _n_continue;
+ _arg2 = _arg2.substr(0, _arg3_ptr);
+
+ image_tmp_data_path.clear();
+ image_tmp_data_path = std::string(parent_dir);
+ image_tmp_data_path.append(_arg2);
+
+ #ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("**FILE %s\n"), image_tmp_data_path.c_str());
+ #endif
+ goto _n_continue; // ToDo: Check ARG2 (BINARY etc..) 20181118 K.O
+ } else if(_arg1 == "TRACK") {
+ _arg2_ptr_s = _arg2.find_first_of((const char *)" \t");
+
+ _arg3 = _arg2.substr(_arg2_ptr_s);
+ _arg2 = _arg2.substr(0, _arg2_ptr_s);
+ _arg3_ptr = _arg3.find_first_not_of((const char *)" \t");
+ int _nr_num = atoi(_arg2.c_str());
+
+ // Set image file
+ if((_nr_num > 0) && (_nr_num < 100) && (_arg3_ptr != std::string::npos)) {
+ nr_current_track = _nr_num;
+ _arg3 = _arg3.substr(_arg3_ptr);
+
+ memset(track_data_path[_nr_num - 1], 0x00, sizeof(_TCHAR) * _MAX_PATH);
+ strncpy((char *)(track_data_path[_nr_num - 1]), image_tmp_data_path.c_str(), _MAX_PATH);
+
+ _arg3_ptr_s = _arg3.find_first_of((const char *)" \t\n");
+ _arg3.substr(0, _arg3_ptr_s);
+
+ std::transform(_arg3.begin(), _arg3.end(), _arg3.begin(),
+ [](unsigned char c) -> unsigned char{ return std::toupper(c); });
+
+ toc_table[nr_current_track].is_audio = false;
+ toc_table[nr_current_track].index0 = 0;
+ toc_table[nr_current_track].index1 = 0;
+ toc_table[nr_current_track].pregap = 0;
+
+ if(_arg3.compare("AUDIO") == 0) {
+ toc_table[nr_current_track].is_audio = true;
+ } else if(_arg3.compare("MODE1/2352") == 0) {
+ toc_table[nr_current_track].is_audio = false;
+ } else {
+ // ToDo: another type
+ }
+ if(track_num < (_nr_num + 1)) track_num = _nr_num + 1;
+ } else {
+ // ToDo: 20181118 K.Ohta
+ nr_current_track = 0;
+ }
+ goto _n_continue;
+ } else if(_arg1 == "INDEX") {
+
+ if((nr_current_track > 0) && (nr_current_track < 100)) {
+ _arg2_ptr_s = _arg2.find_first_of((const char *)" \t");
+ if(_arg2_ptr_s == std::string::npos) goto _n_continue;
+
+ _arg3 = _arg2.substr(_arg2_ptr_s);
+ _arg2 = _arg2.substr(0, _arg2_ptr_s);
+ _arg3_ptr = _arg3.find_first_not_of((const char *)" \t");
+ if(_arg3_ptr == std::string::npos) goto _n_continue;
+
+ _arg3 = _arg3.substr(_arg3_ptr);
+ _arg3_ptr_s = _arg3.find_first_of((const char *)" \t");
+ _arg3.substr(0, _arg3_ptr_s);
+ int index_type = atoi(_arg2.c_str());
+
+ switch(index_type) {
+ case 0:
+ toc_table[nr_current_track].index0 = get_frames_from_msf(_arg3.c_str());
+ break;
+ case 1:
+ toc_table[nr_current_track].index1 = get_frames_from_msf(_arg3.c_str());
+ break;
+ default:
+ break;
+ }
+ goto _n_continue;
+ } else {
+ goto _n_continue;
+ }
+ } else if(_arg1 == "PREGAP") {
+ if((nr_current_track > 0) && (nr_current_track < 100)) {
+ _arg2_ptr_s = _arg2.find_first_of((const char *)" \t");
+ _arg2 = _arg2.substr(0, _arg2_ptr_s - 1);
+
+ toc_table[nr_current_track].pregap = get_frames_from_msf(_arg2.c_str());
+ goto _n_continue;
+ } else {
+ goto _n_continue;
+ }
+ }
+ _n_continue:
+ if(is_eof) break;
+ line_buf.clear();
+ continue;
+ }
+ // Finish
+ max_logical_block = 0;
+ if(track_num > 0) {
+ toc_table[0].lba_offset = 0;
+ toc_table[0].lba_size = 0;
+ toc_table[0].index0 = toc_table[0].index1 = toc_table[0].pregap = 0;
+ // P1: Calc
+ int _n = 0;
+ for(int i = 1; i < track_num; i++) {
+
+ if(fio_img->IsOpened()) {
+ fio_img->Fclose();
+ }
+ if(toc_table[i].index1 != 0) {
+ toc_table[i].index0 = toc_table[i].index0 + max_logical_block;
+ toc_table[i].index1 = toc_table[i].index1 + max_logical_block;
+ if(toc_table[i].index0 != max_logical_block) {
+ if(toc_table[i].pregap == 0) {
+ toc_table[i].pregap = toc_table[i].index1 - toc_table[i].index0;
+ }
+ }
+ } else {
+ toc_table[i].index1 = toc_table[i].index1 + max_logical_block;
+ if(toc_table[i].index0 == 0) {
+ toc_table[i].index0 = toc_table[i].index1 - toc_table[i].pregap;
+ } else {
+ toc_table[i].index0 = toc_table[i].index0 + max_logical_block;
+ if(toc_table[i].pregap == 0) {
+ toc_table[i].pregap = toc_table[i].index1 - toc_table[i].index0;
+ }
+ }
+ }
+ // Even...
+ if(toc_table[i].pregap <= 0) {
+ toc_table[i].pregap = 150; // Default PREGAP must be 2Sec. From OoTake.(Only with PCE? Not with FM-Towns?)
+ }
+
+ _n = 0;
+ if(strlen(track_data_path[i - 1]) > 0) {
+ if(fio_img->Fopen(track_data_path[i - 1], FILEIO_READ_BINARY)) {
+ if((_n = fio_img->FileLength() / 2352) > 0) {
+ max_logical_block += _n;
+ } else {
+ _n = 0;
+ }
+ fio_img->Fclose();
+ }
+ }
+ toc_table[i].lba_size = _n;
+ toc_table[i].lba_offset = max_logical_block - _n;
+
+
+ //#ifdef _CDROM_DEBUG_LOG
+ this->out_debug_log(_T("TRACK#%02d TYPE=%s PREGAP=%d INDEX0=%d INDEX1=%d LBA_SIZE=%d LBA_OFFSET=%d PATH=%s\n"),
+ i, (toc_table[i].is_audio) ? _T("AUDIO") : _T("MODE1/2352"),
+ toc_table[i].pregap, toc_table[i].index0, toc_table[i].index1,
+ toc_table[i].lba_size, toc_table[i].lba_offset, track_data_path[i - 1]);
+ //#endif
+ }
+ toc_table[0].index0 = toc_table[0].index1 = toc_table[0].pregap = 0;
+// toc_table[track_num].index0 = toc_table[track_num].index1 = max_logical_block;
+// toc_table[track_num].lba_offset = max_logical_block;
+// toc_table[track_num].lba_size = 0;
+
+ }
+ fio->Fclose();
+ }
+ delete fio;
+
+ is_cue = false;
+ if(track_num > 0) is_cue = true;
+ // Not Cue FILE.
+ return is_cue;
+}
+
void SCSI_CDROM::open(const _TCHAR* file_path)
{
_TCHAR img_file_path[_MAX_PATH];
close();
if(check_file_extension(file_path, _T(".cue"))) {
+#if 1
+ is_cue = false;
+ current_track = 0;
+ open_cue_file(file_path);
+#else
// get image file name
my_stprintf_s(img_file_path, _MAX_PATH, _T("%s.img"), get_file_path_without_extensiton(file_path));
if(!FILEIO::IsFileExisting(img_file_path)) {
delete fio;
}
}
+#endif
} else if(check_file_extension(file_path, _T(".ccd"))) {
// get image file name
my_stprintf_s(img_file_path, _MAX_PATH, _T("%s.img"), get_file_path_without_extensiton(file_path));
}
}
if(fio_img->Fopen(img_file_path, FILEIO_READ_BINARY)) {
+ is_cue = false;
+ current_track = 0;
// get image file size
if((max_logical_block = fio_img->FileLength() / 2352) > 0) {
// read cue file
}
}
if(track_num != 0) {
+ toc_table[0].lba_offset = 0;
+ toc_table[0].pregap = 0;
for(int i = 1; i < track_num; i++) {
toc_table[i].index0 = toc_table[i].index1 - toc_table[i].pregap;
+ toc_table[i].lba_offset = toc_table[i].pregap;
+ toc_table[i - 1].lba_size = toc_table[i].pregap - toc_table[i - 1].pregap;
}
toc_table[0].index0 = toc_table[0].index1 = toc_table[0].pregap = 0;
toc_table[track_num].index0 = toc_table[track_num].index1 = max_logical_block;
+ if(track_num > 0) {
+ toc_table[track_num].lba_size = max_logical_block - toc_table[track_num - 1].lba_offset;
+ } else {
+ toc_table[track_num].lba_size = 0;
+ }
} else {
fio_img->Fclose();
}
}
memset(toc_table, 0, sizeof(toc_table));
track_num = 0;
+ is_cue = false;
+ current_track = 0;
set_cdda_status(CDDA_OFF);
}
bool SCSI_CDROM::mounted()
{
+ if(is_cue) return true;
return fio_img->IsOpened();
}
void SCSI_CDROM::set_volume(int ch, int decibel_l, int decibel_r)
{
- volume_l = decibel_to_volume(decibel_l);
- volume_r = decibel_to_volume(decibel_r);
+ volume_l = decibel_to_volume(decibel_l + 3.0);
+ volume_r = decibel_to_volume(decibel_r + 3.0);
}
void SCSI_CDROM::set_volume(int volume)
volume_m = (int)(1024.0 * (max(0, min(100, volume)) / 100.0));
}
-#define STATE_VERSION 3
-
-#include "../statesub.h"
-
-void SCSI_CDROM::decl_state()
-{
- enter_decl_state(STATE_VERSION);
-
- DECL_STATE_ENTRY_UINT32(cdda_start_frame);
- DECL_STATE_ENTRY_UINT32(cdda_end_frame);
- DECL_STATE_ENTRY_UINT32(cdda_playing_frame);
- DECL_STATE_ENTRY_UINT8(cdda_status);
- DECL_STATE_ENTRY_BOOL(cdda_repeat);
- DECL_STATE_ENTRY_BOOL(cdda_interrupt);
- DECL_STATE_ENTRY_1D_ARRAY(cdda_buffer, sizeof(cdda_buffer));
- DECL_STATE_ENTRY_INT32(cdda_buffer_ptr);
- DECL_STATE_ENTRY_INT32(cdda_sample_l);
- DECL_STATE_ENTRY_INT32(cdda_sample_r);
- DECL_STATE_ENTRY_INT32(event_cdda);
-// DECL_STATE_ENTRY_INT32(mix_loop_num);
- DECL_STATE_ENTRY_INT32(volume_m);
-// if(fio_img->IsOpened()) {
-// state_fio->FputUint32(fio_img->Ftell());
-// } else {
-// state_fio->FputUint32(0);
-// }
-
- leave_decl_state();
-
- // ToDo: Add Fix Value.
- SCSI_DEV::decl_state();
-}
-
-#include "../state_data.h"
+#define STATE_VERSION 4
-void SCSI_CDROM::save_state(FILEIO* state_fio)
+// Q: If loading state when using another (saved) image? 20181013 K.O
+// May need close() and open() (or ...?).
+bool SCSI_CDROM::process_state(FILEIO* state_fio, bool loading)
{
- uint32_t crc_value = 0xffffffff;
- if(state_entry != NULL) {
- state_entry->save_state(state_fio, &crc_value);
- }
-// state_fio->FputUint32(STATE_VERSION);
-// state_fio->FputInt32(this_device_id);
-
-// state_fio->FputUint32(cdda_start_frame);
-// state_fio->FputUint32(cdda_end_frame);
-// state_fio->FputUint32(cdda_playing_frame);
-// state_fio->FputUint8(cdda_status);
-// state_fio->FputBool(cdda_repeat);
-// state_fio->FputBool(cdda_interrupt);
-// state_fio->Fwrite(cdda_buffer, sizeof(cdda_buffer), 1);
-// state_fio->FputInt32(cdda_buffer_ptr);
-// state_fio->FputInt32(cdda_sample_l);
-// state_fio->FputInt32(cdda_sample_r);
-// state_fio->FputInt32(event_cdda);
-//// state_fio->FputInt32(mix_loop_num);
-// state_fio->FputInt32(volume_m);
- csp_state_data_saver saver(state_fio);
- bool stat = false;
- if(fio_img->IsOpened()) {
- saver.put_dword(fio_img->Ftell(), &crc_value, &stat);
+ uint32_t offset = 0;
+
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(cdda_start_frame);
+ state_fio->StateValue(cdda_end_frame);
+ state_fio->StateValue(cdda_playing_frame);
+ state_fio->StateValue(cdda_status);
+ state_fio->StateValue(cdda_repeat);
+ state_fio->StateValue(cdda_interrupt);
+ state_fio->StateArray(cdda_buffer, sizeof(cdda_buffer), 1);
+ state_fio->StateValue(cdda_buffer_ptr);
+ state_fio->StateValue(cdda_sample_l);
+ state_fio->StateValue(cdda_sample_r);
+ state_fio->StateValue(event_cdda);
+ state_fio->StateValue(event_cdda_delay_play);
+ state_fio->StateValue(event_delay_interrupt);
+ state_fio->StateValue(read_sectors);
+// state_fio->StateValue(mix_loop_num);
+ state_fio->StateValue(read_mode);
+ state_fio->StateValue(volume_m);
+ if(loading) {
+ offset = state_fio->FgetUint32_LE();
} else {
- saver.put_dword(0, &crc_value, &stat);
- }
- saver.post_proc_saving(&crc_value, &stat);
-
- //SCSI_DEV::save_state(state_fio);
-}
-
-bool SCSI_CDROM::load_state(FILEIO* state_fio)
-{
- uint32_t crc_value = 0xffffffff;
- bool mb = false;
- bool stat = false;
- if(state_entry != NULL) {
- mb = state_entry->load_state(state_fio, &crc_value);
- }
- if(!mb) return false;
- csp_state_data_saver saver(state_fio);
-// if(state_fio->FgetUint32() != STATE_VERSION) {
-// return false;
-// }
-// if(state_fio->FgetInt32() != this_device_id) {
-// return false;
-// }
-// cdda_start_frame = state_fio->FgetUint32();
-// cdda_end_frame = state_fio->FgetUint32();
-// cdda_playing_frame = state_fio->FgetUint32();
-// cdda_status = state_fio->FgetUint8();
-// cdda_repeat = state_fio->FgetBool();
-// cdda_interrupt = state_fio->FgetBool();
-// state_fio->Fread(cdda_buffer, sizeof(cdda_buffer), 1);
-// cdda_buffer_ptr = state_fio->FgetInt32();
-// cdda_sample_l = state_fio->FgetInt32();
-// cdda_sample_r = state_fio->FgetInt32();
-// event_cdda = state_fio->FgetInt32();
-// mix_loop_num = state_fio->FgetInt32();
-// volume_m = state_fio->FgetInt32();
- uint32_t offset = saver.get_dword(&crc_value, &stat);
- if(!(saver.post_proc_loading(&crc_value, &stat))) return false;
-
- // post process
- if(fio_img->IsOpened()) {
- fio_img->Fseek(offset, FILEIO_SEEK_SET);
+ if(fio_img->IsOpened()) {
+ offset = fio_img->Ftell();
+ }
+ state_fio->FputUint32_LE(offset);
}
-// return SCSI_DEV::load_state(state_fio);
- return true;
+
+ state_fio->StateValue(is_cue);
+ state_fio->StateValue(current_track);
+ // ToDo: Re-Open Image.20181118 K.O
+ // post process
+ if(loading && fio_img->IsOpened()) {
+ fio_img->Fseek(offset, FILEIO_SEEK_SET);
+ }
+ return SCSI_DEV::process_state(state_fio, loading);
}
-