+++ /dev/null
-/*!
- * @file cdrom_cdc.cpp
- * @brief CD-ROM Conbtroller Device class for eFM-Towns.
- * @author K.Ohta <whatisthis.sowhat _at_ gmail.com>
- * @date 2021-03-31
- * @copyright GPLv2
- */
-
-#include "../device.h"
-
-#include "./cdrom_skelton.h"
-#include "./cdrom_cue.h"
-//#include "./cdrom_ccd.h"
-//#include "./cdrom_iso.h"
-
-namespace FMTOWNS {
-
-#define EVENT_CMD_SEEK 1 //!< UNTIL SEEK COMPLETED
-#define EVENT_READ_SEEK 2 //!< UNTIL SEEK COMPLETED
-#define EVENT_TIMEOUT 3 //!< UNTIL TIMEOUT
-#define EVENT_DRQ 4 //!< DRQ PER BYTE
-#define EVENT_TIMEOUT 5 //!< GENERIC TIMEOUT
-#define EVENT_NEXT_SECTOR 6 //!< TO NEXT SECTOR
-
-
-void CDROM_CDC::initialize()
-{
- fifo_size = 8192;
- max_address = (uint32_t)(sizeof(ram));
- event_seek = -1;
- event_drq = -1;
- event_timeout = -1;
- event_read_wait = -1;
- volume_l = 0; // OK?
- volume_r = 0; // OK?
- enable_prefetch = false;
-
-
- status_queue = new FIFO(100 * 8 + 4);
-}
-
-void CDROM_CDC::release()
-{
- if(cdrom != nullptr) {
- delete cdrom;
- cdrom = NULL;
- }
- if(status_queue != nullptr) {
- delete status_queue;
- status_queue = NULL;
- }
-}
-
-void CDROM_CDC::reset()
-{
- // Reset FIFO until data.
- memset(ram, 0x00, sizeof(ram));
-
- read_ptr = 0x0000;
- write_ptr = 0x0000;
- data_count = 0;
- data_count_tmp = 0;
- tmp_bytes_count = 0;
- access_status = false;
- sectors_remain = 0;
- sample_pos = 0;
- fadeout_level = 16;
- is_playing = false;
-
- in_track = false;
- target_lba = 0;
-
- status_seek = false;
-
- cdda_samples[0].w = 0;
- cdda_samples[1].w = 0;
- clear_event(event_seek);
- clear_event(event_drq);
- clear_event(event_read_wait);
- clear_event(event_timeout);
-
- memset(regs, 0x00, sizeof(regs));
- memset(param_queue, 0x00, sizeof(param_queue));
- memset(param_queue_bak, 0x00, sizeof(param_queue_bak));
- last_commnd = 0x00;
-
- if(cdrom != nullptr) {
- cdrom->seek_absolute_lba(target_lba, in_track);
- }
- if(status_queue != nullptr) {
- status_queue->clear();
- }
-
-}
-
-bool CDROM_CDC::seek_to_lba_msf(uint8_t m, uint8_t s, uint8_t s, uint8_t cmdtype)
-{
- if(cdrom != NULL) {
- double usec = cdrom->get_seek_time(m, s, f);
- if(usec < 0.0) {
- return false;
- }
- clear_event(event_read_wait);
- clear_event(event_timeout);
- force_register_event(this, (cmdtype == 0x00) ? EVENT_CMD_SEEK : EVENT_READ_SEEK,
- usec, false, event_seek);
- return true;
- }
- return false;
-}
-
-pair16_t CDROM_CDC::read_cdda_sample()
-{
- pair16_t sample;
- sample.w = 0;
- if(data_count > 0) {
- sample.b.l = ram[read_ptr];
- read_ptr++;
- if(read_ptr >= fifo_size) {
- read_ptr = 0;
- }
- data_count--;
- }
- if(data_count > 0) {
- sample.b.h = ram[read_ptr];
- read_ptr++;
- if(read_ptr >= fifo_size) {
- read_ptr = 0;
- }
- data_count--;
- }
- return sample;
-}
-
-uint32_t CDROM_CDC::read_dma_io8(uint32_t addr)
-{
- uint8_t dat;
- int count_bak = data_count;
- dat = read_data_from_ram();
- // Check DRQ status.
- return (uint32_t)dat;
-}
-
-uint32_t CDROM_CDC::read_io8(uint32_t addr)
-{
- /*
- * 04C0h : Master status
- * 04C2h : CDC status
- * 04C4h : DATA
- * 04CCh : SUBQ CODE
- * 04CDh : SUBQ STATUS
- */
- uint8_t val = 0x00;
-
- switch(addr & 0x0f) {
- case 0x00: // Read master status.
- val = val | ((mcu_intr) ? 0x80 : 0x00);
- val = val | ((dma_intr) ? 0x40 : 0x00);
- val = val | ((pio_transfer_phase) ? 0x20 : 0x00);
- val = val | ((dma_transfer_phase) ? 0x10 : 0x00); // USING DMAC ch.3
- val = val | ((has_status()) ? 0x02 : 0x00);
- val = val | ((mcu_ready) ? 0x01 : 0x00);
- break;
- case 0x02: // Read from Status queue.
- val = 0x00;
- if(status_queue != nullptr) {
- if(!(status_queue->empty())) {
- val = status_queue->read() & 0xff;
- }
- }
- break;
- case 0x04:
- {
- int count_bak = data_count;
- val = read_data_from_ram();
- if(pio_transfer_phase) {
- // Check DRQ status.
- if(data_count <= 0) {
- // Make EOT
- pio_transfer_phase = false;
- // Q: Will interrupt?
- if(count_bak > 0) {
- //mcu_ready = false;
- //dma_intr = true;
- //mcu_intr = false;
- //clear_event(this, event_time_out);
- //clear_event(this, event_eot);
- //clear_event(this, event_drq);
- set_pio_eot();
- }
- }
- }
- }
- break;
- case 0x0c: // SUBQ STATUS
- break;
- case 0x0d: // SUBQ DATA
- break;
- }
- return (uint32_t)val;
-}
-
-void CDROM_CDC::write_io8(uint32_t addr, uint32_t data)
-{
- /*
- * 04C0h : Master control register
- * 04C2h : Command register
- * 04C4h : Parameter register
- * 04C6h : Transfer control register.
- */
- uint32_t naddr = addr & 0x0f;
- regs[naddr] = data;
- switch(naddr) {
- case 0x00: // Master control register
- if((data & 0x80) != 0) {
- /*if(mcu_intr) */set_mcu_intr(false);
- }
- if((data & 0x40) != 0) {
- /*if(dma_intr) */set_dma_intr(false);
- }
- if((data & 0x04) != 0) {
- cdrom_debug_log(_T("RESET FROM CMDREG: 04C0h"));
- reset_device();
-// break;
- }
- mcu_intr_mask = ((data & 0x02) == 0) ? true : false;
- dma_intr_mask = ((data & 0x01) == 0) ? true : false;
- break;
- case 0x02: // Command
- execute_command(data);
- break;
- case 0x04: // Param
- for(int i = 1; i < 8; i++) {
- param_queue[i - 1] = param_queue[i];
- }
- param_queue[7] = data;
- break;
- case 0x06:
- if(dma_transfer()) {
-// if(data_count > 0) {
- if(!(dma_transfer_phase)) {
- dma_transfer_phase = true;
- force_register_event(this, EVENT_CDROM_DRQ,
- /*0.25 * 1.0e6 / ((double)transfer_speed * 150.0e3 ) */ 1.0 / 8.0,
- true, event_drq);
- }
-// }
- } else if(pio_transfer()) {
-// if(data_count > 0) {
- if(!(pio_transfer_phase)) {
- pio_transfer_phase = true;
- }
-// }
- }
- }
-}
-
-bool CDROM_CDC::execute_command(uint8_t cmd)
-{
- if(!(mcu_ready)) {
- return false;
- }
- // Accepted: Copy to backup.
- memcpy(param_queue_bak, param_queue, sizeof(param_queue));
- memset(param_queue, 0x00, sizeof(param_queue));
- last_command = cmd;
- mcu_ready = false;
- clear_event(this, event_time_out);
-
- bool _err;
- //
-
- switch(last_command & 0x9f) {
- case 0x00: // Seek
- if(!(status_seek)) {
- status_seek = true;
- double seek_time = 1.0;
- if(d_cdrom != nullptr) {
- uint8_t m, s, f;
- m = d_cdrom->bcd_to_bin(param_queue_bak[0], _err);
- s = d_cdrom->bcd_to_bin(param_queue_bak[1], _err);
- f = d_cdrom->bcd_to_bin(param_queue_bak[2], _err);
- seek_time = cdrom->get_seek_time(m, s, f);
- target_lba = cdrom->msf_to_lba(m, s, f);
- if(seek_time < 1.0) {
- seek_time = 1.0;
- }
- // ToDo: Debug LOG
- }
- force_register_event(this, EVENT_CMD_SEEK, usec, false, event_seek);
- }
- break;
- case 0x01: // Read MODE2
- break;
- case 0x02: // Read MODE1
- break;
- case 0x03: // Read RAW
- break;
- case 0x04: // PLAY TRACK
- break;
- }
- return true;
-}
-
-void CDROM_CDC::write_signal(int id, uint32_t data, uint32_t mask)
-{
- switch(id) {
- case SIG_CDC_DMA_EOT:
- if((data & mask) != 0) {
- dma_intr = true;
- dma_transfer_phase = false;
- clear_event(this, event_time_out);
- clear_event(this, event_eot);
- clear_event(this, event_drq);
- if((data_count <= 0) && (sectors_remain <= 0)) {
- clear_event(this, event_next_sector);
- clear_event(this, event_seek_completed);
- status_read_done(false);
- cdrom_debug_log(_T("EOT(DMA)"));
- } else {
- cdrom_debug_log(_T("NEXT(DMA)"));
- }
- if(!(dma_intr_mask) && (stat_reply_intr())) {
- write_interrupt(true);
- }
- }
- break;
- }
-}
-
-}
-
-uint32_t CDROM_CDC::read_signal(int id)
-{
- return 0;
-}
-
-void CDROM_CDC::event_callback(int event_id, int err)
-{
- switch(event_id) {
- case EVENT_CMD_SEEK:
- event_seek = -1;
- status_seek = false;
- if(cdrom != nullptr) {
- cdrom->seek_absolute_lba(target_lba, in_track);
- }
- if(check_cdda_playing()) {
- set_cdda_status(CDDA_OFF);
- set_subq();
- }
- if(!(req_status())) {
- mcu_intr = true;
- write_interrupt(0xffffffff);
- }
- if(req_status()) {
- clear_status();
- push_status_accept(0x00, 0x00); // s1 = CD_STATUS_ACCEPT, s2 = playcode
- push_status(TOWNS_CD_STATUS_SEEK_COMPLETED, 0x00, 0x00, 0x00);
- delay_ready();
- } else {
- delay_ready_nostatus();
- }
-
- break;
- case EVENT_READ_SEEK:
- event_seek = -1;
- clear_event(event_read_wait);
- clear_event(event_timeout);
- if(cdrom != nullptr) {
- cdrom->seek_absolute_lba(target_lba, in_track);
- }
-
- // If still exists data on ram and if disabled to prefetch.
- tmp_bytes_count = 0;
- if(!(enable_prefetch) && (data_count > 0)) {
- // Retry after some uSecs.
- double usec = 1.0e6 / 150.0e3;
- if(cdrom != nullptr) {
- usec = cdrom->get_transfer_time_us();
- if(usec <= 0.0) {
- usec = 1.0e6 / 150.0e3;
- }
- }
- force_register_event(this, EVENT_DATA_SEEK, 16.0 * usec, false, event_seek);
- return;
- }
-
- // OK. Try to read from sector(s).
- if(sectors_remain > 0) {
- double usec = 1.0e6 / 150.0e3;
- uint32_t bytes = 2352;
- uint32_t lbytes = 2048;
- if(cdrom != nullptr) {
- bytes = cdrom->get_physical_block_size();
- lbytes = cdrom->get_logical_block_size();
- usec = cdrom->get_transfer_time_us();
- if((bytes <= 0) || (usec <= 0.0) || (lbytes <= 0)) {
- // Return error.
- return;
- }
- if(!(cdrom->is_available())) {
- // Return error
- return;
- }
- ssize_t _readsize = 0;
- int r_sectors = 1;
- if(enable_prefetch) {
- if((fifo_size - data_count_tmp) < (lbytes * sectors_remain)) {
- r_sectors = (fifo_size - data_count_tmp) / lbytes;
- }
- }
- if(r_sectors > sectors_remain) r_sectors = sectors_remain;
- if(r_sectors > 0) {
- _readsize = read_sectors(r_sectors);
- if(_readsize != (bytes * r_sectors)) {
- // Error trap?
- }
- usec = usec * (double)bytes * (double)r_sectors;
- usec = usec / 2.0; // OK?
- tmp_bytes_count = lbytes * r_sectors;
- target_lba = target_lba + r_sectors;
- force_register_event(this, (is_audio) ? EVENT_START_CDDA : EVENT_DATA_IN, usec, false, event_data_in);
- sectors_remain -= r_sectors;
- } else {
- // Retry after some uSecs.
- force_register_event(this, EVENT_DATA_SEEK, 16.0 * usec, false, event_seek);
- }
- } else {
- // Disc empty.
- }
- } else {
- // End of reading.
- }
- break;
- case EVENT_DATA_IN:
- event_data_in = -1;
- // Set Status and interrupts
- if(tmp_bytes_count > 0) {
- data_count += tmp_bytes_count;
- if(data_count > fifo_size) {
- data_count = fifo_size;
- }
- if(event_drq < 0) {
- // Register DRQ
- double usec = 1.0e6 / 150.0e3;
- if(cdrom != nullptr) {
- usec = cdrom->get_transfer_time_us();
- }
- if(usec <= 0.0) usec = 1.0e6 / 150.0e3;
- usec = usec / 4.0; // OK?
- force_register_event(this, EVENT_DRQ, usec, true, event_drq);
- }
- }
- tmp_bytes_count = 0;
- // ToDo: Make status to DATA IN.
- if(sectors_remain > 0) {
- double usec = 1.0e6 / 150.0e3;
- uint32_t bytes = 2352;
- // Go To Next sector.
- if(cdrom != nullptr) {
- bytes = cdrom->get_physical_block_size();
- usec = cdrom->get_transfer_time_us();
- if((bytes <= 0) || (usec <= 0.0)) {
- bytes = 2352;
- usec = 1.0e6 / 150.0e3;
- }
- }
- usec = (usec * (double)bytes) / 2.0; // OK?
-// usec = 5.0e3; // GAP
- force_register_event(this, EVENT_DATA_SEEK,
- usec, false, event_seek);
- } else {
- // All data has read.
- }
- break;
- case EVENT_DRQ:
- if(data_count > 0) {
- write_drq_signal();
- }
- // MAKE DRQ
- // -> SIGNAL TO DMAC
- // -> DMA:READ FROM CDC(CDROM_CDC::read_dma_io8())
- // -> Check DRQ STATUS.
- break;
- case EVENT_START_CDDA:
- event_data_in = -1;
- if(!(cdda_started)) {
- // Make status to CDDA OK.
- cdda_started = true;
- sample_pos = 0;
- cdda_samples[0].w = 0;
- cdda_samples[1].w = 0;
- }
- update_subq();
- fadeout_level = 16;
- if(event_cdda < 0) {
- // Register DRQ
- double usec = 1.0e6 / 150.0e3;
- force_register_event(this, EVENT_CDDA, usec, true, event_cdda);
- }
- if(sectors_remain > 0) {
- double usec = (2352.0 * (1.0e6 / 150.0e3)) / 2.0;
- force_register_event(this, EVENT_DATA_SEEK,
- usec, false, event_seek);
- }
- break;
- case EVENT_CDDA:
- // Check if CDDA is end.
- if(!(check_cdda_playing())) {
- // End.
- clear_event(event_cdda);
- double usec = 10.0e3; // OK?
- force_register_event(this, EVENT_FADEOUT_CDDA, usec, true, event_cdda);
- if(is_loop_cdda()) {
- // Re-Seek to begin LBA.
- }
- // Make status.
-
- }
- if(is_audio) {
- if(cdda_started) {
- if(data_count > 0) {
- pair16_t sample = read_cdda_sample();
- cdda_samples[sample_pos & 1].w = sample.w;
- sample_pos++;
- }
- }
- }
- break;
- case EVENT_FADEOUT_CDDA:
- sample_pos = 0;
- if(fadeout_level < 0) {
- cdda_cample[0].w = 0;
- cdda_cample[1].w = 0;
- is_playing = false;
- clear_event(event_cdda);
- return;
- }
- fadeout_level--:
- break;
- }
-}
-
-void CDROM_CDC::mix(int32_t* buffer, int cnt)
-{
- if(check_cdda_playing() && (fadeout_level >= 0)) {
- int32_t l = (int32_t)(cdda_samples[0].sw);
- int32_t r = (int32_t)(cdda_samples[1].sw);
- int flevel = (fadeout_level * 3) - 48;
- l = apply_volume(l, flevel + volume_l);
- r = apply_volume(r, flevel + volume_r);
- for(int i = 0, j = 0; i < cnt; i++, j += 2) {
- int32_t sl, sr;
- sl = l + buffer[j + 0];
- sr = r + buffer[j + 1];
- if(sl > 32767) {
- sl = 32767;
- } else if(sl < -32768) {
- sl = -32768;
- }
- if(sr > 32767) {
- sr = 32767;
- } else if(sr < -32768) {
- sr = -32768;
- }
- buffer[j + 0] = sl;
- buffer[j + 1] = sr;
- }
- }
-}
-
-/*!
- * @brief READ a sector from CDROM_SKELTON::read.
- */
-ssize_t CDROM_CDC::read_sectors(int sectors)
-{
- ssize_t read_size = 0;
- ssize_t read_count = 0;
- enum CDROM_META::CDIMAGE_TRACK_TYPE trktype = CDROM_SKELTON::TRACKTYPE_NONE;
-
- if((cdrom != nullptr) && (mounted())) {
- trktype = cdrom->get_track_type();
- if(trktype == CDROM_META::TRACKTYPE_AUDIO) {
- pait16_t *buf = NULL;
- buf = malloc(sectors * 2352);
- if(buf == nullptr) return 0;
-
- for(int i = 0; i < (sectors * (2352 / 2)) ; i++) {
- buf.w = 0;
- }
- read_size = cdrom->read_cdda(buf, 2352, 1) * 2;
- if(read_size <= 0) {
- free(buf);
- return 0;
- }
- for(int i = 0; i < (read_size / 2); i++) {
- if(data_count_tmp >= fifo_size) break;
- ram[write_ptr] = buf[i].b.l;
- write_ptr++;
- if(write_ptr >= fifo_size) {
- write_ptr = 0;
- }
- data_count_tmp++;
- read_count++;
-
- if(data_count_tmp >= fifo_size) break;
- ram[write_ptr] = buf[i].b.h;
- write_ptr++;
- if(write_ptr >= fifo_size) {
- write_ptr = 0;
- }
- data_count_tmp++;
- read_count++;
- }
- free(buf);
- } else {
- uint8_t *buf = NULL; // ToDo: Larger sector.
- buf = malloc(sectors * 2352);
- if(buf == nullptr) return 0;
- memset(buf, 0x00, sectors * 2352);
-
- switch(trktype) {
- case CDROM_META::TRACKTYPE_MODE1_2048:
- case CDROM_META::TRACKTYPE_MODE1_2352:
- case CDROM_META::TRACKTYPE_MODE1_ISO:
- read_size = cdrom->read_mode1(buf, 2352 * sectors, sectors);
- break;
- case CDROM_META::TRACKTYPE_MODE2_2336:
- case CDROM_META::TRACKTYPE_MODE2_2352:
- case CDROM_META::TRACKTYPE_MODE2_ISO:
- read_size = cdrom->read_mode2(buf, 2352 * sectors, sectors);
- break;
- }
- if(read_size <= 0) {
- free(buf);
- return 0;
- }
-
- for(int i = 0; i < read_size; i++) {
- if(data_count_tmp >= fifo_size) break;
-
- ram[write_ptr] = buf[i];
- write_ptr++;
- if(write_ptr >= fifo_size) {
- write_ptr = 0;
- }
- data_count_tmp++;
- read_count++;
- }
- free(buf);
- }
- }
- return read_count;
-}
-
-bool CDROM_CDC::mounted()
-{
- if(cdrom != nullptr) {
- return cdrom->is_available();
- }
- return false;
-}
-
-bool CDROM_CDC::accessed()
-{
- return access_status;
-}
-
-void CDROM_CDC::open(const _TCHAR* file_path)
-{
- close();
- if(FILEIO::IsFileExists(file_path)) {
- CDROM_META::CDIMAGE_TYPE type = CDROM_META::check_type(file_path);
- switch(type) {
- case IMAGETYPE_CUE:
- cdrom = new CDROM_CUE();
- break;
- case IMAGETYPE_ISO:
- cdrom = new CDROM_ISO();
- break;
- case IMAGETYPE_CCD:
- cdrom = new CDROM_CCD();
- break;
- }
- if(cdrom != nullptr) {
- if(cdrom->open(file_path, type)) {
- return; // Succeded.
- } else {
- delete cdrom;
- cdrom = NULL;
- return;
- }
- }
- return;
- }
-}
-
-void CDROM_CDC::close()
-{
- if(cdrom != nullptr) {
- cdrom->close();
- delete cdrom;
- cdrom = NULL;
- }
-}
-
-uint32_t CDROM_CDC::read_debug_data8(uint32_t addr)
-{
- uint32_t r_addr = addr;
- if(max_address == 0) {
- return 0;
- }
- r_addr = r_addr % max_address;
- uint8_t data = ram[r_addr];
- return (uint32_t)data;
-}
-
-void CDROM_CDC::write_debug_data8(uint32_t addr, uint32_t data)
-{
- uint32_t r_addr = addr;
- if(max_address == 0) {
- return;
- }
- r_addr = r_addr % max_address;
- ram[r_addr] = data;
-}
-
-bool CDROM_CDC::get_debug_regs_info(_TCHAR* buffer, size_t buffer_len)
-{
- if((buffer == nullptr) || (buffer_len <= 1)) {
- return false;
- }
- memset(buffer, 0x00, buffer_len * sizeof(_TCHAR));
-
- // Print regs
- _TCHAR tmpstr[256] = {0};
- my_stprintf_s(tmpstr, 256 - 1, _T("REGS: +0 +1 +2 +3 +4 +5 +6 +7\n"));
- my_tcscat_s(buffer, buffer_len - 1, tmpstr);
-
- for(r = 0; r < 16; r += 8) {
- memset(tmpstr, 0x00, sizeof(tmpstr));
- my_stprintf_s(tmpstr, 256 - 1, _T("R%d : %02X %02X %02X %02X %02X %02X %02X %02X\n"),
- r,
- regs[r + 0], regs[r + 1], regs[r + 2], regs[r + 3],
- regs[r + 4], regs[r + 5], regs[r + 6], regs[r + 7]
- );
- my_tcscat_s(buffer, buffer_len - 1, tmpstr);
- }
- memset(tmpstr, 0x00, sizeof(tmpstr));
-
- if(cdrom != nullptr) {
- int64_t lba;
- int track;
- uint8_t m, s, f;
- int64_t sectors;
- bool is_legal = false;
- if(cdrom->is_available()) {
- track = cdrom->get_track();
- lba = cdrom->get_lba();
- sectors = cdrom->get_sectors_of_this_track();
- if(!(cdrom->lba_to_msf(lba, m, s, f))) {
- m = 0;
- s = 0;
- f = 0;
- } else {
- is_legal = true;
- }
- my_stprintf_s(tmpstr, 256 - 1, _T("\nTRACK:%d LBA=%d (M=%d S=%d F=%d)\n"),
- track, lba, m, s, f);
- my_tcscat_s(buffer, buffer_len - 1, tmpstr);
- memset(tmpstr, 0x00, sizeof(tmpstr));
-
- } else {
- my_stprintf_s(tmpstr, 256 - 1, _T("\n** CDROM HAS NOT INSERTED **\n"));
- my_tcscat_s(buffer, buffer_len - 1, tmpstr);
- }
- } else {
- my_stprintf_s(tmpstr, 256 - 1, _T("\n** CDROM HAS NOT INSERTED **\n"));
- my_tcscat_s(buffer, buffer_len - 1, tmpstr);
- }
- return true;
-}
-
-bool CDROM_CDC::write_debug_reg(_TCHAR* reg, uint32_t data)
-{
- if(reg == nullptr) {
- return false;
- }
- if((reg[0] == 'r') || (reg[0] == 'R')) {
- _TCHAR* np = &(p[1]);
- if((np[0] < '0') && (np[0] > '9')) {
- return false;
- }
- _TCHAR regstr[4] = {0};
- for(int i = 0; i < 2; i++) {
- if((np[i] < '0') && (np[i] > '9')) break;
- regstr[i] = np[i];
- }
- if(strlen(regstr) <= 0) {
- return false;
- }
- int regnum = atoi(np);
- if((regnum < 0) || (regnum > 15)) {
- return false;
- }
- // Must apply after update register.
- write_reg(regnum, data);
- return true;
- }
- return false;
-}
-
-void CDROM_CDC::set_volume(int volume)
-{
- volume_l = volume;
- volume_r = volume;
-}
-
-void CDROM_CDC::set_volume(int ch, int decibel_l, int decibel_r)
-{
- volume_l = decibel_l;
- volume_r = decibel_r;
-}
-
-
-
-
-
-
-
-
-
-
+++ /dev/null
-#pragma once
-
-#include "../device.h"
-
-class FMTOWNS::CDROM_SKELON;
-class FIFO;
-
-#define SIG_CDC_DMA_EOT 1
-
-
-#define TOWNS_CDC_RAM_SIZE 8192 // Will be extend for later VMs.
-
-namespace FMTOWNS {
-
-enum WREG_ADDRESS {
- CDC_GENERAL = 0,
- CDC_CMD = 2,
- CDC_PARAM = 4,
- CDC_TRANSFER = 6,
-};
-
-class CDROM_CDC : public DEVICE {
-protected:
- CDROM_SKELTON* d_cdrom;
- DEVICE* d_dmac;
-
- // About STATUS
- int32_t fifo_size;
- int param_ptr;
- uint32_t max_address;
-
- uint8_t ram[TOWNS_CDC_RAM_SIZE];
-
- uint8_t regs[16]; // Registers.
- uint8_t param_queue[8]; // 8 (Ring buffer)
-
- FIFO* status_queue; // 8*100 + 4
-
- // Around CDC's RAM (R/W)
- uint32_t read_ptr;
- uint32_t write_ptr;
- int32_t data_count;
- int32_t data_count_tmp;
-
- int64_t tmp_bytes_count;
-
- // Re-Interpreted around STATUS.
- bool mcu_intr; // 04C0h: bit7
- bool dma_intr; // 04C0h: bit6
- bool pio_transfer_phase; // 04C0h: bit5
- bool dma_transfer_phase; // 04C0h: bit4
-// bool has_status; // 04C0h: bit1
- bool mcu_ready; // 04C0h: bit0
-
- uint8_t last_commnd;
- // Transfer status values.
- bool status_seek;
-
- // Around CD-ROM/DVD-ROM
- int64_t sectors_remain;
- uint64_t target_lba;
-
- bool access_status;
- bool in_track;
- bool enable_prefetch;
-
- // CDDA
- int volume_l;
- int volume_r;
-
- int fadeout_level;
- bool is_plaiing;
-
- pair16_t cdda_camples[2];
-
- int event_seek;
- int event_drq;
- int event_timeout;
- int event_read_wait;
-
- virtual bool seek_to_lba_msf(uint8_t m, uint8_t s, uint8_t s, uint8_t cmdtype);
- virtual pair16_t read_cdda_sample();
- virtual ssize_t read_sectors(int sectors);
- virtual void write_reg(uint8_t num, uint8_t data);
-
- inline bool has_status()
- {
-// if(d_cdrom != nullptr) {
- if(status_queue != nullptr) {
- return (status_queue->empty() == false) ? true : false;
- }
-// }
- return false;
- }
-
- inline bool req_status()
- {
- return (((last_command & 0x20) != 0) ? true : false);
-// return (((regs[CDC_CMD] & 0x20) != 0) ? true : false);
- }
- inline bool stat_reply_intr()
- {
- return (((last_command & 0x40) != 0) ? true : false);
-// return (((regs[CDC_CMD] & 0x40) != 0) ? true : false);
- }
-
- inline bool dma_transfer()
- {
- return (((regs[CDC_TRANSFER] & 0x10) != 0) ? true : false);
- }
- inline bool pio_transfer()
- {
- return (((regs[CDC_TRANSFER] & 0x08) != 0) ? true : false);
- }
-
- inline uint8_t read_data_from_ram()
- {
- uint8_t dat = 0x00;
- if(data_count > 0) {
- dat = ram[read_ptr];
- read_ptr++;
- if(read_ptr >= fifo_size) {
- read_ptr = 0;
- }
- data_count--;
- }
- return dat;
- }
-public:
- CDROM_CDC(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : DEVICE(parent_vm, parent_emu)
- {
- cdrom = NULL;
- param_queue = NULL;
- status_queue = NULL;
- d_cdrom = NULL;
- d_dmac = NULL;
- }
- ~CDROM_CDC()
- {
- close();
- }
-
- virtual void initialize();
- virtual void release();
-
- virtual void reset();
- virtual void event_callback(int event_id, int err);
-
- virtual void mix(int32_t* buffer, int cnt);
- virtual void set_volume(int volume);
- virtual void set_volume(int ch, int decibel_l, int decibel_r);
-
- virtual uint32_t read_debug_data8(uint32_t addr);
- virtual void write_debug_data8(uint32_t addr, uint32_t data);
-
- virtual uint32_t read_dma_io8(uint32_t addr);
- virtual uint32_t read_io8(uint32_t addr);
- virtual void write_io8(uint32_t addr, uint32_t data);
-
-
- virtual void write_signal(int id, uint32_t data, uint32_t mask);
- virtual uint32_t read_signal(int id);
-
- virtual bool mounted();
- virtual bool accessed();
-
- virtual void open(const _TCHAR* file_path);
- virtual void close();
-
- virtual bool get_debug_regs_info(_TCHAR* buffer, size_t buffer_len);
- virtual bool write_debug_reg(_TCHAR* reg, uint32_t data);
-
-
-};
-}
+++ /dev/null
-/*!
- * @file cdrom_cue.cpp
- * @brief Cue methods of new CD-ROM class for eFM-Towns.
- * @author K.Ohta <whatisthis.sowhat _at_ gmail.com>
- * @date 2021-03-17
- * @copyright GPLv2
- */
-#include <cmath>
-#include <stdlib.h>
-#include <cctype>
-
-#include "../../fileio.h"
-#include "./cdrom_cue.h"
-
-/*!
- * @brief constructor
- */
-CDROM_CUE::CDIMAGE_CUE()
-{
-}
-
-/*!
- * @brief de-constructor
- * @note Please implement de-allocating tracks list
- * in de-constructor if you need.
- */
-CDROM_CUE::~CDIMAGE_CUE()
-{
-}
-
-/*!
- * @brief Parse CUE sheet, check track data and construct tracks table.
- * @return true if succeeded.
- * @note Must open sheet file before using.
- * @todo Implement re-calculate multiple tracks inside of ONE IMAGE.
- */
-bool CDROM_CUE::parse_sheet()
-{
- if(!(CDROM_SKELTON::parse_sheet())) return false; // Failed to prepare.
-
- if(sheet_fio->Fseek(0, FILEIO_SEEK_SET) != 0) {
- return false; // Failed to rewined TOP.
- }
- _TCHAR linebuf[1024] = {0};
- int linecount = 0;
- parsed_track = 0;
- current_lba_offset = 0;
- current_lba_size = 0;
- absolute_lba = 0;
- current_bytes_offset = 0;
- current_filename.clear();
- do {
- memset(linebuf, 0x00, sizeof(linebuf));
- if(sheet_fio->Fgets(linebuf, (sizeof(linebuf) / sizeof(_TCHAR)) - 1) == NULL) {
- break; // EOT
- }
- // Parse linebuf
- std::string pstr = linebuf;
- if(pstr.empty()) continue;
-
- std::string ustr = to_upper(pstr); // ToUpper'ed string
- // Tokenize
- bool first = true;
- if(ustr.find(_T("REM")) != basic_string::npos) {
- linecount++;
- continue;
- } else if(ustr.find(_T("FILE")) != basic_string::npos) {
- // Get a file name
- std::string arg1;
- std::string filename;
- std::string s_type;
- int args = parse_args_filename(pstr, arg1, filename, s_type);
- if(args < 2) {
- linecount++;
- continue;
- }
- if(!(filename.empty())) {
- recalc_index_table(parsed_track);
- current_lba_offset = 0;
- current_lba_size = 0;
- current_bytes_offset = 0;
- current_filename = filename;
- first = true;
- }
- } else if(ustr.find(_T("TRACK")) != basic_string::npos) {
- std::string arg1str;
- std::string trackstr;
- std::string typestr;
- if(parse_args_std(ustr, arg1str, trackstr, typestr) < 2) {
- linecount++;
- continue;
- }
- if(!(trackstr.empty())) {
- // Check Track num
- int n = atoi(trackstr.c_str());
- if((n > 0) && (n < 100)) {
- // compare arg3
- bool enabled = false;
- if(typestr.compare(_T("AUDIO")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_AUDIO;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2352;
- toc_table[n].real_physical_size = 2352;
- } else if(typestr.compare(_T("MODE1/2048")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_MODE1_2048;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2048;
- toc_table[n].real_physical_size = 2048;
- } else if(typestr.compare(_T("MODE1/2352")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_MODE1_2352;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2048;
- toc_table[n].real_physical_size = 2352;
- } else if(typestr.compare(_T("MODE2/2336")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_MODE2_2336;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2336;
- toc_table[n].real_physical_size = 2336;
- } else if(typestr.compare(_T("MODE2/2352")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_MODE2_2352;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2336;
- toc_table[n].real_physical_size = 2352;
- } else if(typestr.compare(_T("CDI/2336")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_CDI_2336;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2336;
- toc_table[n].real_physical_size = 2336;
- } else if(typestr.compare(_T("CDI/2352")) == 0) {
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_CDI_2352;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2336;
- toc_table[n].real_physical_size = 2352;
- } else if(typestr.compare(_T("CDG")) == 0) { // OK?
- enabled = true;
- toc_table[n].available = true;
- toc_table[n].type = TRACKTYPE_CDI_2352;
- toc_table[n].physical_size = 2352;
- toc_table[n].logical_size = 2352;
- toc_table[n].real_physical_size = 2352;
- }
- if((enabled) /*|| (first)*/) {
- recalc_index_table(parsed_track);
- absolute_lba += current_lba_size;
- if(!(first)) {
- current_lba_offset += current_lba_size;
- current_bytes_offset += (current_lba_size * toc_table[parsed_track].real_physical_size);
- }
- first = false;
- parsed_track = n;
- }
- }
- }
- } else if(ustr.find(_T("INDEX")) != basic_string::npos) {
- if((parsed_track > 0) && (parsed_track < 100)) {
- std::string arg1str;
- std::string indexstr;
- std::string timestr;
- bool errorval = false;
- if(parse_args_std(ustr, arg1str, indexstr, timestr) < 3) {
- linecount++;
- continue;
- }
- if(indexstr.size() != 2) { //xx
- linecount++;
- continue;
- }
- if((indexstr.empty()) || (timestr.empty())) {
- linecount++;
- continue;
- }
- int indexnum = atoi(indexstr.c_str());
- int64_t framepos = get_frames_from_msfstr(timestr, errorval);
- if(errorval) {
- linecount++;
- continue;
- }
- switch(indexnum) {
- case 0:
- toc_table[parsed_track].index0 = framepos;
- break;
- case 1:
- toc_table[parsed_track].index1 = framepos;
- break;
- }
-// recalc_index_table(parsed_track);
- }
- } else if(ustr.find(_T("PREGAP")) != basic_string::npos) {
- if((parsed_track > 0) && (parsed_track < 100)) {
- std::string arg1str;
- std::string timestr;
- std::string arg3str;
- bool errorval = false;
- if(parse_args_std(ustr, arg1str, timestr, arg3str) < 2) {
- linecount++;
- continue;
- }
- int64_t framepos = get_frames_from_msfstr(timestr, errorval);
- if(errorval) {
- linecount++;
- continue;
- }
- toc_table[parsed_track].pregap = framepos;
- //recalc_index_table(parsed_track);
- }
- }
- linecount++;
- } while(1);
- if(linecount <= 0) return false;
- // Re-Calc last track
- recalc_index_table(parsed_track);
- // Calc tail.
- absolute_lba += current_lba_size;
- current_lba_offset += current_lba_size;
- current_bytes_offset += (current_lba_size * toc_table[parsed_track].real_physical_size);
-
- recalc_index_table(parsed_track + 1);
-
- return true;
-}
-
-/*!
- * @brief RE-Calcurate TOC table.
- * @param num track number.
- */
-void CDROM_CUE::recalc_index_table(int num)
-{
- if((num < 0) || (num > 100)) return;
- int64_t index0 = toc_table[num].index0;
- int64_t index1 = toc_table[num].index1;
- int64_t pregap = toc_table[num].pregap;
- int64_t lbasize = 0;
-
- if(pregap < 150) {
- pregap = 150;
- }
- if(index0 < index1) {
- lbasize = index1 - index0;
- } else if(index0 > index1) {
- lbasize = index0 - index1;
- }
- if(lbasize < pregap) {
- lbasize = 0;
- } else {
- lbasize -= pregap;
- }
-
- if(lbasize < 0) {
- lbasize = 0;
- }
- current_lba_size = lbasize;
-
- toc_table[num].absolute_lba = absolute_lba;
- toc_table[num].lba_offset = current_lba_offset;
- toc_table[num].bytes_offset = current_bytes_offset;
- toc_table[num].lba_size = lbasize;
-
- toc_table[num].pregap = pregap;
- toc_table[num].index0 = index0;
- toc_table[num].index1 = index1;
-
- memset(toc_table[num].filename, 0x00, sizeof(_TCHAR) * _MAX_PATH);
- if(!(current_filename.empty())) {
- current_filename.copy(toc_table[num].filename, _MAX_PATH - 1);
- }
-}
-/*!
- * @brief Parse arguments for filename.
- * @param line source line.
- * @param arg1 answer arg1.
- * @param arg_filename answer arg2 (filename).
- * @param arg_type answer arg3 (type).
- * @return Numbers of arguments.
- * @note arg_filename don't remove delimiters this is for filename contains some space characters.
- */
-int CDROM_CUE::parse_args_filename(std::string line, std::string& arg1, std::string& arg_filename, std::string& arg_type)
-{
- if(line.empty()) return 0;
-
- size_type pos1l = line.find_first_of(_T(" \t\n\r"));
- if(pos1l == basic_string::npos) return 0;
-
- size_type pos2b = line.find_first_not_of(_T(" \t\n\r"), pos1l);
- if(pos2b == basic_string::npos) return 0;
-
- size_type pos2l = line.find_first_of(_T(" \t\n\r"), pos2b);
- if(pos2l == basic_string::npos) {
- pos2l = line.size();
- }
- arg1.substr(line, 0, pos1l);
- if(pos2b >= pos2l) return 1;
- arg2.substr(line, pos2b, pos2l);
- return 2;
-}
-
-/*!
- * @brief Parse arguments.
- * @param line source line.
- * @param arg1 answer arg1.
- * @param arg2 answer arg2.
- * @param arg2 answer arg3.
- * @return Numbers of arguments.
- * @note arguments should be less-equal than 3.
- */
-int CDROM_CUE::parse_args_std(std::string line, std::string& arg1, std::string arg2, std::string arg3)
-{
- if(line.empty()) return 0;
-
- size_type pos1l = line.find_first_of(_T(" \t\n\r"));
- if(pos1l == basic_string::npos) return 0;
-
- size_type pos2b = line.find_first_not_of(_T(" \t\n\r"), pos1l);
- if(pos2b == basic_string::npos) return 0;
-
- size_type pos2l = line.find_first_of(_T(" \t\n\r"), pos2b);
- if(pos2l == basic_string::npos) {
- pos2l = line.size();
- }
-
- arg1.substr(line, 0, pos1l);
- if(pos2b >= pos2l) return 1;
-
- arg2.substr(line, pos2b, pos2l);
-
- size_type pos3b = line.find_first_not_of(_T(" \t\n\r"), pos2l);
- if(pos3b == basic_string::npos){
- return 2;
- }
-
- size_type pos3l = line.find_first_of(_T(" \t\n\r"), pos3b);
- if(pos3l == basic_string::npos) {
- pos3l = line.size();
- }
-
- arg3.substr(line, pos3b, pos3l);
- return 3;
-}
-
+++ /dev/null
-#pragma once
-
-/*!
- * @file cdrom_cue.h
- * @brief CUE CDROM virtual image definitions at new CD-ROM class for eFM-Towns.
- * @author K.Ohta <whatisthis.sowhat _at_ gmail.com>
- * @date 2021-03-11
- * @copyright GPLv2
- */
-#include "./cdrom_skelton.h"
-
-class DLL_PREFIX CDIMAGE_CUE : public CDIMAGE_SKELTON {
-protected:
- int parsed_track;
- uint64_t current_lba_offset;
- uint64_t current_lba_size;
- uint64_t absolute_lba;
- uint64_t current_bytes_offset;
- std::string current_file_name;
- /*!
- * @brief Parse CUE sheet, check track data and construct tracks table.
- * @param filename filename (absolute full path) of sheet (or ISO data).
- * @return true if succeeded.
- * @todo Implement re-calculate multiple tracks inside of ONE IMAGE.
- */
- virtual bool parse_sheet();
- /*!
- * @brief Parse arguments for filename.
- * @param line source line.
- * @param arg1 answer arg1.
- * @param arg_filename answer arg2 (filename).
- * @param arg_type answer arg3 (type).
- * @return Numbers of arguments.
- * @note arg_filename don't remove delimiters this is for filename contains some space characters.
- */
- virtual int parse_args_filename(std::string line, std::string& arg1, std::string& arg_filename, std::string& arg_type);
- /*!
- * @brief Parse arguments.
- * @param line source line.
- * @param arg1 answer arg1.
- * @param arg2 answer arg2.
- * @param arg2 answer arg3.
- * @return Numbers of arguments.
- * @note arguments should be less-equal than 3.
- */
- virtual int parse_args_std(std::string line, std::string& arg1, std::string arg2, std::string arg3);
- /*!
- * @brief RE-Calcurate TOC table.
- * @param num track number.
- */
- virtual void recalc_index_table(int num);
-
-public:
- /*!
- * @brief constructor
- */
- CDIMAGE_CUE();
- /*!
- * @brief de-constructor
- * @note Please implement de-allocating tracks list
- * in de-constructor if you need.
- */
- ~CDIMAGE_CUE();
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
+++ /dev/null
-/*!
- * @file cdrom_skelton.cpp
- * @brief Skelton methods of new CD-ROM class for eFM-Towns.
- * @author K.Ohta <whatisthis.sowhat _at_ gmail.com>
- * @date 2021-03-12
- * @copyright GPLv2
- */
-#include <cmath>
-#include <stdlib.h>
-
-#include "../../fileio.h"
-#include "./cdrom_skelton.h"
-
-/*!
- * @brief constructor
- */
-CDROM_SKELTON::CDIMAGE_SKELTON()
-{
- max_blocks = 0;
- tracks = 0;
- type = CDROM_META::IMAGETYPE_NONE;
- tracktype = CDROM_META::TRACKTYPE_NONE;
- openmode = CDROM_META::OPENMODE_AUTO;
- logical_bytes_per_block = 2048;
- physical_bytes_per_block = 2352;
- real_physical_bytes_per_block = 2352; //!< 2048 if MODE1/ISO.
- allow_beyond_track = false;
- transfer_rate_us = 1.0e6 / 150.0e3; //!< 1.0x 150s
-
- seek_speed = 1.0;
-
- now_lba = 0;
- now_track = 0;
- offset_in_sector = 0;
- lba_offset_of_this_track = 0;
- sectors_of_this_track = 0;
- pregap_of_this_track = 150;
- track_is_available = false;
- bytes_position = 0;
- __filename.erase();
- for(int t = 0; t < 102; i++) {
- init_toc_table(t);
- }
-
- current_fio = NULL;
- sheet_fio = NULL;
-}
-/*!
- * @brief de-constructor
- * @note Please implement de-allocating tracks list
- * in de-constructor if you need.
- */
-CDROM_SKELTON::~CDIMAGE_SKELTON()
-{
- reset_sheet_fio();
-}
-
-/*!
- * @brief initialize function (blank skelton)
- */
-void CDROM_SKELTON::initialize()
-{
-}
-/*!
- * @brief de-initialize function (blank skelton)
- */
-void CDROM_SKELTON::release()
-{
-}
-
-/*!
- * @brief reset status function (blank skelton)
- */
-void CDROM_SKELTON::reset()
-{
-}
-
-/*!
- * @brief Convert BCD value to binary value.
- * @param n BCD value
- * @return Binarized value.-1 if error.
- */
-int CDROM_SKELTON::bcd2bin(uint8_t n, bool& __error)
-{
- return bcd_to_bin(n, __error);
-}
-/*!
- * @brief Convert POSITIVE BINARY value to BCD.
- * @param n Binary value.
- * @param _error Set true if available range (0 to 99) at n.
- * @return BCDed value.
- */
-uint8_t CDROM_SKELTON::bin2bcd(uint8_t n, bool& __error)
-{
- return bin_to_bcd(n, __error);
-}
-
-/*!
- * @brief Calculate LBA position of M,S,F.
- * @param m minutes of LBA.
- * @param s seconds of LBA.
- * @param f frames of LBA.
- * @return LBA position.-1 if error.
- * @note m,s,f must be encoded by BCD.Not binary.
- */
-int64_t CDROM_SKELTON::msf_to_lba(uint8_t m, uint8_t s, uint8_t f) const
-{
- bool _err1, _err2, _err3;
- int64_t mm = bcd_to_bin(m, _err1);
- int64_t ss = bcd_to_bin(s, _err2);
- int64_t ff = bcd_to_bin(f, _err3);
-
- if((_err1) || (_err2) || (_err3)) return -1;
- return ((mm * 60 * 75) + (ss * 75) + ff);
-}
-/*!
- * @brief Calculate M,S,F from LBA position.
- * @param lba LBA position.
- * @param m minutes of LBA.
- * @param s seconds of LBA.
- * @param f frames of LBA.
- * @return true if suceeded.
- * @note m,s,f are encoded by BCD.Not binary.
- */
-bool CDROM_SKELTON::lba_to_msf(int64_t lba, uint8_t& m, uint8_t& s, uint8_t& f) const
-{
- if(lba < 0) return false;
- int64_t mm = lba / (60 * 75);
- int64_t ss;
- int64_t ff;
- bool _error = false;
-
-// ss = (lba - (mm * (60 * 75))) / 75;
-// ff = lba - ((mm * (60 * 75)) + ss * 75);
- ss = (lba / 75) % 60;
- ff = lba % 75;
- if((mm >= 100) || (mm < 0)) return false;
- if((ss >= 60) || (ss < 0)) return false;
- if((ff >= 75) || (ff < 0)) return false;
- m = bin_to_bcd((uint8_t)mm, _error);
- if(_error) return false;
- s = bin_to_bcd((uint8_t)ss, _error);
- if(_error) return false;
- f = bin_to_bcd((uint8_t)ff, _error);
- if(_error) return false;
- return true;
-}
-
-/*!
- * @brief Read TOC/Playing position of used track (BCD Format)
- * @param trk TRACK NUM (0 to 99). If -1 get informations of track now playing.
- * @param pointer of Destination Playing status table buffer.
- * MUST allocate more than sizeof(CDROM_META::cdrom_position_bcd_t).
- * @return true if available this track.
- */
-bool CDROM_SKELTON::get_position_by_bcd(int trk, CDROM_META::cdrom_position_bcd_t* data)
-{
- if(data == nullptr) return false;
- if(trk == -1) {
- if(now_track > 99) return -false;
- if(now_track < 1) return false;
- trk = now_track;
- }
- if((trk < 0) || (trk > 99)) return false;
- if(trk >= tracks) return false;
- if(!(toc_table[trk].available)) return false;
- CDROM_META::cdrom_position_binary_t __data;
-
- memset(((uint8_t*)data), 0x00, sizeof(cdrom_position_bcd_t));
- if(get_position_by_bynary(trk, &__data)) {
- uint8_t m, s, f;
-
- data->trk = __data.trk;
- data->type = __data.type;
-
-// if(!(lba_to_msf(__data.pregap, m, s, f))) {
-// return false;
-// }
- data->pregap_m = m;
- data->pregap_s = s;
- data->pregap_f = f;
-
-// if(!(lba_to_msf(__data.start, m, s, f))) {
-// return false;
-// }
- data->start_m = m;
- data->start_s = s;
- data->start_f = f;
-
-// if(!(lba_to_msf(__data.end, m, s, f))) {
-// return false;
-// }
- data->end_m = m;
- data->end_s = s;
- data->end_f = f;
-
-// if(!(lba_to_msf(__data.abs_pos, m, s, f))) {
-// return false;
-// }
- data->abs_m = m;
- data->abs_s = s;
- data->abs_f = f;
-
-// if(!(lba_to_msf(__data.rel_pos, m, s, f))) {
-// return false;
-// }
- data->rel_m = m;
- data->rel_s = s;
- data->rel_f = f;
- return true;
- }
- return false;
-}
-
-/*!
- * @brief Read TOC/Playing position of used track (BINARY Format)
- * @param trk TRACK NUM (0 to 99). If -1 get informations of track now playing.
- * @param pointer of Destination Playing status table buffer.
- * MUST allocate more than sizeof(CDROM_META::cdrom_position_bcd_t).
- * @return true if available this track.
- */
-bool CDROM_SKELTON::get_position_by_binary(int trk, CDROM_META::cdrom_position_binary_t* data)
-{
- if(data == nullptr) return false;
- if(trk == -1) {
- if(now_track > 99) return -false;
- if(now_track < 1) return false;
- trk = now_track;
- }
- if((trk < 0) || (trk > 99)) return false;
- if(trk >= tracks) return false;
- if(!(toc_table[trk].available)) return false;
-
- memset(((uint8_t*)data), 0x00, sizeof(cdrom_position_binary_t));
-
- int64_t _pregap = toc_table[trk].pregap;
-
- if(_pregap < 0) _pregap = 0; // OK?
- data->trk = trk;
- data->type = toc_table[trk].type;
- data->pregap = _pregap;
- data->start = toc_table[trk].absolute_lba;
-
- int64_t n_size = toc_table[trk].lba_size;
- if(n_size < 1) n_size = 1;
-
- data->end = toc_table[trk].absolute_lba + n_size - 1;
-
- data->abs_pos = 0;
- data->rel_pos = 0;
-
- int64_t rel_lba = now_lba;
- if(rel_lba > 0) {
- if(trk == now_track) {
- data->abs_pos = toc_table[trk].absolute_lba + rel_lba;
- data->rel_pos = rel_lba;
- }
- }
- return true;
-}
-/*!
- * @brief Get TOC table by TRACK (RAW format).
- * @param trk TRACK NUM (0 to 99).
- * @param pointer of Destination TOC buffer.
- * MUST allocate more than sizeof(CDROM_META::cdrom_toc_table_t).
- * @return true if success.
- */
-bool CDROM_SKELTON::get_toc_table(int trk, CDROM_META::cdrom_toc_table_t* data)
-{
- if(data == nullptr) return false;
- if((trk < 0) || (track > 99)) return false;
- if(trk >= tracks) return false;
-
- data->available = toc_table[trk].available;
- data->type = toc_table[trk].type;
- data->absolute_lba = toc_table[trk].absolute_lba;
- data->lba_offset = toc_table[trk].lba_offset;
- data->lba_size = toc_table[trk].lba_size;
- data->index0 = toc_table[trk].index0;
- data->index1 = toc_table[trk].index1;
- data->current_bytes_offset = toc_table[trk].current_bytes_offset;
- data->pregap = toc_table[trk].pregap;
- data->physical_size = toc_table[trk].physical_size;
- data->real_physical_size = toc_table[trk].real_physical_size;
- data->logical_size = toc_table[trk].logical_size;
-
- memset(&(data->filename[0]), 0x00, sizeof(_TCHAR) * _MAX_PATH);
- my_tcscpy_s(&(data->filename[0]), _MAX_PATH - 1, &(toc_table[trk].filename[0]));
- return true;
-}
-
-/*!
- * @brief Open virtual disc image.
- * @param filename Filename of image (absolute path).
- * @param req_type Opening mode.
- * @return true if succeeded.
- *
- * @note Must set disc parameters list only at this function (or sub-functions).
- * @see parse_sheet
- * @see check_type
- */
-bool CDROM_SKELTON::open(_TCHAR *filename, enum CDROM_META::CDIMAGE_OPEN_MODE req_type)
-{
- close();
- if(FILEIO::IsFileExisting(filename)) {
- bool stat = false;
- sheet_fio = new FILEIO();
- if(sheet_fio != nullptr) {
- if(sheet_fio->Fopen(filename, FILEIO_READ_BINARY)) {
- parse_sheet();
- }
- delete sheet_fio;
- sheet_fio = NULL;
- }
- return stat;
- }
- return false;
-}
-/*!
- * @brief Close virtual disc image.
- * @return true if succeeded.
- */
-bool CDROM_SKELTON::close()
-{
- reset_sheet_fio();
- for(uint8_t num = 0; num < 102; num++) {
- init_toc_table(num);
- }
-
- type = CDROM_META::IMAGETYPE_NODE;
- tracktype = CDROM_META::TRACKTYPE_NONE;
- logical_bytes_per_block = 2048;
- physical_bytes_per_block = 2352;
- real_physical_bytes_per_block = 2352;
- track_is_available = false;
- now_lba = 0;
- offset_in_sector = 0;
- bytes_position = 0;
- lba_offset_of_this_track = 0;
-
- sectors_of_this_track = 0;
- pregap_of_this_track = 150;
- __filename.erase();
-
- return true;
-}
-
-/*!
- * @brief Read image data to buffer as CD-ROM/MODE1 from current LBA position.
- * @param buf Destination pointer of read buffer.
- * @param buflen Size of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param _clear true if expect to clear buffer.
- * @return size of reading.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- */
-ssize_t CDROM_SKELTON::read_mode1(uint8_t *buf, ssize_t buflen, size_t sectors, bool _clear)
-{
- if(buf == nullptr) return -1;
- if(buflen <= 0) return -1;
- if(_clear) {
- memset(buf, 0x00, buflen);
- }
-
- if((now_track == 0) || (now_track >= 100)) return -1;
- if(now_track >= tracks) return -1;
-
- if(sectors <= 0) return -1;
- if(current_fio == nullptr) return -1;
- if(!(curent_fio->IsOpened())) return -1;
-
- int64_t logical_size = (int64_t)(sectors * logical_bytes_per_block);
- if(logical_size >= buflen) logical_size = buflen;
- if(logical_size <= 0) return -1;
-
- int xptr = 0;
- /*!
- * @note standard reading function.
- */
- switch(tracktype) {
- case TRACKTYPE_2352_ISO:
- case TRACKTYPE_MODE1_2352:
- {
- CDROM_META::cdrom_data_mode1_t secbuf;
- for(int i = 0; i < sectors; i++) {
- if(xptr >= logical_size) break;
- if(now_lba >= sectors_of_this_track) {
- // SEEK?
- return xptr;
- }
- size_t n = current_fio->Fread((uint8_t*)(&secbuf), sizeof(secbuf), 1);
- now_lba++;
- if(n != sizeof(secbuf)) {
- return xptr;
- }
- // Data OK
- memcpy(&(buf[xptr]), &(secbuf.data[0]), 2048);
- xptr += 2048;
- }
- }
- break;
- case TRACKTYPE_MODE1_2048:
- case TRACKTYPE_MODE1_ISO:
- {
- uint8_t secbuf[2048];
- for(int i = 0; i < sectors; i++) {
- if(xptr >= logical_size) break;
- if(now_lba >= sectors_of_this_track) {
- // SEEK?
- return xptr;
- }
- size_t n = current_fio->Fread((uint8_t*)(secbuf), sizeof(secbuf), 1);
- now_lba++;
- if(n != sizeof(secbuf)) {
- return xptr;
- }
- // Data OK
- memcpy(&(buf[xptr]), secbuf, 2048);
- xptr += 2048;
- }
- }
- break;
- /*
- * If another Image type, return -1.
- */
- default:
- return -1;
- break;
- }
- return logical_size;
-}
-/*!
- * @brief Read image data to buffer as CD-ROM/MODE2 from current LBA position.
- * @param buf Destination pointer of read buffer.
- * @param buflen Size of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param _clear true if expect to clear buffer.
- * @return size of reading.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- */
-ssize_t CDROM_SKELTON::read_mode2(uint8_t *buf, ssize_t buflen, size_t sectors, bool _clear)
-{
- if(buf == nullptr) return -1;
- if(buflen <= 0) return -1;
- if(_clear) {
- memset(buf, 0x00, buflen);
- }
-
- if((now_track == 0) || (now_track >= 100)) return -1;
- if(now_track >= tracks) return -1;
-
- if(sectors <= 0) return -1;
- if(current_fio == nullptr) return -1;
- if(!(curent_fio->IsOpened())) return -1;
-
- int64_t logical_size = (int64_t)(sectors * logical_bytes_per_block);
- if(logical_size >= buflen) logical_size = buflen;
- if(logical_size <= 0) return -1;
-
- int xptr = 0;
- /*!
- * @note standard reading function.
- */
- switch(tracktype) {
- case TRACKTYPE_MODE2_2352:
- case TRACKTYPE_2352_ISO:
- {
- CDROM_META::cdrom_data_mode2_t secbuf;
- for(int i = 0; i < sectors; i++) {
- if(xptr >= logical_size) break;
- if(now_lba >= sectors_of_this_track) {
- // SEEK?
- return xptr;
- }
- size_t n = current_fio->Fread((uint8_t*)(&secbuf), sizeof(secbuf), 1);
-
- now_lba++;
- if(n != sizeof(secbuf)) {
- return xptr;
- }
- // Data OK
- memcpy(&(buf[xptr]), &(secbuf.data[0]), 2336);
- xptr += 2336;
- }
- }
- break;
- case TRACKTYPE_MODE2_ISO:
- case TRACKTYPE_MODE2_2336:
- {
- uint8_t secbuf[2336];
- for(int i = 0; i < sectors; i++) {
- if(xptr >= logical_size) break;
- if(now_lba >= sectors_of_this_track) {
- // SEEK?
- return xptr;
- }
- size_t n = current_fio->Fread((uint8_t*)(secbuf), sizeof(secbuf), 1);
- now_lba++;
- if(n != sizeof(secbuf)) {
- return xptr;
- }
- // Data OK
- memcpy(&(buf[xptr]), secbuf, 2336);
- xptr += 2336;
- }
- }
- break;
- /*
- * If another Image type, return -1.
- */
- default:
- return -1;
- break;
- }
- return logical_size;
-}
-/*!
- * @brief Read image data to buffer as CD-DA from current LBA position.
- * @param buf Destination pointer of read buffer.Must be pair16_t[(2352 / 4) * 2].
- * @param buflen bytes of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param swap_byte true if swap byte order.
- * @param _clear true if expect to clear buffer.
- * @return read samples.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- */
-ssize_t CDROM_SKELTON::read_cdda(pair16_t *buf, ssize_t buflen, size_t sectors, bool swap_byte, bool _clear)
-{
- if(buf == nullptr) return -1;
- if(buflen <= 0) return -1;
- if(_clear) {
- memset(buf, 0x00, buflen);
- }
-
- if((now_track == 0) || (now_track >= 100)) return -1;
- if(now_track >= tracks) return -1;
-
- if(sectors <= 0) return -1;
- if(current_fio == nullptr) return -1;
- if(!(curent_fio->IsOpened())) return -1;
-
- int64_t physical_size = ((int64_t)sectors) * (2352 / 4);
- buflen >>= 2;
- if(physical_size >= buflen) physical_size = buflen;
- if(physical_size <= 0) return -1;
-
- int xptr = 0;
- int64_t xbptr = 0;
- switch(tracktype) {
- case TRACKTYPE_AUDIO:
- case TRACKTYPE_MODE1_2352:
- case TRACKTYPE_MODE2_2352:
- case TRACKTYPE_CDI_2352:
- case TRACKTYPE_2352_ISO:
- {
- __DECL_ALIGNED(8) uint8_t secbuf[2352];
- for(int i = 0; i < sectors; i++) {
- if(xbptr >= physical_size) break;
- if(now_lba >= sectors_of_this_track) {
- // SEEK?
- if(!(allow_beyond_track)) {
- return xbptr;
- } else {
- if(now_track >= 99) return xbptr;
- if(!(get_track_image(now_track + 1))) {
- return xbptr;
- }
- // Refleshed.
- if(!(seek_in_track(pregap_of_this_track))) {
- return xbptr;
- }
- }
- }
- size_t n = current_fio->Fread((uint8_t*)(secbuf), sizeof(secbuf), 1);
- now_lba++;
- if(n != sizeof(secbuf)) {
- return xbptr;
- }
- // Data OK
- xptr = 0;
- if(swap_byte) {
-__DECL_VECTORIZED_LOOP
- for(int j = 0; j < (2352 / 2); j++) {
- buf[j + (xbptr << 1)].b.h = secbuf[xptr];
- buf[j + (xbptr << 1)].b.l = secbuf[xptr + 1];
- xptr += 2;
- }
- } else {
-__DECL_VECTORIZED_LOOP
- for(int j = 0; j < (2352 / 2); j++) {
- buf[j + (xbptr << 1)].b.l = secbuf[xptr];
- buf[j + (xbptr << 1)].b.h = secbuf[xptr + 1];
- xptr += 2;
- }
- }
- xbptr += (2352 / 4);
- }
- }
- break;
- /*!
- * @todo Implement sector size = 2048 or 2336.
- */
- default:
- return -1;
- }
- return xbptr;
-}
-
-/*!
- * @brief Read raw image data to buffer from current LBA position.
- * @param buf Destination pointer of read buffer.
- * @param buflen Size of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param _clear true if expect to clear buffer.
- * @return size of reading.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- * @note Changing size of data by type of Virtual image.
- */
-ssize_t CDROM_SKELTON::read_raw(uint8_t *buf, ssize_t buflen, size_t sectors, bool _clear)
-{
- if(buf == nullptr) return -1;
- if(buflen <= 0) return -1;
- if(_clear) {
- memset(buf, 0x00, buflen);
- }
-
- if((now_track == 0) || (now_track >= 100)) return -1;
- if(now_track >= tracks) return -1;
-
- if(sectors <= 0) return -1;
- if(current_fio == nullptr) return -1;
- if(!(curent_fio->IsOpened())) return -1;
-
- int64_t physical_size = (int64_t)(sectors * physical_bytes_per_block);
- if(physical_size >= buflen) physical_size = buflen;
- if(physical_size <= 0) return -1;
- int xptr = 0;
- uint8_t secbuf[2352];
- int ps = physical_bytes_per_block;
- if(ps >= 2352) ps = 2352;
- if(ps <= 0) {
- return -1;
- }
-
-
- for(int i = 0; i < sectors; i++) {
- if(xptr >= physical_size) break;
- if(now_lba >= sectors_of_this_track) {
- // SEEK?
- if(!(allow_beyond_track)) {
- return xptr;
- } else {
- if(now_track >= 99) return xptr;
- if(!(get_track_image(now_track + 1))) {
- return xptr;
- }
- // Refleshed.
- if(!(seek_in_track(pregap_of_this_track))) {
- return xptr;
- }
- }
- }
- size_t n = current_fio->Fread((uint8_t*)(secbuf), ps, 1);
- now_lba++;
- if(n != ps) {
- return xptr;
- }
- memcpy(&(buf[xptr]), secbuf, ps);
- xptr += ps;
- }
- return physical_size;
-}
-
-/*!
- * @brief Try to seek to expected LBA.
- * @param m minutes of LBA (absolute)
- * @param s seconds of LBA (absolute)
- * @param f frames of LBA (absolute)
- * @param in_track Set true if within track, set false if seek to another track.
- * @return true if succeeded.
- * @note need to implement accross another tracks.
- */
-bool CDROM_SKELTON::seek(uint8_t m, uint8_t s, uint8_t f, bool& in_track)
-{
- int64_t lba = msf_to_lba(m, s, f);
- return seek_absolute_lba(lba);
-}
-/*!
- * @brief Try to seek to expected LBA.
- * @param lba Position of LBA (absolute)
- * @param in_track Set true if within track, set false if seek to another track.
- * @return true if succeeded.
- * @note need to implement accross another tracks.
- */
-bool CDROM_SKELTON::seek_absolute_lba(int64_t lba, bool& in_track)
-{
- if(lba >= max_blocks) {
- lba = max_blocks;
- }
- if(lba < 0) {
- lba = 0;
- }
- uint8_t trk = 0;
- for(int i = 0; i < tracks; i++) {
- if(toc_table[trk + 1].absolute_lba > lba) break;
- trk++;
- }
- if(trk >= tracks) {
- trk = (tracks > 0) ? (tracks - 1) : 0;
- }
- if((trk == 0) || (!(toc_table[trk].available))) {
- if(now_track != 0) {
- in_track = false;
- if(!(allow_beyond_track)) {
- return false;
- }
- }
- get_track_image(0);
- return seek_in_track(0);
- }
- if(trk != now_track) {
- in_track = false;
- now_track = trk;
- if(allow_beyond_track) {
- if(!(get_track_image(now_trk))) { // Seek inner.
- seek_in_track(0);
- return false;
- }
- } else {
- get_track_image(0);
- seek_in_track(0);
- return false;
- }
- } else {
- in_track = true;
- }
- lba = lba - toc_table[now_track].lba_offset;
- if(lba <= 0) {
- lba = 0;
- }
- return seek_in_track(lba);
-}
-/*!
- * @brief Try to seek to expected LBA.
- * @param lba Position of LBA (relative)
- * @param in_track Set true if within track, set false if seek to another track.
- * @return true if succeeded.
- * @note need to implement accross another tracks.
- */
-bool CDROM_SKELTON::seek_relative_lba(int64_t lba, bool& in_track)
-{
- int64_t __lba = lba + now_lba;
- return seek_absolute_lba(__lba, in_track);
-}
-
-
-/*!
- * @brief Calculate seek time to expected LBA.
- * @param m minutes of LBA (absolute)
- * @param s seconds of LBA (absolute)
- * @param f frames of LBA (absolute)
- * @return seek time as usec.
- * If error, return NaN.
- */
-double CDROM_SKELTON::get_seek_time(uint8_t m, uint8_t s, uint8_t f)
-{
- int64_t lba = msf_to_lba(m, s, f);
- return get_seek_time_absolute_lba(lba);
-}
-/*!
- * @brief Calculate seek time to expected LBA.
- * @param lba Position of LBA (absolute)
- * @return seek time as usec.
- * If error, return NaN.
- */
-double CDROM_SKELTON::get_seek_time_absolute_lba(int64_t lba)
-{
- if(lba < 0) {
- return std::nan();
- } else {
- int64_t step = (int64_t)(llabs(lba - now_lba));
- if(step > max_blocks) step = max_blocks;
-
- double _t = (get_single_seek_time_us() * ((double)step));
- return _t;
- }
-}
-/*!
- * @brief Calculate seek time to expected LBA.
- * @param lba Position of LBA (relative)
- * @return seek time as usec.
- * If error, return NaN.
- */
-double CDROM_SKELTON::get_seek_time_relative_lba(int64_t lba)
-{
- int64_t lba2 = llabs(lba);
- if(lba2 > max_blocks) lba2 = max_blocks;
-
- double _t = (get_single_seek_time_us() * ((double)lba2));
- return _t;
-}
-/*!
- * @brief Check type of virtual disc image by filename.
- * @param filename Filename of image (absolute path).
- * @return Type of CD image.
- */
-static enum CDROM_META::CDIMAGE_TYPE CDROM_SKELTON::check_type(_TCHAR *filename)
-{
- if(filename == nullptr) {
- return CDROM_META::IMAGETYPE_NONE;
- }
- if(!(FILEIO::IsFileExisting(filename))) {
- return CDROM_META::IMAGETYPE_NONE;
- }
- if(check_file_extension(filename, _T(".gz"))) {
- if(check_file_extension(filename, _T(".iso.gz"))) {
- return CDROM_META::IMAGETYPE_ISO;
- }
- if(check_file_extension(filename, _T(".cue.gz"))) {
- return CDROM_META::IMAGETYPE_CUE;
- }
- if(check_file_extension(filename, _T(".ccd.gz"))) {
- return CDROM_META::IMAGETYPE_CCD;
- }
- } else {
- if(check_file_extension(filename, _T(".iso"))) {
- return CDROM_META::IMAGETYPE_ISO;
- }
- if(check_file_extension(filename, _T(".cue"))) {
- return CDROM_META::IMAGETYPE_CUE;
- }
- if(check_file_extension(filename, _T(".ccd"))) {
- return CDROM_META::IMAGETYPE_CCD;
- }
- }
- return CDROM_META::IMAGETYPE_NONE; // Write Unique routines to next.
-}
-
-/*!
- * @brief Get Relative LBA offset value (at head of this track) of this image.
- * @return Relative LBA offset value (in image).
- */
-int64_t CDROM_SKELTON::get_lba_offset() const
-{
- return __get_lba_offset();
-}
-/*!
- * @brief Get image type of this virtual CD.
- * @return Image type of virtual CD.
- */
-enum CDROM_META::CDIMAGE_TYPE CDROM_SKELTON::get_type() const
-{
- return __get_type();
-}
-/*!
- * @brief Get track type of this track.
- * @return TRACK TYPE.
- */
-enum CDROM_META::CDIMAGE_TRACK_TYPE CDROM_SKELTON::get_track_type() const
-{
- return __get_track_type();
-}
-/*!
- * @brief Get full path of this virtual image.
- * @param var Returned full path of opened file.Erase if not opened.
- * @return true if already opened.
- */
-bool CDROM_SKELTON::get_track_image_file_name(std::string& var)
-{
- return __get_track_image_file_name(var);
-}
-
-/*!
- * @brief Set seek speed.
- * @param usec Basic transfer time normally 1.0 / 150.0KHz.
- */
-void CDROM_SKELTON::set_transfer_time_us(double usec)
-{
- __set_transfer_time_us(double usec);
-}
-/*!
- * @brief Get transfer time per byte.
- * @return transfer time as uSec.
- */
-double CDROM_SKELTON::get_transfer_time_us()
-{
- return __get_transfer_time_us();
-}
-/*!
- * @brief Get seek multiply rate.
- * @return Seek rate.
- */
-double CDROM_SKELTON::get_seek_speed()
-{
- return __get_seek_speed();
-}
-/*!
- * @brief Get seek time per block.
- * @return seek time as uSec.
- */
-double CDROM_SKELTON::get_single_seek_time_us()
-{
- return __get_single_seek_time_us();
-}
-/*!
- * @brief Set seek speed.
- * @param speed Transfer speed multiply rate, normally 1.0.
- */
-void CDROM_SKELTON::set_seek_speed(double speed)
-{
- __set_seek_speed(speed);
-}
-/*!
- * @brief Set physical bytes per block (in emulation).
- * @param bytes bytes per block.
- */
-void CDROM_SKELTON::set_physical_bytes_per_block(uint32_t bytes)
-{
- __set_physical_bytes_per_block(bytes);
-}
-/*!
- * @brief Set physical bytes per block (in image).
- * @param bytes bytes per block.
- */
-void CDROM_SKELTON::set_real_physical_bytes_per_block(uint32_t bytes)
-{
- __set_real_physical_bytes_per_block(bytes);
-}
-/*!
- * @brief Set logical bytes per block (in emulation).
- * @param bytes bytes per block.
- */
-void CDROM_SKELTON::set_logical_bytes_per_block(uint32_t bytes)
-{
- __set_logical_bytes_per_block(bytes);
-}
-
-/*!
- * @brief Set enable/disable beyond track reading.
- * @param val enable when setting true.
- */
-void CDROM_SKELTON::enable_beyond_track_reading(bool val)
-{
- allow_beyond_track = val;
-}
-
-/*!
- * @brief Get track position now accessing.
- * @return track value.-1 if not avaiable image.
- */
-int CDROM_SKELTON::get_track() const
-{
- return __get_track();
-}
-/*!
- * @brief Get LBA position of now accessing.
- * @return LBA position of now accessing.
- */
-int64_t CDROM_SKELTON::get_lba() const
-{
- return __get_lba();
-}
-/*!
- * @brief Get number of sectors at this track.
- * @return Number of sectors at this track.
- */
-int64_t CDROM_SKELTON::get_sectors_of_this_track() const
-{
- return __get_sectors_of_this_track();
-}
-/*!
- * @brief Get current position-offset in this sector.
- * @return Offset position.
- */
-int CDROM_SKELTON::get_offset_of_this_sector() const
-{
- return __get_offset_of_this_sector();
-}
-/*!
- * @brief Whether this track is available.
- * @return true if available.
- */
-bool CDROM_SKELTON::is_available() const
-{
- return __is_available();
-}
-/*!
- * @brief Get blocks of this virtual CD.
- * @return Blocks (sectors) of this virtual CD.
- */
-int64_t CDROM_SKELTON::get_blocks() const
-{
- return __get_blocks();
-}
-/*!
- * @brief Get physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
-uint32_t CDROM_SKELTON::get_physical_block_size() const
-{
- return __get_physical_block_size();
-}
-/*!
- * @brief Get REAL (in VIRTUAL IMAGE) physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
-uint32_t CDROM_SKELTON::get_real_physical_block_size() const
-{
- return __get_real_physical_block_size();
-}
-/*!
- * @brief Get logical block size of this virtual CD.
- * @return Logical block size of this virtual CD.
- */
-uint32_t CDROM_SKELTON::get_logical_block_size() const
-{
- return __get_logical_block_size();
-}
-
-/*!
- * @brief Parse CUE/CCD sheet, check track data and construct tracks table.
- * @return true if succeeded.
- * @note Must open sheet file before using.
- * @note Initialize TOC table when calling.
- */
-bool CDROM_SKELTON::parse_sheet()
-{
- for(int trk = 0; trk < 102; trk++) {
- init_toc_table(trk);
- }
- return true;
-}
-
-/*!
- * @brief Load / Save state(TOC table part) to VM.
- * @param state_fio FILE IO for state loading/saving.
- * @param loading If true loading, false is saving.
- * @return true if succeeded.
- */
-bool CDROM_SKELTON::load_save_toc_table(FILEIO* state_fio, bool loading)
-{
- uint8_t ntracks = 0;
- if(loading) {
- ntracks = state_fio->FgetUint8();
- if(ntracks >= 101) return false;
- } else {
- ntracks = tracks;
- if(ntracks >= 101) return false;
- state_fio->FputUint8(tracks);
- }
- uint8_t n = 0;
- for(int i = 1; i <= ntracks; i++) {
- if(loading) {
- n = state_fio->FgetUint8(); //!< Get track number
- if(n != i) return false; //!< Error when wrong filename.
- } else {
- state_fio->FputUint8((uint8_t)i);
- }
- state_fio->StateValue(toc_table[i].available);
- state_fio->StateValue(toc_table[i].type);
- state_fio->StateValue(toc_table[i].pregap);
- state_fio->StateValue(toc_table[i].absolute_lba);
- state_fio->StateValue(toc_table[i].lba_offset);
- state_fio->StateValue(toc_table[i].lba_size);
- state_fio->StateValue(toc_table[i].index0);
- state_fio->StateValue(toc_table[i].index1);
- state_fio->StateValue(toc_table[i].physical_size);
- state_fio->StateValue(toc_table[i].real_physical_size);
- state_fio->StateValue(toc_table[i].logical_size);
- state_fio->StateArray(toc_table[i].filename, _MAX_PATH, 1);
- }
- if(loading) {
- tracks = ntracks;
- /*
- * clear TRACK 00.
- */
- init_toc_table(0);
- if(tracks > 1) {
- toc_table[0].available = true;
- } else {
- toc_table[0].available = false;
- }
- }
- return true;
-}
-
-/*!
- * @brief Seek assigned position in track.
- * @param lba *Relative* LBA in this track.
- * @return true if success.
- */
-bool CDROM_SKELTON::seek_in_track(int64_t lba)
-{
- if(lba < 0) return false;
- if((now_track < 0) || (now_track >= 100)) return false;
-
- int64_t _lba_bak = lba + lba_offset_of_this_track;
- if(current_fio == nullptr) return true;
-
- int64_t lba_max = sectors_of_this_track + lba_offset_of_this_track;
- int64_t lba_min = lba_offset_of_this_track;
- if(lba_min < 0) lba_min = 0;
- if(lba_max < 0) lba_max = 0;
- lba = lba + lba_offset_of_this_track;
-
- if(lba >= lba_max) return false;
- if(lba < lba_min) return false;
- if(pregap_of_this_track < 0) return false; // Illegal PREGAP
-
- lba = lba - pregap_of_this_track;
- if(lba < 0) lba = 0;
-
- int64_t offset = lba * get_real_physical_block_size();
-
- if(offset >= LONG_MAX) {
- bytes_position = 0;
- offset_in_sector = 0;
- return false;
- }
- if(current_fio->Fseek(offset, FILEIO_SEEK_SET) != 0) {
- bytes_position = 0;
- offset_in_sector = 0;
- return false;
- }
- now_lba = _lba_bak;
- bytes_position = offset;
- offset_in_sector = 0;
- return true;
-}
-/*!
- * @brief Get image data of track.
- * @param track track number.
- * return true if success.
- */
-bool CDROM_SKELTON::get_track_image(uint8_t track)
-{
- bool result = false;
- if(track >= tracks) track = tracks;
- /*
- * Set default values
- */
- tracktype = CDROM_META::TRACKTYPE_NONE;
- logical_bytes_per_block = 2048;
- physical_bytes_per_block = 2352;
- real_physical_bytes_per_block = 2352;
- track_is_available = false;
- now_lba = 0;
- offset_in_sector = 0;
- bytes_position = 0;
- lba_offset_of_this_track = 0;
-
- sectors_of_this_track = 0;
- pregap_of_this_track = 150;
-
- __filename.erase();
-
- if(current_fio != nullptr) {
- if(current_fio->IsOpened()) {
- current_fio->Fclose();
- }
- delete curent_fio;
- current_fio = NULL;
- }
- if(track >= 100) {
- return false;
- }
-
- if(now_track != track) {
- now_track = track;
- }
- if(!(toc_table[track].available)) {
- return false;
- }
- if(strlen(toc_table[track].filename) > 0) {
- current_fio = new FILEIO();
- if(current_fio != nullptr) {
- result = current_fio->Fopen(toc_table[track].filename, FILEIO_READ_BINARY);
- }
- if(result) {
- __filename.assign(toc_table[track].filename, _MAX_PATH);
- }
- }
- if(result) {
- tracktype = toc_table[now_track].type;
- logical_bytes_per_block = toc_table[now_track].logical_size;
- physical_bytes_per_block = toc_table[now_track].physical_size;
- real_physical_bytes_per_block = toc_table[now_track].real_physical_size;
- track_is_available = toc_table[now_track].available;
- now_lba = toc_table[now_track].lba_offset;
- offset_in_sector = 0;
- bytes_position = 0;
- lba_offset_of_this_track = toc_table[now_track].lba_offset;
- sectors_of_this_track = toc_table[now_track].lba_size;
- pregap_of_this_track = toc_table[now_track].pregap;
- }
- return false;
-}
-/*!
- * @brief reset FILEIOs for sheet and image.
- */
-void CDROM_SKELTON::reset_sheet_fio()
-{
- if(current_fio != nullptr) {
- if(current_fio->IsOpened()) {
- current_fio->Fclose();
- }
- delete current_fio;
- current_fio = NULL;
- }
- if(sheet_fio != nullptr) {
- if(sheet_fio->IsOpened()) {
- sheet_fio->Fclose();
- }
- delete sheet_fio;
- sheet_fio = NULL;
- }
-}
-
-/*!
- * @brief To be Upper characters from string.
- * @param s source string.
- * @return ToUpper'ed string.
- */
-static std::string CDROM_SKELTON::to_upper(std::string s)
-{
- std::string rets;
-
- rets.clear();
- if(!(s.empty())) {
- for(auto c = s.begin(); c != s.end(); ++c) {
- _TCHAR n = std::toupper(*c);
- rets.push_back(n);
- }
- }
- return rets;
-}
-/*!
- * @brief Get uint value from BCD string.
- * @param s source string
- * @param errorval set true if wrong string value.
- * @return Value if success, 0 if not.
- */
-static uint64_t CDROM_SKELTON::get_val_from_bcdstr(std::string s, bool& errorval)
-{
- int pos = 0;
- uint64_t rval = 0;
- int pval;
- for(auto c = s.begin(); c != s.end() ; ++c) {
- char cc = *c;
- if((cc < '0') || (cc > '9')) {
- break;
- }
- rval = rval * 10;
- pval = cc - '0';
- rval = rval + pval;
- pos++;
- }
- if(pos < 1) {
- errorval = true;
- return 0;
- }
- errorval = false;
- return rval;
-}
-
-/*!
- * @brief Get uint value from HEXADECIMAL string.
- * @param s source string
- * @param errorval set true if wrong string value.
- * @return Value if success, 0 if not.
- */
-static uint64_t CDROM_SKELTON::get_val_from_hexstr(std::string s, bool& errorval)
-{
- int pos = 0;
- uint64_t rval = 0;
- int pval;
- for(auto c = s.begin(); c != s.end() ; ++c) {
- char cc = *c;
- bool is_val = false;
- if((cc >= '0') && (cc <= '9')) {
- is_val = true;
- pval = cc - '0';
- } else if((cc >= 'A') && (cc <= 'F')) {
- is_val = true;
- pval = cc - 'A';
- } else if((cc >= 'a') && (cc <= 'f')) {
- is_val = true;
- pval = cc - 'a';
- }
- if(!(is_val)) {
- break;
- }
- rval = rval << 4;
- rval = rval + pval;
- pos++;
- }
- if(pos < 1) {
- errorval = true;
- return 0;
- }
- errorval = false;
- return rval;
-}
-
-/*!
- * @brief Decode frame value from MSF string.
- * @param timestr Time string. Encoded by "xx:xx:xx". xx must be BCD value.
- * @param errorval true if wrong string.
- * @return value if success, 0 when failed.
- */
-static uint64_t CDROM_SKELTON::get_frames_from_msfstr(std::string timestr, bool &errorval)
-{
- if(timestr.size() < 8) { //xx:xx:xx
- errorval = true;
- return 0;
- }
- std::string s_m = timnestr.substr(0, 2);
- std::string _d1 = timnestr.substr(2, 1);
- std::string s_s = timnestr.substr(3, 2);
- std::string _d2 = timnestr.substr(5, 1);
- std::string s_f = timnestr.substr(6, 2);
-
- if((_d1 != ":") || (_d2 != ":")) {
- // delimiter(s) not found
- errorval = true;
- return 0;
- }
- bool error1, error2, error3;
- error1 = false;
- error2 = false;
- error3 = false;
- uint64_t mm = get_val_from_bcdstr(s_m, error1);
- uint64_t ss = get_val_from_bcdstr(s_s, error2);
- uint64_t ff = get_val_from_bcdstr(s_f, error3);
- if((error1) || (error2) || (error3)) {
- errorval = true;
- return 0;
- }
- if(mm > 99) {
- errorval = true;
- return 0;
- }
- if(ss > 59) {
- errorval = true;
- return 0;
- }
- if(ff > 74) {
- errorval = true;
- return 0;
- }
- uint64_t nt = (mm * 60 * 75) + (ss * 75) + ff;
- errorval = false;
- return nt;
-}
-
-
-#define STATE_VERSION 1
-/*!
- * @brief Load / Save state(main part) to VM.
- * @param state_fio FILE IO for state loading/saving.
- * @param loading If true loading, false is saving.
- * @return true if succeeded.
- */
-bool CDROM_SKELTON::load_save_params(FILEIO* state_fio, bool loading)
-{
- if(!state_fio->StateCheckUint32(STATE_VERSION)) {
- return false;
- }
- // device id is not exists.
- state_fio->StateValue(type);
- state_fio->StateValue(tracks);
- state_fio->StateValue(tracktype);
- state_fio->StateValue(openmode);
- state_fio->StateValue(logical_bytes_per_block);
- state_fio->StateValue(physical_bytes_per_block);
- state_fio->StateValue(real_physical_bytes_per_block);
- state_fio->StateValue(max_blocks);
-
- state_fio->StateValue(transfer_time_us);
- state_fio->StateValue(seek_speed);
-
- state_fio->StateValue(allow_beyond_track);
-
- state_fio->StateValue(track_is_available);
- state_fio->StateValue(now_track);
- state_fio->StateValue(now_lba);
- state_fio->StateValue(bytes_position);
- state_fio->StateValue(offset_in_sector);
- state_fio->StateValue(lba_offset_of_this_track);
- state_fio->StateValue(sectors_of_this_track);
- state_fio->StateValue(pregap_of_this_track);
-
- int strsize = 0;
- _TCHAR _l[_MAX_PATH] = {0};
- if(loading) {
- strsize = state_fio->FgetInt32_LE();
- if(strsize < 0) return false;
-
- __filename.clear();
- state_fio->StateArray(_l, _MAX_PATH, 1);
- __filename.assign(_l, _MAX_PATH - 1);
- } else {
- strsize = __filename.length();
- if(strsize < 0) strsize = 0;
- state_fio->FputInt32_LE(strsize);
- __filename.copy(_l, _MAX_PATH - 1);
- state_fio->StateArray(_l, _MAX_PATH, 1);
- }
- return true;
-}
-
-/*!
- * @brief Initialize TOC table..
- * @param num track number.
- */
-void CDROM_SKELTON::init_toc_table(uint8_t num)
-{
- if(num > 101) return;
-
- toc_table[num].available = false;
- toc_table[num].type = CDROM_META::TRACKTYPE_NONE;
- toc_table[num].pregap = 0;
- toc_table[num].absolute_lba = 0;
- toc_table[num].lba_offset = 0;
- toc_table[num].lba_size = 0;
- toc_table[num].index0 = 0;
- toc_table[num].index1 = 0;
- toc_table[num].physical_size = 2352;
- toc_table[num].logical_size = 2048;
- toc_table[num].real_physical_size = 2352;
- toc_table[num].current_bytes_offset = 0;
-
- memset(toc_table[num].filename, 0x00, sizeof(_TCHAR) * _MAX_PATH);
-}
-
-/*!
- * @brief Load / Save state to VM.
- * @param state_fio FILE IO for state loading/saving.
- * @param loading If true loading, false is saving.
- * @return true if succeeded.
- */
-bool CDROM_SKELTON::process_state(FILEIO* state_fio, bool loading)
-{
- /*!
- * @note Must place checking STATE_VERSION and MAGIC for unique image type..
- */
- if(!(load_save_params(state_fio, loading))) {
- return false;
- }
- if(!(load_save_toc_table(state_fio, loading))) {
- return false;
- }
- /*
- * please place state procesing for unuque values below.
- */
- return true;
-}
+++ /dev/null
-#pragma once
-
-/*!
- * @file cdrom_skelton.h
- * @brief Skelton definitions of new CD-ROM class for eFM-Towns.
- * @author K.Ohta <whatisthis.sowhat _at_ gmail.com>
- * @date 2021-03-04
- * @copyright GPLv2
- */
-#include "../../common.h"
-#include <string>
-class FILEIO;
-
-namespace CDROM_META { // BEGIN OF NAMESPACE CDROM_META .
-/*!
- * @enum Image type of current virtual CD image.
- */
-typedef enum CDIMAGE_TYPE {
- IMAGETYPE_NONE = 0,
- IMAGETYPE_ISO,
- IMAGETYPE_CUE,
- IMAGETYPE_CCD
-}
-/*!
- * @enum Track type of opening virtual CD image.
- */
-typedef enum CDIMAGE_TRACK_TYPE {
- TRACKTYPE_NONE = 0, //!< NONE OPENING TYPE
- TRACKTYPE_AUDIO, //!< Open as audio
- TRACKTYPE_MODE1_2048, //!< MODE1/2048
- TRACKTYPE_MODE1_2352, //!< MODE1/2352
- TRACKTYPE_MODE1_ISO, //!< MODE1/ISO (2048 bytes/sector)
- TRACKTYPE_MODE2_2336, //!< MODE2/2336
- TRACKTYPE_MODE2_2352, //!< MODE2/2352
- TRACKTYPE_MODE2_ISO, //!< MODE2/ISO (2336 bytes/sector)
- TRACKTYPE_2352_ISO, //!< ISO (2352 bytes/sector)
- TRACKTYPE_CDI_2336, //!< CD-I/2336
- TRACKTYPE_CDI_2352, //!< CD-I/2352
- TRACKTYPE_CDG, //!< CD/G
-}
-
-/*!
- * @enum Opening modes of virtual CD image.
- */
-typedef enum CDIMAGE_OPEN_MODE {
- OPENMODE_AUDIO, //!< AUDIO
- OPENMODE_MODE1, //!< MODE1
- OPENMODE_MODE2, //!< MODE2
- OPENMODE_CDI, //!< CD-I
- OPENMODE_CDG //!< CD/G
-}
-
-/*!
- * @note Belows are CD-ROM sector structuer.
- * @note See https://en.wikipedia.org/wiki/CD-ROM#Sector_structure .
- */
-
-#pragma pack(1)
-/*!
- * @struct definition of SUBC field of CD-ROM.
- */
-typedef union {
- struct {
- uint8_t P:1;
- uint8_t Q:1;
- uint8_t R:1;
- uint8_t S:1;
- uint8_t T:1;
- uint8_t U:1;
- uint8_t V:1;
- uint8_t W:1;
- } bit;
- uint8_t byte;
-} cdrom_SUBC_t;
-#pragma pack()
-
-#pragma pack(1)
-/*!
- * @struct definition of CD-ROM data header (excepts audio track).
- */
-typedef struct {
- uint8_t sync[12]; //!< SYNC BYTES (Mostly 00h * 12?)
- uint8_t addr_m; //!< Minute as BCD
- uint8_t addr_s; //!< Second as BCD
- uint8_t addr_f; //!< Frame as BCD
- uint8_t sector_type; //!< 1 = MODE1, 2=MODE2
-} cdrom_data_head_t;
-#pragma pack()
-
-#pragma pack(1)
-/*!
- * @struct definition of CD-ROM MODE1 sector struct (excepts ISO image).
- * @note ToDo: Still not implement crc32 and ecc.
- * @note 20201116 K.O
- */
-typedef struct {
- cdrom_data_head_t header; //!< HEADER
- uint8_t data[2048]; //!< DATA field (2048bytes)
- uint8_t crc32[4]; //!< CRC32 checksum.
- uint8_t reserved[8]; //!< Reserved
- uint8_t ecc[276]; //! ERROR CORRECTIOM DATA; by read solomon code.
-} cdrom_data_mode1_t;
-#pragma pack()
-
-#pragma pack(1)
-/*!
- * @struct definition of CD-ROM MODE2 sector struct (excepts ISO image).
- */
-typedef struct {
- cdrom_data_head_t header; //!< HEADER
- uint8_t data[2336]; //!< DATA field 2336 bytes
-} cdrom_data_mode2_t;
-#pragma pack()
-
-#pragma pack(1)
-/*!
- * @struct definition of CD-DA sector struct (excepts ISO image).
- */
-typedef struct {
- uint8_t data[2352]; //!< DATA field (without HEADER) 2352 bytes, without ECCs.
-} cdrom_audio_sector_t;
-#pragma pack()
-
-#pragma pack(1)
-/*!
- * @struct definition of CDROM RAW sector struct (excepts ISO image).
- */
-typedef struct {
- uint8_t data[2352]; //!< RAW DATA field.
-} cdrom_raw_sector_t;
-#pragma pack()
-
-#pragma pack(1)
-/*!
- * @struct definition of DATA field for ISO.
- * @note ToDo: Add fake header and crc and ecc.
- * @note 20201116 K.O
- */
-typedef struct {
- uint8_t data[2048]; //!< AT ISO virtual image, contains only data sector.
-} cdrom_iso_data_t;
-#pragma pack()
-
-/*!
- * @struct definition of track table.
- * @note 20210311 K.O
- */
-typedef struct {
- bool available; //!< indicate this track is available.
- uint8_t type; //!< track type (enum CDIMAGE_TRACK_TYPE)
- int64_t pregap; //!< pregap value
- int64_t absolute_lba; //!< absolute lba position.
- int64_t lba_offset; //!< LBA offset Within a image.
- int64_t lba_size; //!< LBA size of track.
- int64_t index0; //!< INDEX0 (relative)
- int64_t index1; //!< INDEX1 (relative)
- uint64_t current_bytes_offset; //!< CURRENT BYTES OFFSET INSIDE OF THIS IMAGE.
- uint32_t physical_size; //!< Physical sector size
- uint32_t real_physical_size; //!< Real physical sector size
- uint32_t logial_size; //!< Logical sector size
- _TCHAR filename[_MAX_PATH]; //!< Image file name.
-} cdrom_toc_table_t;
-
-/*!
- * Information of PLaying position and a track (BCD Format).
- * This is useful to read TOC and to make SUBQ.
- */
-typedef struct {
- //!< Current track information.
- uint8_t trk; //!< 0-99 : Available / 0xff: Unavailable (BCD Value).
- uint8_t type; //!< enum CDROM_META::CDIMAGE_TRACK_TYPE
-
- uint8_t pregap_m; //!< Pregap of track ; minutes (BCD Value).
- uint8_t pregap_s; //!< Pregap of track ; seconds (BCD Value).
- uint8_t pregap_f; //!< Pregap of track ; frames (BCD Value).
-
- uint8_t start_m; //!< Start of track ; minutes (BCD Value).
- uint8_t start_s; //!< Start of track ; seconds (BCD Value).
- uint8_t start_f; //!< Start of track ; frames (BCD Value).
-
- uint8_t end_m; //!< End of track ; minutes (BCD Value).
- uint8_t end_s; //!< End of track ; seconds (BCD Value).
- uint8_t end_f; //!< End of track ; frames (BCD Value).
- //!< Belows are frame position(s).
- uint8_t abs_m; //!< Relative minutes from start of track (BCD Value).
- uint8_t abs_s; //!< Relative seconds from start of track (BCD Value).
- uint8_t abs_f; //!< Relative frames from start of track (BCD Value).
-
- uint8_t rel_m; //!< Relative minutes from start of track (BCD Value).
- uint8_t rel_s; //!< Relative seconds from start of track (BCD Value).
- uint8_t rel_f; //!< Relative frames from start of track (BCD Value).
-} cdrom_position_bcd_t;
-
-/*!
- * Information of PLaying position and a track (Binary Format).
- * This is useful to read TOC and to make SUBQ.
- */
-typedef struct {
- uint8_t trk; //!< 0-99 : Available / 0xff: Unavailable (BCD Value).
- uint8_t type; //!< enum CDROM_META::CDIMAGE_TRACK_TYPE
- int pregap; //!< Pregap value.
- int64_t start; //!< Start LBA Position.
- int64_t end; //!< End LBA Position. (start + SIZE - 1).
- //!< Belows are frame position(s).
- uint64_t abs_pos; //!< Absolute LBA Position.
- uint64_t rel_pos; //!< Relative LBA Position.
-} cdrom_position_binary_t;
-
-} // END OF NAMESPACE CDROM_META .
-
-/*!
- * @class BASIC class of CD Image.
- * @note You must add list of tracks.
- */
-class DLL_PREFIX CDIMAGE_SKELTON {
-protected:
- FILEIO* current_fio;
- FILEIO* sheet_fio;
-
- uint8_t type; //!< enum CDIMAGE_TYPE
- uint8_t tracks; //!< 00-99. (Maybe)
- uint8_t tracktype; //!< enum CDIMAGE_TRACK_TYPE
- uint8_t openmode; //!< enum CDIMAGE_OPENMODE
-
- CDROM_META::cdrom_toc_table_t toc_table[102];
- uint32_t logical_bytes_per_block;
- uint32_t physical_bytes_per_block;
- uint32_t real_physical_bytes_per_block;
- int64_t max_blocks;
- bool allow_beyond_track; //!< allow over track reading.
-
- double transfer_time_us;
- double seek_speed;
- /*!
- * @note belows are status value.
- * Not table values.
- */
- bool track_is_available;
- uint8_t now_track; //! @note 00 - 99.
- int64_t now_lba;
- uint32_t offset_in_sector;
- int64_t bytes_position;
- int64_t lba_offset_of_this_track;
- int64_t sectors_of_this_track;
- int64_t pregap_of_this_track;
- std::string __filename;
-
- /*!
- * @brief Parse CUE/CCD sheet, check track data and construct tracks table.
- * @return true if succeeded.
- * @note Must open sheet file before using.
- * @note Initialize TOC table when calling.
- */
- virtual bool parse_sheet();
- /*!
- * @brief Load / Save state(TOC table part) to VM.
- * @param state_fio FILE IO for state loading/saving.
- * @param loading If true loading, false is saving.
- * @return true if succeeded.
- */
- virtual bool load_save_toc_table(FILEIO* state_fio, bool loading);
- /*!
- * @brief Load / Save state(main part) to VM.
- * @param state_fio FILE IO for state loading/saving.
- * @param loading If true loading, false is saving.
- * @return true if succeeded.
- */
- virtual bool load_save_params(FILEIO* state_fio, bool loading);
- /*!
- * @brief Initialize TOC table..
- * @param num track number.
- */
- virtual void init_toc_table(uint8_t num);
- /*!
- * @brief Convert BCD value to binary value.
- * @param n BCD value
- * @return Binarized value.-1 if error.
- */
- inline int bcd_to_bin(uint8_t n, bool& __error);
- /*!
- * @brief Convert POSITIVE BINARY value to BCD.
- * @param n Binary value.
- * @param _error Set true if available range (0 to 99) at n.
- * @return BCDed value.
- */
- inline uint8_t bin_to_bcd(uint8_t n, bool& __error);
-
- /*!
- * @brief Get track position now accessing.
- * @return track value.-1 if not avaiable image.
- */
- inline int __get_track() const;
- /*!
- * @brief Get LBA position of now accessing.
- * @return LBA position of now accessing.
- */
- inline int64_t __get_lba() const;
- /*!
- * @brief Get Relative LBA offset value (at head of this track) of this image.
- * @return Relative LBA offset value (in image).
- */
- inline int64_t __get_lba_offset() const;
- /*!
- * @brief Get number of sectors at this track.
- * @return Number of sectors at this track.
- */
- inline int64_t __get_sectors_of_this_track() const;
- /*!
- * @brief Get current position-offset in this sector.
- * @return Offset position.
- */
- inline int __get_offset_of_this_sector() const;
- /*!
- * @brief Whether this track is available.
- * @return true if available.
- */
- inline bool __is_available() const;
- /*!
- * @brief Get blocks of this virtual CD.
- * @return Blocks (sectors) of this virtual CD.
- */
- inline int64_t __get_blocks() const;
- /*!
- * @brief Get physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
- inline uint32_t __get_physical_block_size() const;
- /*!
- * @brief Get REAL (in VIRTUAL IMAGE) physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
- inline uint32_t __get_real_physical_block_size() const;
- /*!
- * @brief Get logical block size of this virtual CD.
- * @return Logical block size of this virtual CD.
- */
- inline uint32_t __get_logical_block_size() const;
- /*!
- * @brief Get image type of this virtual CD.
- * @return Image type of virtual CD.
- */
- inline enum CDROM_META::CDIMAGE_TYPE __get_type() const;
- /*!
- * @brief Get track type of this track.
- * @return TRACK TYPE.
- */
- inline enum CDROM_META::CDIMAGE_TRACK_TYPE __get_track_type() const;
- /*!
- * @brief Get full path of this virtual image.
- * @param var Returned full path of opened file.Erase if not opened.
- * @return true if already opened.
- */
- inline bool __get_track_image_file_name(std::string& var);
-
-
- /*!
- * @brief Set seek speed.
- * @param usec Basic transfer time normally 1.0 / 150.0KHz.
- */
- inline void __set_transfer_time_us(double usec);
- /*!
- * @brief Get transfer time per byte.
- * @return transfer time as uSec.
- */
- inline double __get_transfer_time_us();
- /*!
- * @brief Get seek multiply rate.
- * @return Seek rate.
- */
- inline double __get_seek_speed();
-
- /*!
- * @brief Seek assigned position in track.
- * @param lba *Relative* LBA in this track.
- * @return true if success.
- */
- virtual bool seek_in_track(int64_t lba);
- /*!
- * @brief Get image data of track.
- * @param track track number.
- * return true if success.
- */
- virtual bool get_track_image(uint8_t track);
- /*!
- * @brief reset FILEIOs for sheet and image.
- */
- virtual void reset_sheet_fio();
-public:
- /*!
- * @brief constructor
- */
- CDIMAGE_SKELTON();
- /*!
- * @brief de-constructor
- * @note Please implement de-allocating tracks list
- * in de-constructor if you need.
- */
- ~CDIMAGE_SKELTON();
-
- /*!
- * @brief initialize function (blank skelton)
- */
- virtual void initialize();
- /*!
- * @brief de-initialize function (blank skelton)
- */
- virtual void release();
- /*!
- * @brief reset status function (blank skelton)
- */
- virtual void reset();
-
- /*!
- * @brief Get Relative LBA offset value (at head of this track) of this image.
- * @return Relative LBA offset value (in image).
- */
- virtual int64_t get_lba_offset() const;
- /*!
- * @brief Get track type of this track.
- * @return TRACK TYPE.
- */
- virtual enum CDROM_META::CDIMAGE_TRACK_TYPE get_track_type() const;
- /*!
- * @brief Get image type of this virtual CD.
- * @return Image type of virtual CD.
- */
- virtual enum CDROM_META::CDIMAGE_TYPE get_type() const;
- /*!
- * @brief Get full path of this virtual image.
- * @param var Returned full path of opened file.Erase if not opened.
- * @return true if already opened.
- */
- virtual bool get_track_image_file_name(std::string& var);
-
- /*!
- * @brief Set seek speed.
- * @param usec Basic transfer time normally 1.0 / 150.0KHz.
- */
- virtual void set_transfer_time_us(double usec);
- /*!
- * @brief Get transfer time per byte.
- * @return transfer time as uSec.
- */
- virtual double get_transfer_time_us();
- /*!
- * @brief Get seek multiply rate.
- * @return Seek rate.
- */
- virtual double get_seek_speed();
- /*!
- * @brief Get seek time per block.
- * @return seek time as uSec.
- */
- virtual double get_single_seek_time_us();
- /*!
- * @brief Set seek speed.
- * @param speed Transfer speed multiply rate, normally 1.0.
- */
- virtual void set_seek_speed(double speed);
- /*!
- * @brief Set physical bytes per block (in emulation).
- * @param bytes bytes per block.
- */
- virtual void set_physical_bytes_per_block(uint32_t bytes);
- /*!
- * @brief Set physical bytes per block (in image).
- * @param bytes bytes per block.
- */
- virtual void set_real_physical_bytes_per_block(uint32_t bytes);
- /*!
- * @brief Set logical bytes per block (in emulation).
- * @param bytes bytes per block.
- */
- virtual void set_logical_bytes_per_block(uint32_t bytes);
-
- /*!
- * @brief Convert BCD value to binary value.
- * @param n BCD value
- * @return Binarized value.-1 if error.
- */
- virtual int bcd2bin(uint8_t n, bool& __error);
- /*!
- * @brief Convert POSITIVE BINARY value to BCD.
- * @param n Binary value.
- * @param _error Set true if available range (0 to 99) at n.
- * @return BCDed value.
- */
- virtual uint8_t bin2bcd(uint8_t n, bool& __error);
- /*!
- * @brief Calculate LBA position of M,S,F.
- * @param m minutes of LBA.
- * @param s seconds of LBA.
- * @param f frames of LBA.
- * @return LBA position.-1 if error.
- * @note m,s,f must be encoded by BCD.Not binary.
- */
- virtual int64_t msf_to_lba(uint8_t m, uint8_t s, uint8_t f) const;
- /*!
- * @brief Calculate M,S,F from LBA position.
- * @param lba LBA position.
- * @param m minutes of LBA.
- * @param s seconds of LBA.
- * @param f frames of LBA.
- * @return true if suceeded.
- * @note m,s,f are encoded by BCD.Not binary.
- */
- virtual bool lba_to_msf(int64_t lba, uint8_t& m, uint8_t& s, uint8_t& f) const;
-
- /*
- * MAIN APIs
- */
- /*!
- * @brief Open virtual disc image.
- * @param filename Filename of image (absolute path).
- * @param req_type Opening mode.
- * @return true if succeeded.
- *
- * @note Must set disc parameters list only at this function (or sub-functions).
- * @see parse_sheet
- * @see check_type
- */
- virtual bool open(_TCHAR *filename, enum CDROM_META::CDIMAGE_OPEN_MODE req_type);
- /*!
- * @brief Close virtual disc image.
- * @return true if succeeded.
- */
- virtual bool close();
- /*!
- * @brief Read image data to buffer as CD-ROM/MODE1 from current LBA position.
- * @param buf Destination pointer of read buffer.
- * @param buflen Size of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param _clear true if expect to clear buffer.
- * @return size of reading.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- */
- virtual ssize_t read_mode1(uint8_t *buf, ssize_t buflen, size_t sectors = 1, bool _clear = false);
- /*!
- * @brief Read image data to buffer as CD-ROM/MODE2 from current LBA position.
- * @param buf Destination pointer of read buffer.
- * @param buflen Size of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param _clear true if expect to clear buffer.
- * @return size of reading.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- */
- virtual ssize_t read_mode2(uint8_t *buf, ssize_t buflen, size_t sectors = 1, bool _clear = false);
-
- /*!
- * @brief Read image data to buffer as CD-DA from current LBA position.
- * @param buf Destination pointer of read buffer.Must be pair16_t[(2352 / 4) * 2].
- * @param buflen bytes of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param swap_byte true if swap byte order.
- * @param _clear true if expect to clear buffer.
- * @return read samples.
- * @note Override and inherit this to implement real method.
- */
- virtual ssize_t read_cdda(pair16_t *buf, ssize_t buflen, size_t sectors = 1, bool swap_byte = false, bool _clear = false);
- /*!
- * @brief Read raw image data to buffer from current LBA position.
- * @param buf Destination pointer of read buffer.
- * @param buflen Size of read buffer.
- * @param sectors Count of sectors (LBAs).
- * @param _clear true if expect to clear buffer.
- * @return size of reading.
- * @note Override and inherit this to implement real method.
- * @note Stop when reaches END of CURRENT TRACK.
- * @note Changing size of data by type of Virtual image.
- */
- virtual ssize_t read_raw(uint8_t *buf, ssize_t buflen, size_t sectors = 1, bool _clear = false);
- /*!
- * @brief Try to seek to expected LBA.
- * @param m minutes of LBA (absolute)
- * @param s seconds of LBA (absolute)
- * @param f frames of LBA (absolute)
- * @param in_track Set true if within track, set false if seek to another track.
- * @return true if succeeded.
- * @note need to implement accross another tracks.
- */
- virtual bool seek(uint8_t m, uint8_t s, uint8_t f, bool& in_track);
- /*!
- * @brief Try to seek to expected LBA.
- * @param lba Position of LBA (absolute)
- * @param in_track Set true if within track, set false if seek to another track.
- * @return true if succeeded.
- * @note need to implement accross another tracks.
- */
- virtual bool seek_absolute_lba(int64_t lba, bool& in_track);
- /*!
- * @brief Try to seek to expected LBA.
- * @param lba Position of LBA (relative)
- * @param in_track Set true if within track, set false if seek to another track.
- * @return true if succeeded.
- * @note need to implement accross another tracks.
- */
- virtual bool seek_relative_lba(int64_t lba, bool& in_track);
-
- /*!
- * @brief Read TOC table by TRACK.
- * @param trk TRACK NUM (0 to 99).
- * @param pointer of Destination TOC buffer.
- * MUST allocate more than sizeof(CDROM_META::cdrom_toc_table_t).
- * @return true if success.
- */
- virtual bool get_toc_table(int trk, CDROM_META::cdrom_toc_table_t* data);
- /*!
- * @brief Read TOC/Playing position of used track (BCD Format)
- * @param trk TRACK NUM (0 to 99). If -1 get informations of track now playing.
- * @param pointer of Destination Playing status table buffer.
- * MUST allocate more than sizeof(CDROM_META::cdrom_position_bcd_t).
- * @return true if available this track.
- */
- virtual bool get_position_by_bcd(int trk, CDROM_META::cdrom_position_bcd_t* data);
- /*!
- * @brief Read TOC/Playing position of used track (BINARY Format)
- * @param trk TRACK NUM (0 to 99). If -1 get informations of track now playing.
- * @param pointer of Destination Playing status table buffer.
- * MUST allocate more than sizeof(CDROM_META::cdrom_position_bcd_t).
- * @return true if available this track.
- */
- virtual bool get_position_by_binary(int trk, CDROM_META::cdrom_position_binary_t* data);
- /*!
- * @brief Get track position now accessing.
- * @return track value.-1 if not avaiable image.
- */
- virtual int get_track() const;
- /*!
- * @brief Get LBA position of now accessing.
- * @return LBA position of now accessing.
- */
- virtual int64_t get_lba() const;
- /*!
- * @brief Get number of sectors at this track.
- * @return Number of sectors at this track.
- */
- virtual int64_t get_sectors_of_this_track() const;
- /*!
- * @brief Get current position-offset in this sector.
- * @return Offset position.
- */
- virtual int get_offset_of_this_sector() const;
- /*!
- * @brief Whether this track is available.
- * @return true if available.
- */
- virtual bool is_available() const;
- /*!
- * @brief Get blocks of this virtual CD.
- * @return Blocks (sectors) of this virtual CD.
- */
- virtual int64_t get_blocks() const;
- /*!
- * @brief Get physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
- virtual uint32_t get_physical_block_size() const;
- /*!
- * @brief Get REAL (in VIRTUAL IMAGE) physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
- virtual uint32_t get_real_physical_block_size() const;
- /*!
- * @brief Get logical block size of this virtual CD.
- * @return Logical block size of this virtual CD.
- */
- virtual uint32_t get_logical_block_size() const;
- /*!
- * @brief Calculate seek time to expected LBA.
- * @param m minutes of LBA (absolute)
- * @param s seconds of LBA (absolute)
- * @param f frames of LBA (absolute)
- * @return seek time as usec.
- * If error, return NaN.
- */
- virtual double get_seek_time(uint8_t m, uint8_t s, uint8_t f);
- /*!
- * @brief Calculate seek time to expected LBA.
- * @param lba Position of LBA (absolute)
- * @return seek time as usec.
- * If error, return NaN.
- */
- virtual double get_seek_time_absolute_lba(int64_t lba);
- /*!
- * @brief Calculate seek time to expected LBA.
- * @param lba Position of LBA (relative)
- * @return seek time as usec.
- * If error, return NaN.
- */
- virtual double get_seek_time_relative_lba(int64_t lba);
- /*!
- * @brief Set enable/disable beyond track reading.
- * @param val enable when setting true.
- */
- virtual void enable_beyond_track_reading(bool val);
-
- /*!
- * @brief Check type of virtual disc image by filename.
- * @param filename Filename of image (absolute path).
- * @return Type of CD image.
- */
- static enum CDROM_META::CDIMAGE_TYPE check_type(_TCHAR *filename);
-
- /*!
- * @brief Get uint value from BCD string.
- * @param s source string
- * @param errorval set true if wrong string value.
- * @return Value if success, 0 if not.
- */
- static uint64_t get_val_from_bcdstr(std::string s, bool& errorval);
- /*!
- * @brief Get uint value from HEXADECIMAL string.
- * @param s source string
- * @param errorval set true if wrong string value.
- * @return Value if success, 0 if not.
- */
- static uint64_t get_val_from_hexstr(std::string s, bool& errorval);
- /*!
- * @brief Decode frame value from MSF string.
- * @param timestr Time string. Encoded by "xx:xx:xx". xx must be BCD value.
- * @param errorval true if wrong string.
- * @return value if success, 0 when failed.
- */
- static uint64_t get_frames_from_msfstr(std::string timestr, bool &errorval);
- /*!
- * @brief To be Upper characters from string.
- * @param s source string.
- * @return ToUpper'ed string.
- */
- static std::string to_upper(std::string s);
-
- /*!
- * @brief Load / Save state to VM.
- * @param state_fio FILE IO for state loading/saving.
- * @param loading If true loading, false is saving.
- * @return true if succeeded.
- */
- virtual bool process_state(FILEIO* state_fio, bool loading);
-};
-
-/*!
- * Inline functions.
- */
-/*!
- * @brief Convert BCD value to binary value.
- * @param n BCD value
- * @return Binarized value.-1 if error.
- */
-inline int CDROM_SKELTON::bcd_to_bin(uint8_t n, bool& __error)
-{
- uint8_t n1 = n >> 4;
- uint8_t n2 = n & 0x0f;
- if(n1 >= 10) {
- __error = true;
- return 0;
- }
- if(n2 >= 10) {
- __error = true;
- return 0;
- }
- __error = false;
- return (((int)(n1 * 10)) + (int)n2);
-}
-/*!
- * @brief Convert POSITIVE BINARY value to BCD.
- * @param n Binary value.
- * @param _error Set true if available range (0 to 99) at n.
- * @return BCDed value.
- */
-inline uint8_t CDROM_SKELTON::bin_to_bcd(uint8_t n, bool& __error)
-{
- if((n < 0) || (n >= 100)) {
- __error = true;
- return 0;
- }
- uint8_t n1 = ((uint8_t)(n / 10));
- uint8_t n2 = ((uint8_t)(n % 10));
- __error = false;
- return ((n1 << 8) | n2);
-}
-
-/*!
- * @brief Get track position now accessing.
- * @return track value.-1 if not avaiable image.
- */
-inline int CDROM_SKELTON::__get_track() const
-{
- return now_track;
-}
-
-/*!
- * @brief Get LBA position of now accessing.
- * @return LBA position of now accessing.
- */
-inline int64_t CDROM_SKELTON::__get_lba() const
-{
- return now_lba;
-}
-/*!
- * @brief Get Relative LBA offset value (at head of this track) of this image.
- * @return Relative LBA offset value (in image).
- */
-inline int64_t CDROM_SKELTON::__get_lba_offset() const
-{
- return lba_offset_of_this_track;
-}
-/*!
- * @brief Get number of sectors at this track.
- * @return Number of sectors at this track.
- */
-inline int64_t CDROM_SKELTON::__get_sectors_of_this_track() const
-{
- return sectors_of_this_track;
-}
-/*!
- * @brief Get current position-offset in this sector.
- * @return Offset position.
- */
-inline int CDROM_SKELTON::__get_offset_of_this_sector() const
-{
- return (int)offset_in_sector;
-}
-/*!
- * @brief Whether this track is available.
- * @return true if available.
- */
-inline bool CDROM_SKELTON::__is_available() const
-{
- return track_is_available;
-}
-/*!
- * @brief Get blocks of this virtual CD.
- * @return Blocks (sectors) of this virtual CD.
- */
-inline int64_t CDROM_SKELTON::__get_blocks() const
-{
- return max_blocks;
-}
-/*!
- * @brief Get physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
-inline uint32_t CDROM_SKELTON::__get_physical_block_size() const
-{
- return physical_bytes_per_block;
-}
-/*!
- * @brief Get REAL (in VIRTUAL IMAGE) physical block size of this virtual CD.
- * @return Physical block size of this virtual CD.
- */
-inline uint32_t CDROM_SKELTON::__get_real_physical_block_size() const
-{
- return real_physical_bytes_per_block;
-}
-/*!
- * @brief Get logical block size of this virtual CD.
- * @return Logical block size of this virtual CD.
- */
-inline uint32_t CDROM_SKELTON::__get_logical_block_size() const
-{
- return logical_bytes_per_block;
-}
-
-/*!
- * @brief Get transfer time per byte.
- * @return transfer time as uSec.
- */
-inline double CDROM_SKELTON::__get_transfer_time_us()
-{
- double _speed = seek_speed;
- if(_speed <= 0.0) _speed = 1.0;
-
- return (transfer_time_us / _speed);
-}
-
-/*!
- * @brief Get seek multiply rate.
- * @return Seek rate.
- */
-inline double CDROM_SKELTON::__get_seek_speed()
-{
- double _speed = seek_speed;
- if(_speed <= 0.0) {
- _speed = 1.0;
- }
- return _speed;
-}
-
-/*!
- * @brief Get seek time per block.
- * @return seek time as uSec.
- */
-inline double CDROM_SKELTON::__get_single_seek_time_us()
-{
- double bytes = (double)physical_bytes_per_block;
- if(bytes < 1.0) bytes = 1.0;
- double usec = __get_transfer_time_us();
-
- if(usec < (1.0 / 32.0)) usec = 1.0 / 32.0;
- return usec * bytes;
-}
-
-/*!
- * @brief Set seek speed.
- * @param usec Basic transfer time normally 1.0 / 150.0KHz.
- */
-inline void CDROM_SKELTON::__set_transfer_time_us(double usec)
-{
- if(usec <= 0.0) {
- usec = 1.0e6 / 150.0e3;
- }
- transfer_time_us = usec;
- if(transfer_time_us <= (1.0 / 32.0)) {
- transfer_time_us = 1.0 / 32.0;
- }
-}
-/*!
- * @brief Set seek speed.
- * @param speed Transfer speed multiply rate, normally 1.0.
- */
-inline void CDROM_SKELTON::__set_seek_speed(double speed)
-{
- if(speed <= 0.0) {
- speed = 1.0;
- }
- seek_speed = speed;
-}
-/*!
- * @brief Set physical bytes per block (in emulation).
- * @param bytes bytes per block.
- */
-inline void CDROM_SKELTON::__set_physical_bytes_per_block(uint32_t bytes)
-{
- if(bytes == 0) bytes = 2352; // Default value
- physical_bytes_per_block = bytes;
-}
-/*!
- * @brief Set physical bytes per block (in image).
- * @param bytes bytes per block.
- */
-inline void CDROM_SKELTON::__set_real_physical_bytes_per_block(uint32_t bytes)
-{
- if(bytes == 0) bytes = 2352; // Default value
- real_physical_bytes_per_block = bytes;
-}
-/*!
- * @brief Set logical bytes per block (in emulation).
- * @param bytes bytes per block.
- */
-inline void CDROM_SKELTON::__set_logical_bytes_per_block(uint32_t bytes)
-{
- if(bytes == 0) bytes = 2048; // Default value
- logical_bytes_per_block = bytes;
-}
-
-/*!
- * @brief Get track type of this track.
- * @return TRACK TYPE.
- */
-inline enum CDROM_META::CDIMAGE_TRACK_TYPE CDROM_SKELTON::__get_track_type() const
-{
- return ((CDROM_META::CDIMAGE_TRACK_TYPE)tracktype);
-}
-/*!
- * @brief Get image type of this virtual CD.
- * @return Image type of virtual CD.
- */
-inline enum CDROM_META::CDIMAGE_TYPE CDROM_SKELTON::__get_type() const
-{
- return ((CDROM_META::CDIMAGE_TYPE)type);
-}
-/*!
- * @brief Get full path of this virtual image.
- * @param var Returned full path of opened file.Erase if not opened.
- * @return true if already opened.
- */
-inline bool CDROM_SKELTON::__get_track_image_file_name(std::string& var)
-{
- if(__filename.empty()) {
- var.erase();
- return false;
- }
- var = __filename;
- return true;
-}
-