diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index dff3a9105..be6779f9b 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -97,6 +97,9 @@ image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc) subc->rel_m = rel_pos.min; subc->rel_s = rel_pos.sec; subc->rel_f = rel_pos.fr; + + cdrom_image_log("image_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", + subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f, subc->rel_m, subc->rel_s, subc->rel_f); } static int diff --git a/src/cdrom/cdrom_ioctl.c b/src/cdrom/cdrom_ioctl.c index dae9abaad..c1bc6569e 100644 --- a/src/cdrom/cdrom_ioctl.c +++ b/src/cdrom/cdrom_ioctl.c @@ -82,19 +82,12 @@ ioctl_get_subchannel(UNUSED(cdrom_t *dev), uint32_t lba, subchannel_t *subc) TMSF abs_pos; if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) { - uint32_t dat = lba + 150; - abs_pos.fr = dat % 75; - dat /= 75; - abs_pos.sec = dat % 60; - dat /= 60; - abs_pos.min = dat; + const uint32_t trk = plat_cdrom_get_track_start(lba, &subc->attr, &subc->track); - dat = lba - plat_cdrom_get_track_start(lba, &subc->attr, &subc->track); - rel_pos.fr = dat % 75; - dat /= 75; - rel_pos.sec = dat % 60; - dat /= 60; - rel_pos.min = dat; + FRAMES_TO_MSF(lba + 150, &abs_pos.min, &abs_pos.sec, &abs_pos.fr); + + /* Absolute position should be adjusted by 150, not the relative ones. */ + FRAMES_TO_MSF(lba - trk, &rel_pos.min, &rel_pos.sec, &rel_pos.fr); subc->index = 1; } else @@ -109,12 +102,12 @@ ioctl_get_subchannel(UNUSED(cdrom_t *dev), uint32_t lba, subchannel_t *subc) subc->rel_s = rel_pos.sec; subc->rel_f = rel_pos.fr; - cdrom_ioctl_log("ioctl_get_subchannel(): %02i, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", + cdrom_ioctl_log("ioctl_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n", subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f, subc->rel_m, subc->rel_s, subc->rel_f); } static int -cdrom_ioctl_get_capacity(UNUSED(cdrom_t *dev)) +ioctl_get_capacity(UNUSED(cdrom_t *dev)) { int ret; @@ -145,9 +138,9 @@ ioctl_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) } static int -ioctl_is_track_pre(UNUSED(cdrom_t *dev), UNUSED(uint32_t lba)) +ioctl_is_track_pre(UNUSED(cdrom_t *dev), uint32_t lba) { - return 0; + return plat_cdrom_is_track_pre(lba); } static int @@ -193,11 +186,16 @@ ioctl_track_type(cdrom_t *dev, uint32_t lba) static int ioctl_ext_medium_changed(cdrom_t *dev) { - const int ret = plat_cdrom_ext_medium_changed(); + int ret; + + if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) + ret = 0; + else + ret = plat_cdrom_ext_medium_changed(); if (ret == 1) { dev->cd_status = CD_STATUS_STOPPED; - dev->cdrom_capacity = cdrom_ioctl_get_capacity(dev); + dev->cdrom_capacity = ioctl_get_capacity(dev); } else if (ret == -1) dev->cd_status = CD_STATUS_EMPTY; @@ -260,7 +258,7 @@ cdrom_ioctl_open(cdrom_t *dev, const char *drv) dev->is_dir = 0; dev->seek_pos = 0; dev->cd_buflen = 0; - dev->cdrom_capacity = cdrom_ioctl_get_capacity(dev); + dev->cdrom_capacity = ioctl_get_capacity(dev); cdrom_ioctl_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL); diff --git a/src/include/86box/plat_cdrom.h b/src/include/86box/plat_cdrom.h index a21dd357f..8e81f9459 100644 --- a/src/include/86box/plat_cdrom.h +++ b/src/include/86box/plat_cdrom.h @@ -50,6 +50,7 @@ typedef struct SMSF { } TMSF; extern int plat_cdrom_is_track_audio(uint32_t sector); +extern int plat_cdrom_is_track_pre(uint32_t sector); extern uint32_t plat_cdrom_get_last_block(void); extern void plat_cdrom_get_audio_tracks(int *st_track, int *end, TMSF *lead_out); extern int plat_cdrom_get_audio_track_info(int end, int track, int *track_num, TMSF *start, uint8_t *attr); diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 36838820a..ff422bcd2 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -72,6 +72,17 @@ plat_cdrom_open(void) { plat_cdrom_close(); + handle = CreateFileW((LPCWSTR)ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + win_cdrom_ioctl_log("handle=%p, error=%x\n", handle, (unsigned int) GetLastError()); + + return (handle != INVALID_HANDLE_VALUE); +} + +static int +plat_cdrom_load(void) +{ + plat_cdrom_close(); + handle = CreateFileW((LPCWSTR)ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); win_cdrom_ioctl_log("handle=%p, error=%x\n", handle, (unsigned int) GetLastError()); if (handle != INVALID_HANDLE_VALUE) { @@ -112,7 +123,7 @@ plat_cdrom_is_track_audio(uint32_t sector) cur_toc.TrackData[c].TrackNumber, c, cur_toc.TrackData[c].Control, track_addr, sector); if ((cur_toc.TrackData[c].TrackNumber >= cur_toc.FirstTrack) && (cur_toc.TrackData[c].TrackNumber <= cur_toc.LastTrack) && - (sector >= track_addr) && (sector <= next_track_addr)) { + (sector >= track_addr) && (sector < next_track_addr)) { control = cur_toc.TrackData[c].Control; break; } @@ -125,6 +136,36 @@ plat_cdrom_is_track_audio(uint32_t sector) return ret; } +int +plat_cdrom_is_track_pre(uint32_t sector) +{ + int control = 0; + uint32_t track_addr = 0; + uint32_t next_track_addr = 0; + + plat_cdrom_read_toc(); + + for (int c = 0; cur_toc.TrackData[c].TrackNumber != 0xaa; c++) { + track_addr = MSFtoLBA(cur_toc.TrackData[c].Address[1], cur_toc.TrackData[c].Address[2], cur_toc.TrackData[c].Address[3]) - 150; + next_track_addr = MSFtoLBA(cur_toc.TrackData[c + 1].Address[1], cur_toc.TrackData[c + 1].Address[2], cur_toc.TrackData[c + 1].Address[3]) - 150; + win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, A: %08X, S: %08X\n", + cur_toc.FirstTrack, cur_toc.LastTrack, + cur_toc.TrackData[c].TrackNumber, c, + cur_toc.TrackData[c].Control, track_addr, sector); + if ((cur_toc.TrackData[c].TrackNumber >= cur_toc.FirstTrack) && (cur_toc.TrackData[c].TrackNumber <= cur_toc.LastTrack) && + (sector >= track_addr) && (sector < next_track_addr)) { + control = cur_toc.TrackData[c].Control; + break; + } + } + + const int ret = (control & 0x01); + + win_cdrom_ioctl_log("plat_cdrom_is_track_audio(%08X): %i\n", sector, ret); + + return ret; +} + uint32_t plat_cdrom_get_track_start(uint32_t sector, uint8_t *attr, uint8_t *track) { @@ -136,14 +177,16 @@ plat_cdrom_get_track_start(uint32_t sector, uint8_t *attr, uint8_t *track) for (int c = 0; cur_toc.TrackData[c].TrackNumber != 0xaa; c++) { track_addr = MSFtoLBA(cur_toc.TrackData[c].Address[1], cur_toc.TrackData[c].Address[2], cur_toc.TrackData[c].Address[3]) - 150; next_track_addr = MSFtoLBA(cur_toc.TrackData[c + 1].Address[1], cur_toc.TrackData[c + 1].Address[2], cur_toc.TrackData[c + 1].Address[3]) - 150; - win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, A: %08X, S: %08X\n", + win_cdrom_ioctl_log("F: %i, L: %i, C: %i (%i), c: %02X, a: %02X, A: %08X, S: %08X\n", cur_toc.FirstTrack, cur_toc.LastTrack, cur_toc.TrackData[c].TrackNumber, c, - cur_toc.TrackData[c].Control, track_addr, sector); + cur_toc.TrackData[c].Control, cur_toc.TrackData[c].Adr, + track_addr, sector); if ((cur_toc.TrackData[c].TrackNumber >= cur_toc.FirstTrack) && (cur_toc.TrackData[c].TrackNumber <= cur_toc.LastTrack) && - (sector >= track_addr) && (sector <= next_track_addr)) { + (sector >= track_addr) && (sector < next_track_addr)) { *track = cur_toc.TrackData[c].TrackNumber; *attr = cur_toc.TrackData[c].Control; + *attr |= ((cur_toc.TrackData[c].Adr << 4) & 0xf0); break; } } @@ -239,6 +282,7 @@ plat_cdrom_get_audio_track_info(UNUSED(int end), int track, int *track_num, TMSF *track_num = cur_toc.TrackData[track - 1].TrackNumber; *attr = cur_toc.TrackData[track - 1].Control; + *attr |= ((cur_toc.TrackData[track - 1].Adr << 4) & 0xf0); win_cdrom_ioctl_log("plat_cdrom_get_audio_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n", track, start->min, start->sec, start->fr, *track_num, *attr); @@ -265,6 +309,7 @@ plat_cdrom_get_audio_sub(UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track, *track = sub.CurrentPosition.TrackNumber; *attr = sub.CurrentPosition.Control; + *attr |= ((sub.CurrentPosition.ADR << 4) & 0xf0); *index = sub.CurrentPosition.IndexNumber; rel_pos->min = sub.CurrentPosition.TrackRelativeAddress[1]; @@ -303,15 +348,7 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) plat_cdrom_open(); - if (!raw) { - win_cdrom_ioctl_log("Cooked\n"); - /* Cooked */ - int success = 0; - DWORD newPos = SetFilePointer(handle, sector * COOKED_SECTOR_SIZE, 0, FILE_BEGIN); - if (newPos != 0xFFFFFFFF) - success = ReadFile(handle, buffer, buflen, (LPDWORD)&size, NULL); - status = (success != 0); - } else { + if (raw) { win_cdrom_ioctl_log("Raw\n"); /* Raw */ RAW_READ_INFO in; @@ -321,9 +358,17 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) in.TrackMode = CDDA; status = DeviceIoControl(handle, IOCTL_CDROM_RAW_READ, &in, sizeof(in), buffer, buflen, (LPDWORD)&size, NULL); + } else { + win_cdrom_ioctl_log("Cooked\n"); + /* Cooked */ + int success = 0; + DWORD newPos = SetFilePointer(handle, sector * COOKED_SECTOR_SIZE, 0, FILE_BEGIN); + if (newPos != 0xFFFFFFFF) + success = ReadFile(handle, buffer, buflen, (LPDWORD)&size, NULL); + status = (success != 0); } plat_cdrom_close(); - win_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%d.\n", status, sector, size); + win_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size); return (size == buflen) && (status > 0); } @@ -361,6 +406,6 @@ plat_cdrom_set_drive(const char *drv) toc_valid = 0; - plat_cdrom_open(); + plat_cdrom_load(); return 1; }