From 97472bc5e92630a963e12ed684916f0abc61d1a5 Mon Sep 17 00:00:00 2001 From: Sorgelig Date: Wed, 16 Aug 2023 23:16:29 +0800 Subject: [PATCH] ide_cdrom: fixes and tweaks. --- ide_cdrom.cpp | 229 +++++++++++++++++++++----------------- support/archie/archie.cpp | 6 +- support/x86/x86.cpp | 2 + user_io.cpp | 5 +- 4 files changed, 133 insertions(+), 109 deletions(-) diff --git a/ide_cdrom.cpp b/ide_cdrom.cpp index f2310bb..1525e30 100644 --- a/ide_cdrom.cpp +++ b/ide_cdrom.cpp @@ -22,13 +22,13 @@ #include "ide.h" #if 0 - #define dbg_printf printf - #define dbg_print_regs ide_print_regs - #define dbg_hexdump hexdump +#define dbg_printf printf +#define dbg_print_regs ide_print_regs +#define dbg_hexdump hexdump #else - #define dbg_printf(...) void() - #define dbg_print_regs void - #define dbg_hexdump(...) void() +#define dbg_printf(...) void() +#define dbg_print_regs void +#define dbg_hexdump(...) void() #endif #define ide_send_data(databuf, size) ide_sendbuf(ide, 255, (size), (uint16_t*)(databuf)) @@ -69,7 +69,7 @@ static int check_magic(fileTYPE *file, int sectorSize, int mode2) // pvd[0] = descriptor type, pvd[1..5] = standard identifier, // pvd[6] = iso version (+8 for High Sierra) return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || - (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); + (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); } static int check_iso_file(fileTYPE *f, uint8_t *mode2, uint16_t *sectorSize) @@ -106,7 +106,7 @@ static int check_iso_file(fileTYPE *f, uint8_t *mode2, uint16_t *sectorSize) static const char * load_iso_file(drive_t *drv, const char* filename) { - fileTYPE f; + fileTYPE f; memset(drv->track, 0, sizeof(drv->track)); drv->track_cnt = 0; @@ -117,7 +117,7 @@ static const char * load_iso_file(drive_t *drv, const char* filename) return 0; } - if(!check_iso_file(&f, &drv->track[0].mode2, &drv->track[0].sectorSize)) + if (!check_iso_file(&f, &drv->track[0].mode2, &drv->track[0].sectorSize)) { printf("Fail to parse ISO!\n"); FileClose(&f); @@ -160,15 +160,15 @@ static int get_timecode(uint32_t &frames, std::istream &in) static track_t *get_track_from_lba(drive_t *drive, uint32_t lba) { - track_t *ret = NULL; - for (int i = 0; i < drive->track_cnt; i++) - { - if (lba >= drive->track[i].start && lba < (drive->track[i].start + drive->track[i].length)) - { - ret = &drive->track[i]; - } - } - return ret; + track_t *ret = NULL; + for (int i = 0; i < drive->track_cnt; i++) + { + if (lba >= drive->track[i].start && lba < (drive->track[i].start + drive->track[i].length)) + { + ret = &drive->track[i]; + } + } + return ret; } static int add_track(drive_t *drv, track_t *curr, uint32_t &shift, const int32_t prestart, uint32_t &totalPregap, uint32_t currPregap) @@ -200,7 +200,7 @@ static int add_track(drive_t *drv, track_t *curr, uint32_t &shift, const int32_t totalPregap = currPregap; memcpy(&drv->track[drv->track_cnt], curr, sizeof(track_t)); - FileOpenEx(&drv->track[drv->track_cnt].f, curr->filename, O_RDONLY); + FileOpenEx(&drv->track[drv->track_cnt].f, curr->filename, O_RDONLY); drv->track_cnt++; return 1; } @@ -262,7 +262,7 @@ static const char* load_chd_file(drive_t *drv, const char *chdfile) //TODO: abstract all the bin/cue+chd+iso parsing and reading into a shared class // - const char *ext = chdfile+strlen(chdfile)-4; + const char *ext = chdfile + strlen(chdfile) - 4; uint32_t total_sector_size = 0; @@ -290,11 +290,11 @@ static const char* load_chd_file(drive_t *drv, const char *chdfile) drv->chd_f = tmpTOC.chd_f; //don't use add_track, just do it ourselves... - for(int i = 0; i < tmpTOC.last; i++) + for (int i = 0; i < tmpTOC.last; i++) { cd_track_t *chd_track = &tmpTOC.tracks[i]; track_t *trk = &drv->track[i]; - trk->number = i+1; + trk->number = i + 1; trk->sectorSize = chd_track->sector_size; if (chd_track->type) { @@ -316,16 +316,16 @@ static const char* load_chd_file(drive_t *drv, const char *chdfile) //Add the lead-out track track_t *lead_out = &drv->track[drv->track_cnt]; - lead_out->number = drv->track_cnt+1; + lead_out->number = drv->track_cnt + 1; lead_out->attr = 0; - lead_out->start = tmpTOC.tracks[tmpTOC.last-1].end; + lead_out->start = tmpTOC.tracks[tmpTOC.last - 1].end; lead_out->length = 0; drv->track_cnt++; drv->total_sectors = total_sector_size / 512; drv->chd_total_size = total_sector_size; - for(uint8_t i = 0; i < drv->track_cnt; i++) + for (uint8_t i = 0; i < drv->track_cnt; i++) { if (drv->track[i].attr == 0x40) { @@ -483,7 +483,7 @@ static const char* load_cue_file(drive_t *drv, const char *cuefile) track.number++; track.filename[0] = 0; track.attr = 0;//sync with load iso - track.start = drv->track[track.number-1].start + drv->track[track.number-1].length; + track.start = drv->track[track.number - 1].start + drv->track[track.number - 1].length; track.length = 0; if (!add_track(drv, &track, shift, -1, totalPregap, 0)) @@ -696,21 +696,21 @@ static int read_toc(drive_t *drv, uint8_t *cmdbuf) void cdrom_mode_select(ide_config *ide) { - uint8_t *mode_page = &ide_buf[8]; + uint8_t *mode_page = &ide_buf[8]; drive_t *drv = &ide->drive[ide->regs.drv]; - uint8_t page_code = mode_page[0] & 0x3F; + uint8_t page_code = mode_page[0] & 0x3F; - switch(page_code) { - case 0x0E: - { - uint8_t p0vol = mode_page[9]; - uint8_t p1vol = mode_page[11]; - //in gain factor - drv->volume_l = (p0vol+1)/256.0f; - drv->volume_r = (p1vol+1)/256.0f; - } - break; - } + switch (page_code) { + case 0x0E: + { + uint8_t p0vol = mode_page[9]; + uint8_t p1vol = mode_page[11]; + //in gain factor + drv->volume_l = (p0vol + 1) / 256.0f; + drv->volume_r = (p1vol + 1) / 256.0f; + } + break; + } } static uint16_t mode_sense(drive_t *drv, int page) @@ -773,9 +773,9 @@ static uint16_t mode_sense(drive_t *drv, int page) *write++ = 0x00; /* +6 Obsolete (75) */ *write++ = 75; /* +7 Obsolete (75) */ *write++ = 0x01; /* +8 output port 0 selection (0001b = channel 0) */ - *write++ = (uint8_t)((drv->volume_l*256)-1); /* +9 output port 0 volume (0xFF = 0dB atten.) */ + *write++ = (uint8_t)((drv->volume_l * 256) - 1); /* +9 output port 0 volume (0xFF = 0dB atten.) */ *write++ = 0x02; /* +10 output port 1 selection (0010b = channel 1) */ - *write++ = (uint8_t)((drv->volume_l*256)-1); /* +11 output port 1 volume (0xFF = 0dB atten.) */ + *write++ = (uint8_t)((drv->volume_l * 256) - 1); /* +11 output port 1 volume (0xFF = 0dB atten.) */ *write++ = 0x00; /* +12 output port 2 selection (none) */ *write++ = 0x00; /* +13 output port 2 volume (0x00 = mute) */ *write++ = 0x00; /* +14 output port 3 selection (none) */ @@ -865,7 +865,7 @@ static int get_subchan(drive_t *drv, unsigned char& attr, unsigned char& track_n track_num = drv->track[i].number; attr = drv->track[i].attr; absolute_msf = frames_to_msf(cur_pos + REDBOOK_FRAME_PADDING); - relative_msf = frames_to_msf((cur_pos + REDBOOK_FRAME_PADDING) - drv->track[i].start); + relative_msf = frames_to_msf((cur_pos + REDBOOK_FRAME_PADDING) - drv->track[i].start); return 1; } } @@ -1017,7 +1017,7 @@ void cdrom_read(ide_config *ide) } - track_t *track = get_track_from_lba(drive, ide->regs.pkt_lba); + track_t *track = get_track_from_lba(drive, ide->regs.pkt_lba); if (ide->state == IDE_STATE_INIT_RW && !drive->chd_f && track) { @@ -1040,22 +1040,26 @@ void cdrom_read(ide_config *ide) drive->chd_last_partial_lba = ide->regs.pkt_lba; } - for(uint32_t i = 0; i < cnt; i++) + for (uint32_t i = 0; i < cnt; i++) { if (mister_chd_read_sector(drive->chd_f, drive->chd_last_partial_lba + drive->track[drive->data_num].chd_offset, d_offset, hdr, 2048, ide_buf, drive->chd_hunkbuf, &drive->chd_hunknum) != CHDERR_NONE) { //I don't think anything else uses this, but set it just in case. ide->null = 1; - memset(ide_buf+d_offset, 0, 2048); - } else { + memset(ide_buf + d_offset, 0, 2048); + } + else + { ide->null = 0; } d_offset += 2048; drive->chd_last_partial_lba++; } - } else { + } + else + { read_cd_sectors(ide, track, cnt); } @@ -1129,7 +1133,7 @@ static int get_sense(drive_t *drv) static void pause_resume(drive_t *drv, uint8_t *cmdbuf) { bool resume = !!(cmdbuf[8] & 1); - if(drv->playing) drv->paused = !resume; + if (drv->playing) drv->paused = !resume; } static void play_audio_msf(drive_t *drv, uint8_t *cmdbuf) @@ -1243,7 +1247,7 @@ void cdrom_handle_pkt(ide_config *ide) dbg_printf("** par: lba = %d, cnt = %d, load_state = %d\n", ide->regs.pkt_lba, ide->regs.pkt_cnt, drv->load_state); ide->state = IDE_STATE_INIT_RW; - if(!drv->load_state) cdrom_read(ide); + if (!drv->load_state) cdrom_read(ide); else cdrom_nodisk(ide); break; @@ -1256,7 +1260,9 @@ void cdrom_handle_pkt(ide_config *ide) if (drv->chd_f) { tmp = drv->chd_total_size / 2048; - } else { + } + else + { tmp = drv->f->size / 2048; } ide_buf[0] = tmp >> 24; @@ -1283,10 +1289,10 @@ void cdrom_handle_pkt(ide_config *ide) cdrom_reply(ide, 0); break; - case 0x1B: //START STOP UNIT - dbg_printf("** Start Stop Unit\n"); - cdrom_reply(ide, 0); - break; + case 0x1B: //START STOP UNIT + dbg_printf("** Start Stop Unit\n"); + cdrom_reply(ide, 0); + break; case 0x1E: // lock the cd door - doing nothing. dbg_printf("** Lock Door\n"); @@ -1317,7 +1323,7 @@ void cdrom_handle_pkt(ide_config *ide) dbg_printf("** get sense:\n"); pkt_send(ide, ide_buf, get_sense(drv)); break; - + case 0x55: // mode select dbg_printf("** mode select\n"); @@ -1447,7 +1453,9 @@ void cdrom_reply(ide_config *ide, uint8_t error, bool unit_attention) ide->regs.error = CD_ERR_UNIT_ATTENTION; ide->regs.error |= ATA_ERR_MCR; ide->drive[ide->regs.drv].mcr_flag = false; - } else { + } + else + { ide->regs.status = ATA_STATUS_RDY | ATA_STATUS_IRQ | (error ? ATA_STATUS_ERR : 0); ide->regs.error = error; } @@ -1482,7 +1490,7 @@ const char* cdrom_parse(uint32_t num, const char *filename) int drv = num & 1; num >>= 1; cdrom_close_chd(&ide_inst[num].drive[drv]); - for(uint8_t i=0; i < sizeof(ide_inst[num].drive[drv].track)/sizeof(track_t); i++) + for (uint8_t i = 0; i < sizeof(ide_inst[num].drive[drv].track) / sizeof(track_t); i++) { if (ide_inst[num].drive[drv].track[i].f.opened()) { @@ -1503,54 +1511,67 @@ const char* cdrom_parse(uint32_t num, const char *filename) return res; } +void ide_cdda_send_sector() +{ + static uint8_t cdda_buf[BYTES_PER_RAW_REDBOOK_FRAME]; + drive_t *drv = NULL; + ide_config *ide = NULL; + int ide_idx = -1; + for (ide_idx = 0; ide_idx < 2; ide_idx++) + { + for (int drv_idx = 0; drv_idx < 2; drv_idx++) + { + if (ide_inst[ide_idx].drive[drv_idx].playing == 1 && ide_inst[ide_idx].drive[drv_idx].paused == 0) + { + drv = &ide_inst[ide_idx].drive[drv_idx]; + ide = &ide_inst[ide_idx]; + break; + } + } + if (drv) break; + } -void ide_cdda_send_sector() { - drive_t *drv = NULL; - ide_config *ide = NULL; - int ide_idx = -1; - for (ide_idx = 0; ide_idx < 2; ide_idx++) { - for (int drv_idx = 0; drv_idx < 2; drv_idx++) { - if (ide_inst[ide_idx].drive[drv_idx].playing == 1 && ide_inst[ide_idx].drive[drv_idx].paused == 0) { - drv = &ide_inst[ide_idx].drive[drv_idx]; - ide = &ide_inst[ide_idx]; - break; - } - } - if (drv) break; - } - if (!drv || !ide) return; - uint8_t cdda_buf[BYTES_PER_RAW_REDBOOK_FRAME]; - bool needs_swap = false; + if (!drv || !ide) return; - if (drv->chd_f) { - mister_chd_read_sector(drv->chd_f, drv->play_start_lba + drv->track[drv->data_num].chd_offset, 0, 0, BYTES_PER_RAW_REDBOOK_FRAME, cdda_buf, drv->chd_hunkbuf, &drv->chd_hunknum ); - needs_swap = true; - } else { - track_t *track = get_track_from_lba(drv, drv->play_start_lba); - //uint32_t pos = ide->regs.pkt_lba * ide->drive[ide->regs.drv].track[ide->drive[ide->regs.drv].data_num].sectorSize; - uint32_t pos = track->skip + (drv->play_start_lba - track->start) * track->sectorSize; - FileSeek(&track->f, pos, SEEK_SET); - FileReadAdv(&track->f, cdda_buf, sizeof(cdda_buf), -1); - } + bool needs_swap = false; + track_t *track = get_track_from_lba(drv, drv->play_start_lba); - int16_t *cdda_buf16 = (int16_t *)cdda_buf; - for (int sidx = 0; sidx < 1176; sidx++) - { - if (needs_swap) { - cdda_buf16[sidx] = bswap_16(cdda_buf16[sidx]); - } - double tmps = (double)cdda_buf16[sidx]; - if (sidx%2) { - cdda_buf16[sidx] = (int16_t)(tmps*drv->volume_r); - } else { - cdda_buf16[sidx] = (int16_t)(tmps*drv->volume_r); - } - } - ide_sendbuf(ide, 0x200, sizeof(cdda_buf)/2, (uint16_t *)cdda_buf); - drv->play_start_lba += 1; - if (drv->play_start_lba >= drv->play_end_lba) - { - drv->playing = 0; - drv->paused = 0; - } + if (!track->attr) + { + if (drv->chd_f) + { + mister_chd_read_sector(drv->chd_f, drv->play_start_lba + drv->track[drv->data_num].chd_offset, 0, 0, BYTES_PER_RAW_REDBOOK_FRAME, cdda_buf, drv->chd_hunkbuf, &drv->chd_hunknum); + needs_swap = true; + } + else + { + //uint32_t pos = ide->regs.pkt_lba * ide->drive[ide->regs.drv].track[ide->drive[ide->regs.drv].data_num].sectorSize; + uint32_t pos = track->skip + (drv->play_start_lba - track->start) * track->sectorSize; + FileSeek(&track->f, pos, SEEK_SET); + FileReadAdv(&track->f, cdda_buf, sizeof(cdda_buf), -1); + } + } + else + { + memset(cdda_buf, 0, sizeof(cdda_buf)); + } + + int16_t *cdda_buf16 = (int16_t *)cdda_buf; + const int buf_wsize = sizeof(cdda_buf) / 2; + + for (int sidx = 0; sidx < buf_wsize; sidx++) + { + if (needs_swap) cdda_buf16[sidx] = bswap_16(cdda_buf16[sidx]); + double tmps = (double)cdda_buf16[sidx]; + cdda_buf16[sidx] = (int16_t)(tmps*((sidx & 1) ? drv->volume_l : drv->volume_r)); + } + + ide_sendbuf(ide, 0x200, buf_wsize, (uint16_t *)cdda_buf); + + drv->play_start_lba++; + if (drv->play_start_lba >= drv->play_end_lba) + { + drv->playing = 0; + drv->paused = 0; + } } diff --git a/support/archie/archie.cpp b/support/archie/archie.cpp index 5ce8fd7..d77379c 100644 --- a/support/archie/archie.cpp +++ b/support/archie/archie.cpp @@ -474,7 +474,11 @@ void archie_poll(void) DisableFpga(); uint16_t sd_req = ide_check(); - if (sd_req & 0x8000) ide_io(0, sd_req & 7); + if (sd_req & 0x8000) + { + ide_io(0, sd_req & 7); + if (sd_req & 0x0100) ide_cdda_send_sector(); + } else HandleHDD(status >> 8, 0); check_cmos(status); diff --git a/support/x86/x86.cpp b/support/x86/x86.cpp index f923361..ceae50c 100644 --- a/support/x86/x86.cpp +++ b/support/x86/x86.cpp @@ -726,6 +726,8 @@ void x86_poll() uint16_t sd_req = ide_check(); if (sd_req) { + if (sd_req & 0x400) ide_cdda_send_sector(); + ide_io(0, sd_req & 7); sd_req >>= 3; ide_io(1, sd_req & 7); diff --git a/user_io.cpp b/user_io.cpp index 7ed2370..3c82977 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -2891,10 +2891,7 @@ void user_io_poll() { ide_io(0, sd_req & 7); ide_io(1, (sd_req >> 3) & 7); - if (sd_req & 0x0100) - { - ide_cdda_send_sector(); - } + if (sd_req & 0x0100) ide_cdda_send_sector(); } else {