diff --git a/.github/workflows/cmake_linux.yml b/.github/workflows/cmake_linux.yml index 73ae94969b..83672974f7 100644 --- a/.github/workflows/cmake_linux.yml +++ b/.github/workflows/cmake_linux.yml @@ -106,7 +106,7 @@ jobs: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build - name: Run sonar-scanner -# if: 0 + if: 0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/src/86box.c b/src/86box.c index 5f14d00562..5f0c8453cc 100644 --- a/src/86box.c +++ b/src/86box.c @@ -207,7 +207,7 @@ int video_fullscreen_scale_maximized = 0; /* (C) Whether also apply when maximized. */ int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus loss */ -int raw_input = 0; /* (C) Use raw input */ +int hook_enabled = 1; /* (C) Keyboard hook is enabled */ char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */ int other_ide_present = 0; /* IDE controllers from non-IDE cards are @@ -454,6 +454,8 @@ delete_nvr_file(uint8_t flash) fn = NULL; } +extern void device_find_all_descs(void); + /* * Perform initial startup of the PC. * @@ -563,7 +565,7 @@ pc_init(int argc, char *argv[]) printf("-S or --settings - show only the settings dialog\n"); #endif printf("-V or --vmname name - overrides the name of the running VM\n"); - printf("-W or --raw - uses raw input (compatibility-only outside Windows)\n"); + printf("-W or --nohook - disables keyboard hook (compatibility-only outside Windows)\n"); printf("-X or --clear what - clears the 'what' (cmos/flash/both)\n"); printf("-Y or --donothing - do not show any UI or run the emulation\n"); printf("-Z or --lastvmpath - the last parameter is VM path rather than config\n"); @@ -639,8 +641,8 @@ pc_init(int argc, char *argv[]) dump_missing = 1; } else if (!strcasecmp(argv[c], "--donothing") || !strcasecmp(argv[c], "-Y")) { do_nothing = 1; - } else if (!strcasecmp(argv[c], "--raw") || !strcasecmp(argv[c], "-W")) { - raw_input = 1; + } else if (!strcasecmp(argv[c], "--nohook") || !strcasecmp(argv[c], "-W")) { + hook_enabled = 0; } else if (!strcasecmp(argv[c], "--keycodes") || !strcasecmp(argv[c], "-K")) { if ((c + 1) == argc) goto usage; diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index ac002ab658..6d993f24af 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1426,33 +1426,11 @@ cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf) buf[8] = 0x00; } +/* TODO: Actually implement this properly. */ void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode) { - track_info_t ti; - int first_track; - int last_track; - - if (dev != NULL) { - dev->ops->get_tracks(dev, &first_track, &last_track); - dev->ops->get_track_info(dev, *curtoctrk, 0, &ti); - buf[0] = (ti.attr << 4) & 0xf0; - buf[1] = ti.number; - buf[2] = bin2bcd(*curtoctrk + 1); - buf[3] = ti.m; - buf[4] = ti.s; - buf[5] = ti.f; - buf[6] = 0x00; - dev->ops->get_track_info(dev, 1, 0, &ti); - buf[7] = ti.m; - buf[8] = ti.s; - buf[9] = ti.f; - if (*curtoctrk >= (last_track + 1)) - *curtoctrk = 0; - else if (mode) - *curtoctrk = *curtoctrk + 1; - } else - memset(buf, 0x00, 10); + memset(buf, 0x00, 10); } uint8_t @@ -2196,7 +2174,7 @@ cdrom_exit(uint8_t id) memset(dev->image_path, 0, sizeof(dev->image_path)); - pclog("cdrom_exit(%i): cdrom_insert(%i)\n", id, id); + cdrom_log("cdrom_exit(%i): cdrom_insert(%i)\n", id, id); cdrom_insert(id); } @@ -2274,7 +2252,7 @@ cdrom_reload(uint8_t id) #endif /* Signal media change to the emulated machine. */ - pclog("cdrom_reload(%i): cdrom_insert(%i)\n", id, id); + cdrom_log("cdrom_reload(%i): cdrom_insert(%i)\n", id, id); cdrom_insert(id); /* The drive was previously empty, transition directly to UNIT ATTENTION. */ diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index f74e0d3447..0c7870902a 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -58,26 +58,32 @@ cdrom_image_log(const char *fmt, ...) of the audio while audio still plays. With an absolute conversion, the counter is fine. */ #define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) -static void -image_get_tracks(cdrom_t *dev, int *first, int *last) -{ - cd_img_t *img = (cd_img_t *) dev->local; - TMSF tmsf; - - cdi_get_audio_tracks(img, first, last, &tmsf); -} - static void image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) { cd_img_t *img = (cd_img_t *) dev->local; - TMSF tmsf; + track_t *ct = NULL; - cdi_get_audio_track_info(img, end, track, &ti->number, &tmsf, &ti->attr); + for (int i = 0; i < img->tracks_num; i++) { + ct = &(img->tracks[i]); + if (ct->point == track) + break; + } - ti->m = tmsf.min; - ti->s = tmsf.sec; - ti->f = tmsf.fr; + ti->number = ct->point; + + if (ct == NULL) { + ti->attr = 0x14; + ti->m = 0; + ti->s = 2; + ti->f = 0; + } else { + uint32_t pos = end ? ct->idx[1].start : (ct->idx[1].start + ct->idx[1].length); + ti->attr = ct->attr; + ti->m = (pos / 75) / 60; + ti->s = (pos / 75) % 60; + ti->f = pos % 75; + } } static void @@ -113,24 +119,22 @@ static int image_get_capacity(cdrom_t *dev) { cd_img_t *img = (cd_img_t *) dev->local; - int first_track; - int last_track; - int number; - unsigned char attr; - uint32_t address = 0; uint32_t lb = 0; + track_t *lo = NULL; if (!img) return 0; - cdi_get_audio_tracks_lba(img, &first_track, &last_track, &lb); - - for (int c = 0; c <= last_track; c++) { - cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr); - if (address > lb) - lb = address; + for (int i = (img->tracks_num - 1); i >= 0; i--) { + if (img->tracks[i].point == 0xa2) { + lo = &(img->tracks[i]); + break; + } } + if (lo != NULL) + lb = lo->idx[1].start - 1; + return lb; } @@ -138,13 +142,9 @@ static int image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) { cd_img_t *img = (cd_img_t *) dev->local; - uint8_t attr; - TMSF tmsf; int m; int s; int f; - int number; - int track; if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY)) return 0; @@ -156,29 +156,18 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) pos = MSFtoLBA(m, s, f) - 150; } - /* GetTrack requires LBA. */ - track = cdi_get_track(img, pos); - if (track == -1) - return 0; - else { - cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr); - return attr == AUDIO_TRACK; - } + return cdi_is_audio(img, pos); } static int image_is_track_pre(cdrom_t *dev, uint32_t lba) { cd_img_t *img = (cd_img_t *) dev->local; - int track; - - /* GetTrack requires LBA. */ - track = cdi_get_track(img, lba); - if (track != -1) - return cdi_get_audio_track_pre(img, track); + if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY)) + return 0; - return 0; + return cdi_is_pre(img, lba); } static int @@ -238,7 +227,6 @@ image_exit(cdrom_t *dev) } static const cdrom_ops_t cdrom_image_ops = { - image_get_tracks, image_get_track_info, image_get_raw_track_info, image_get_subchannel, @@ -270,14 +258,13 @@ cdrom_image_open(cdrom_t *dev, const char *fn) strcpy(dev->image_path, fn); /* Create new instance of the CDROM_Image class. */ - img = (cd_img_t *) malloc(sizeof(cd_img_t)); + img = (cd_img_t *) calloc(1, sizeof(cd_img_t)); /* This guarantees that if ops is not NULL, then neither is the image pointer. */ - if (!img) + if (img == NULL) return image_open_abort(dev); - memset(img, 0, sizeof(cd_img_t)); dev->local = img; /* Open the image. */ diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index fdc4f662fb..9d065a0cba 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -6,20 +6,15 @@ * * This file is part of the 86Box distribution. * - * CD-ROM image file handling module, translated to C from - * cdrom_dosbox.cpp. - * - * + * CD-ROM image file handling module. * * Authors: Miran Grca, - * Fred N. van Kempen, - * The DOSBox Team, + * RichardG, * Cacodemon345 * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2002-2020 The DOSBox Team. - * Copyright 2024 Cacodemon345. + * Copyright 2016-2025 Miran Grca. + * Copyright 2016-2025 Miran Grca. + * Copyright 2024-2025 Cacodemon345. */ #define __STDC_FORMAT_MACROS #include @@ -278,285 +273,137 @@ bin_init(const char *filename, int *error) } static track_file_t * -track_file_init(const char *filename, int *error) +track_file_init(const char *filename, int *error, int *is_viso) { + track_file_t *tf; + + *is_viso = 0; + /* Current we only support .BIN files, either combined or one per track. In the future, more is planned. */ - return bin_init(filename, error); -} + tf = bin_init(filename, error); -static void -track_file_close(track_t *trk) -{ - if (trk == NULL) - return; + if (*error) { + if ((tf != NULL) && (tf->close != NULL)) { + tf->close(tf); + tf = NULL; + } - if (trk->file == NULL) - return; + tf = viso_init(filename, error); - if (trk->file->close == NULL) - return; + if (!*error) + *is_viso = 1; + } - trk->file->close(trk->file); - trk->file = NULL; + return tf; } -/* Root functions. */ static void -cdi_clear_tracks(cd_img_t *cdi) +index_file_close(track_index_t *idx) { - const track_file_t *last = NULL; - track_t *cur = NULL; - - if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) + if (idx == NULL) return; - for (int i = 0; i < cdi->tracks_num; i++) { - cur = &cdi->tracks[i]; - - /* Make sure we do not attempt to close a NULL file. */ - if (cur->file != last) { - last = cur->file; - track_file_close(cur); - } else - cur->file = NULL; - } - - /* Now free the array. */ - free(cdi->tracks); - cdi->tracks = NULL; - - /* Mark that there's no tracks. */ - cdi->tracks_num = 0; -} - -void -cdi_close(cd_img_t *cdi) -{ - cdi_clear_tracks(cdi); - free(cdi); -} - -int -cdi_set_device(cd_img_t *cdi, const char *path) -{ - int ret; - - if ((ret = cdi_load_cue(cdi, path))) - return ret; + if (idx->file == NULL) + return; - if ((ret = cdi_load_iso(cdi, path))) - return ret; + if (idx->file->close == NULL) + return; - return 0; + idx->file->close(idx->file); + idx->file = NULL; } void -cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) -{ - *st_track = 1; - *end = cdi->tracks_num - 1; - FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); -} - -void -cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out) -{ - *st_track = 1; - *end = cdi->tracks_num - 1; - *lead_out = cdi->tracks[*end].start; -} - -int -cdi_get_audio_track_pre(cd_img_t *cdi, int track) -{ - const track_t *trk = &cdi->tracks[track - 1]; - - if ((track < 1) || (track > cdi->tracks_num)) - return 0; - - return trk->pre; -} - -/* This replaces both Info and EndInfo, they are specified by a variable. */ -int -cdi_get_audio_track_info(cd_img_t *cdi, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) +cdi_get_raw_track_info(cd_img_t *cdi, int *num, uint8_t *buffer) { - const track_t *trk = &cdi->tracks[track - 1]; - // const int pos = trk->start + 150; - const int pos = trk->indexes[1].start; - - if ((track < 1) || (track > cdi->tracks_num)) - return 0; + int len = 0; - FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); + cdrom_image_backend_log("cdi->tracks_num = %i\n", cdi->tracks_num); - *track_num = trk->track_number; - *attr = trk->attr; + for (int i = 0; i < cdi->tracks_num; i++) { + track_t *ct = &(cdi->tracks[i]); +#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG + int old_len = len; +#endif + buffer[len++] = ct->session; /* Session number */ + buffer[len++] = ct->attr; /* Track ADR and Control */ + buffer[len++] = ct->tno; /* TNO (always 0) */ + buffer[len++] = ct->point; /* Point (for track points - track number) */ + for (int j = 0; j < 4; j++) + buffer[len++] = ct->extra[j]; + buffer[len++] = (ct->idx[1].start / 75) / 60; + buffer[len++] = (ct->idx[1].start / 75) % 60; + buffer[len++] = ct->idx[1].start % 75; + cdrom_image_backend_log("%i: %02X %02X %02X %02X %02X %02X %02X\n", i, + buffer[old_len], buffer[old_len + 1], buffer[old_len + 2], buffer[old_len + 3], + buffer[old_len + 8], buffer[old_len + 9], buffer[old_len + 10]); + } - return 1; + *num = cdi->tracks_num; } -int -cdi_get_audio_track_info_lba(cd_img_t *cdi, UNUSED(int end), int track, int *track_num, uint32_t *start, uint8_t *attr) +static int +cdi_get_track(cd_img_t *cdi, uint32_t sector) { - const track_t *trk = &cdi->tracks[track - 1]; + int ret = -1; - if ((track < 1) || (track > cdi->tracks_num)) - return 0; - - *start = (uint32_t) trk->start; - // *start = (uint32_t) trk->indexes[1].start - 150ULL; - - *track_num = trk->track_number; - *attr = trk->attr; - - return 1; -} - -void -cdi_get_raw_track_info(cd_img_t *cdi, int *num, uint8_t *buffer) -{ - TMSF tmsf; - int track_num = 0; - uint8_t attr = 0; - int len = 0; - int first_track; - int last_track; - - cdi_get_audio_tracks(cdi, &first_track, &last_track, &tmsf); - - *num = last_track + 3; - - cdi_get_audio_track_info(cdi, 0, 1, &track_num, &tmsf, &attr); - - buffer[len++] = 1; /* Session number */ - buffer[len++] = attr; /* Track ADR and Control */ - buffer[len++] = 0; /* TNO (always 0) */ - buffer[len++] = 0xA0; /* Point (for track points - track number) */ - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = track_num; /* First track number */ - buffer[len++] = 0; - buffer[len++] = 0; - - cdi_get_audio_track_info(cdi, 0, last_track, &track_num, &tmsf, &attr); - - buffer[len++] = 1; /* Session number */ - buffer[len++] = attr; /* Track ADR and Control */ - buffer[len++] = 0; /* TNO (always 0) */ - buffer[len++] = 0xA1; /* Point (for track points - track number) */ - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = track_num; /* Last track number */ - buffer[len++] = 0; - buffer[len++] = 0; - - cdi_get_audio_track_info(cdi, 0, last_track + 1, &track_num, &tmsf, &attr); - - cdrom_image_backend_log(" tracks(%i) = %02X, %02X, %02i:%02i.%02i\n", last_track, attr, - track_num, tmsf.min, tmsf.sec, tmsf.fr); - - buffer[len++] = 1; /* Session number */ - buffer[len++] = attr; /* Track ADR and Control */ - buffer[len++] = 0; /* TNO (always 0) */ - buffer[len++] = 0xA2; /* Point (for track points - track number) */ - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = tmsf.min; /* PM */ - buffer[len++] = tmsf.sec; /* PS */ - buffer[len++] = tmsf.fr; /* PF */ - - for (int i = 0; i < last_track; i++) { - cdi_get_audio_track_info(cdi, 0, i + 1, &track_num, &tmsf, &attr); - - cdrom_image_backend_log(" tracks(%i) = %02X, %02X, %02i:%02i.%02i\n", i, attr, - track_num, tmsf.min, tmsf.sec, tmsf.fr); - - buffer[len++] = 1; /* Session number */ - buffer[len++] = attr; /* Track ADR and Control */ - buffer[len++] = 0; /* TNO (always 0) */ - buffer[len++] = track_num; /* Point (for track points - track number) */ - /* Yes, this is correct - MSF followed by PMSF, the actual position is in PMSF. */ - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = 0; - buffer[len++] = tmsf.min; /* PM */ - buffer[len++] = tmsf.sec; /* PS */ - buffer[len++] = tmsf.fr; /* PF */ + for (int i = 0; i < cdi->tracks_num; i++) { + track_t *ct = &(cdi->tracks[i]); + for (int j = 0; j < 3; j++) { + track_index_t *ci = &(ct->idx[j]); + if (((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) { + ret = i; + break; + } + } } + + return ret; } -int -cdi_get_track(cd_img_t *cdi, uint32_t sector) +static void +cdi_get_track_and_index(cd_img_t *cdi, uint32_t sector, int *track, int *index) { - /* There must be at least two tracks - data and lead out. */ - if (cdi->tracks_num < 2) - return -1; - - /* This has a problem - the code skips the last track, which is - lead out - is that correct? */ - for (int i = 0; i < (cdi->tracks_num - 1); i++) { - const track_t *cur = &cdi->tracks[i]; - const track_t *next = &cdi->tracks[i + 1]; + *track = -1; + *index = -1; - /* Take into account cue sheets that do not start on sector 0. */ - // if ((i == 0) && (sector < cur->start)) - if ((i == 0) && (sector < cur->indexes[0].start)) - return cur->number; - - // if ((cur->start <= sector) && (sector < next->start)) - if ((cur->indexes[0].start <= sector) && (sector < next->indexes[0].start)) - return cur->number; + for (int i = 0; i < cdi->tracks_num; i++) { + track_t *ct = &(cdi->tracks[i]); + for (int j = 0; j < 3; j++) { + track_index_t *ci = &(ct->idx[j]); + if (((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) { + *track = i; + *index = j; + break; + } + } } - - return -1; } /* TODO: See if track start is adjusted by 150 or not. */ int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) { - const int cur_track = cdi_get_track(cdi, sector); + int cur_track = cdi_get_track(cdi, sector); if (cur_track < 1) return 0; *track = (uint8_t) cur_track; - const track_t *trk = &cdi->tracks[*track - 1]; + const track_t *trk = &cdi->tracks[*track]; *attr = trk->attr; *index = 1; + /* Absolute position should be adjusted by 150, not the relative ones. */ FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); - /* Absolute position should be adjusted by 150, not the relative ones. */ - // FRAMES_TO_MSF(sector - trk->start, &rel_pos->min, &rel_pos->sec, &rel_pos->fr); /* Relative position is relative Index 1 start - pre-gap values will be negative. */ - FRAMES_TO_MSF((int32_t) (sector + 150 - trk->indexes[1].start), &rel_pos->min, &rel_pos->sec, &rel_pos->fr); + FRAMES_TO_MSF((int32_t) (sector + 150 - trk->idx[1].start), &rel_pos->min, &rel_pos->sec, &rel_pos->fr); return 1; } -static int -cdi_get_sector_index(const track_t *trk, const uint32_t sector) -{ - int ret = 1; - - if ((sector + 150) < trk->indexes[1].start) - ret = 0; - else if ((sector + 150) >= trk->indexes[2].start) - ret = 2; - - return ret; -} - static __inline int bin2bcd(int x) { @@ -566,34 +413,37 @@ bin2bcd(int x) int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) { - const int track = cdi_get_track(cdi, sector) - 1; - const uint64_t sect = (uint64_t) sector; + const uint64_t sect = (uint64_t) sector; + int m = 0; + int s = 0; + int f = 0; + int ret = 0; + uint64_t offset = 0ULL; + int track; + int index; int raw_size; int cooked_size; - uint64_t offset; - int m = 0; - int s = 0; - int f = 0; - int ret = 0; uint8_t q[16] = { 0x00 }; + cdi_get_track_and_index(cdi, sector, &track, &index); + if (track < 0) return 0; - const track_t *trk = &cdi->tracks[track]; - const int track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); - - const uint64_t seek = trk->skip + ((sect - trk->start) * trk->sector_size); - const int index = cdi_get_sector_index(trk, sector); + const track_t *trk = &(cdi->tracks[track]); + const track_index_t *idx = &(trk->idx[index]); + const int track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); + const uint64_t seek = (sect + 150 - idx->start + idx->file_start) * trk->sector_size; + cdrom_image_backend_log("cdrom_read_sector(%08X): track %02X, index %02X, %016" PRIX64 ", %016" PRIX64 ", %i\n", - sector, track, index, trk->skip, trk->start, trk->sector_size); + sector, track, index, idx->start, trk->sector_size); if (track_is_raw) raw_size = trk->sector_size; else raw_size = 2448; - if (trk->mode2 && (trk->form != 1)) { + if ((trk->mode == 2) && (trk->form != 1)) { if (trk->form == 2) cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ else @@ -601,14 +451,12 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) } else cooked_size = COOKED_SECTOR_SIZE; - const size_t length = (raw ? raw_size : cooked_size); - - if (trk->mode2 && (trk->form >= 1)) + if ((trk->mode == 2) && (trk->form >= 1)) offset = 24ULL; else offset = 16ULL; - if (!trk->indexes[index].in_file) { + if (idx->type < INDEX_NORMAL) { memset(buffer, 0x00, 2448); if (trk->attr & 0x04) { /* Construct the rest of the raw sector. */ @@ -620,12 +468,13 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) buffer[1] = CDROM_BCD(s & 0xff); buffer[2] = CDROM_BCD(f & 0xff); /* Data, should reflect the actual sector type. */ - buffer[3] = trk->mode2 ? 2 : 1; + buffer[3] = trk->mode; ret = 1; } } else if (raw && !track_is_raw) { memset(buffer, 0x00, 2448); - const int temp = trk->file->read(trk->file, buffer + offset, seek, length); + /* We are doing a raw read but the track is cooked, length should be cooked size. */ + const int temp = idx->file->read(idx->file, buffer + offset, seek, cooked_size); if (temp <= 0) return temp; if (trk->attr & 0x04) { @@ -638,23 +487,29 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) buffer[1] = CDROM_BCD(s & 0xff); buffer[2] = CDROM_BCD(f & 0xff); /* Data, should reflect the actual sector type. */ - buffer[3] = trk->mode2 ? 2 : 1; + buffer[3] = trk->mode; ret = 1; } } else if (!raw && track_is_raw) - return trk->file->read(trk->file, buffer, seek + offset, length); + /* The track is raw but we are doing a cooked read, length should be cooked size. */ + return idx->file->read(idx->file, buffer, seek + offset, cooked_size); else { - ret = trk->file->read(trk->file, buffer, seek, length); + /* The track is raw and we are doing a raw read, length should be raw size. */ + ret = idx->file->read(idx->file, buffer, seek, raw_size); if (raw && (raw_size == 2448)) return ret; } /* Construct Q. */ q[0] = (trk->attr >> 4) | ((trk->attr & 0xf) << 4); - q[1] = bin2bcd(trk->track_number); - q[2] = 1; /* TODO: Index number. */ - // FRAMES_TO_MSF(sector - trk->start, &m, &s, &f); - FRAMES_TO_MSF((int32_t) (sector + 150 - trk->indexes[1].start), &m, &s, &f); + q[1] = bin2bcd(trk->point); + q[2] = index; + if (index == 0) { + /* Pre-gap sector relative frame addresses count from 00:01:74 downwards. */ + FRAMES_TO_MSF((int32_t) (149 - (sector + 150 - idx->start)), &m, &s, &f); + } else { + FRAMES_TO_MSF((int32_t) (sector + 150 - idx->start), &m, &s, &f); + } q[3] = bin2bcd(m); q[4] = bin2bcd(s); q[5] = bin2bcd(f); @@ -671,85 +526,90 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) return ret; } +/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ int -cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) +cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) { - int success = 1; + int track; + int index; - /* TODO: This fails to account for Mode 2. Shouldn't we have a function - to get sector size? */ - const int sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - const uint32_t buf_len = num * sector_size; - uint8_t *buf = (uint8_t *) calloc(1, buf_len * sizeof(uint8_t)); + cdi_get_track_and_index(cdi, sector, &track, &index); - for (uint32_t i = 0; i < num; i++) { - success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); - if (success <= 0) - break; - /* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an - audio track. */ - if (raw && (sector < cdi->tracks[0].length) && !cdi->tracks[0].mode2 && (cdi->tracks[0].attr != AUDIO_TRACK) && *(uint64_t *) &(buf[(i * sector_size) + 2068])) - return 0; - } + if (track < 0) + return 0; - memcpy((void *) buffer, buf, buf_len); - free(buf); - buf = NULL; + const track_t *trk = &(cdi->tracks[track]); + const track_index_t *idx = &(trk->idx[index]); - return success; + const uint64_t seek = (((uint64_t) sector + 150 - idx->start + idx->file_start) * trk->sector_size); + + if ((idx->type < INDEX_NORMAL) && (trk->sector_size != 2448)) + return 0; + + return idx->file->read(idx->file, buffer, seek, 2448); } -/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ int -cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) +cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) { - const int track = cdi_get_track(cdi, sector) - 1; + int track = cdi_get_track(cdi, sector); if (track < 0) return 0; - const track_t *trk = &cdi->tracks[track]; - const uint64_t seek = trk->skip + (((uint64_t) sector - trk->start) * trk->sector_size); - if (trk->sector_size != 2448) + const track_t *trk = &(cdi->tracks[track]); + + return trk->sector_size; +} + +int +cdi_is_audio(cd_img_t *cdi, uint32_t sector) +{ + int track = cdi_get_track(cdi, sector); + + if (track < 0) return 0; - return trk->file->read(trk->file, buffer, seek, 2448); + const track_t *trk = &(cdi->tracks[track]); + + return !!(trk->mode == 0); } int -cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) +cdi_is_pre(cd_img_t *cdi, uint32_t sector) { - const int track = cdi_get_track(cdi, sector) - 1; + int track = cdi_get_track(cdi, sector); if (track < 0) return 0; - const track_t *trk = &cdi->tracks[track]; - return trk->sector_size; + const track_t *trk = &(cdi->tracks[track]); + + return !!(trk->attr & 0x01); } int cdi_is_mode2(cd_img_t *cdi, uint32_t sector) { - const int track = cdi_get_track(cdi, sector) - 1; + int track = cdi_get_track(cdi, sector); if (track < 0) return 0; - const track_t *trk = &cdi->tracks[track]; + const track_t *trk = &(cdi->tracks[track]); - return !!(trk->mode2); + return !!(trk->mode == 2); } int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) { - const int track = cdi_get_track(cdi, sector) - 1; + int track = cdi_get_track(cdi, sector); if (track < 0) return 0; - const track_t *trk = &cdi->tracks[track]; + const track_t *trk = &(cdi->tracks[track]); return trk->form; } @@ -773,133 +633,6 @@ cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) 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)); } -/* This reallocates the array and returns the pointer to the last track. */ -static void -cdi_track_push_back(cd_img_t *cdi, track_t *trk) -{ - /* This has to be done so situations in which realloc would misbehave - can be detected and reported to the user. */ - if ((cdi->tracks != NULL) && (cdi->tracks_num == 0)) - fatal("CD-ROM Image: Non-null tracks array at 0 loaded tracks\n"); - if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) - fatal("CD-ROM Image: Null tracks array at non-zero loaded tracks\n"); - - cdi->tracks = realloc(cdi->tracks, (cdi->tracks_num + 1) * sizeof(track_t)); - memcpy(&(cdi->tracks[cdi->tracks_num]), trk, sizeof(track_t)); - cdi->tracks_num++; -} - -int -cdi_get_iso_track(cd_img_t *cdi, track_t *trk, const char *filename) -{ - int error = 0; - int ret = 2; - memset(trk, 0, sizeof(track_t)); - - /* Data track (shouldn't there be a lead in track?). */ - trk->file = bin_init(filename, &error); - if (error) { - if ((trk->file != NULL) && (trk->file->close != NULL)) - trk->file->close(trk->file); - ret = 3; - trk->file = viso_init(filename, &error); - if (error) { - if ((trk->file != NULL) && (trk->file->close != NULL)) - trk->file->close(trk->file); - return 0; - } - } - trk->number = 1; - trk->track_number = 1; - trk->attr = DATA_TRACK; - - /* Try to detect ISO type. */ - trk->form = 0; - trk->mode2 = 0; - - if (cdi_can_read_pvd(trk->file, RAW_SECTOR_SIZE, 0, 0)) - trk->sector_size = RAW_SECTOR_SIZE; - else if (cdi_can_read_pvd(trk->file, 2336, 1, 0)) { - trk->sector_size = 2336; - trk->mode2 = 1; - } else if (cdi_can_read_pvd(trk->file, 2324, 1, 2)) { - trk->sector_size = 2324; - trk->mode2 = 1; - trk->form = 2; - trk->noskip = 1; - } else if (cdi_can_read_pvd(trk->file, 2328, 1, 2)) { - trk->sector_size = 2328; - trk->mode2 = 1; - trk->form = 2; - trk->noskip = 1; - } else if (cdi_can_read_pvd(trk->file, 2336, 1, 1)) { - trk->sector_size = 2336; - trk->mode2 = 1; - trk->form = 1; - trk->skip = 8; - } else if (cdi_can_read_pvd(trk->file, RAW_SECTOR_SIZE, 1, 0)) { - trk->sector_size = RAW_SECTOR_SIZE; - trk->mode2 = 1; - } else if (cdi_can_read_pvd(trk->file, RAW_SECTOR_SIZE, 1, 1)) { - trk->sector_size = RAW_SECTOR_SIZE; - trk->mode2 = 1; - trk->form = 1; - } else { - /* We use 2048 mode 1 as the default. */ - trk->sector_size = COOKED_SECTOR_SIZE; - } - - trk->length = trk->file->get_length(trk->file) / trk->sector_size; - - trk->indexes[0].in_file = 0; - trk->indexes[0].start = 0; - trk->indexes[0].length = 150; - trk->indexes[1].in_file = 1; - trk->indexes[1].start = 150; - trk->indexes[1].length = trk->length; - trk->indexes[2].in_file = 0; - trk->indexes[2].start = trk->length + 150; - trk->indexes[2].length = 0; - - cdrom_image_backend_log("ISO: Data track: length = %" PRIu64 ", sector_size = %i\n", trk->length, trk->sector_size); - return ret; -} - -int -cdi_load_iso(cd_img_t *cdi, const char *filename) -{ - int ret = 2; - track_t trk = { 0 }; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - ret = cdi_get_iso_track(cdi, &trk, filename); - - if (ret >= 1) { - cdi_track_push_back(cdi, &trk); - - /* Lead out track. */ - trk.number = 2; - trk.track_number = 0xAA; - // trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ - trk.start = trk.length; - trk.file = NULL; - - for (int i = 0; i < 3; i++) { - trk.indexes[i].in_file = 0; - trk.indexes[i].start = trk.length + 150; - trk.indexes[i].length = 0; - } - - trk.length = 0; - - cdi_track_push_back(cdi, &trk); - } - - return ret; -} - static int cdi_cue_get_buffer(char *str, char **line, int up) { @@ -1020,120 +753,432 @@ cdi_cue_get_flags(track_t *cur, char **line) if (!success) return 0; - cur->pre = (strstr(temp2, "PRE") != NULL); + if (strstr(temp2, "PRE") != NULL) + cur->attr |= 0x01; + if (strstr(temp2, "DCP") != NULL) + cur->attr |= 0x02; + if (strstr(temp2, "4CH") != NULL) + cur->attr |= 0x08; return 1; } -uint64_t total_pregap = 0ULL; +static track_t * +cdi_insert_track(cd_img_t *cdi, uint8_t session, uint8_t point) +{ + track_t *ct = NULL; -static int -cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t cur_pregap) + cdi->tracks_num++; + if (cdi->tracks == NULL) { + cdi->tracks = calloc(1, sizeof(track_t)); + ct = &(cdi->tracks[0]); + } else { + cdi->tracks = realloc(cdi->tracks, cdi->tracks_num * sizeof(track_t)); + ct = &(cdi->tracks[cdi->tracks_num - 1]); + } + cdrom_image_backend_log("%02X: cdi->tracks[%2i] = %016" PRIX64 "\n", point, cdi->tracks_num - 1, (uint64_t) ct); + + memset(ct, 0x00, sizeof(track_t)); + + ct->session = session; + ct->point = point; + + for (int i = 0; i < 3; i++) + ct->idx[i].type = (point > 99) ? INDEX_SPECIAL : INDEX_NONE; + + return ct; +} + +static void +cdi_last_3_passes(cd_img_t *cdi) { - /* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */ - track_t *prev = NULL; + track_t *ct = NULL; + track_t *lt = NULL; + track_index_t *ci = NULL; + track_file_t *tf = NULL; + uint64_t tf_len = 0ULL; + uint64_t cur_pos = 0ULL; + int map[256] = { 0 }; + int lead[3] = { 0 }; + int pos = 0; + int ls = 0; + uint64_t spg[256] = { 0ULL }; + track_t *lo[256] = { 0 }; + + cdrom_image_backend_log("A2 = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[2])); + + for (int i = 0; i < cdi->tracks_num; i++) { + ct = &(cdi->tracks[i]); + if (((ct->point >= 1) && (ct->point <= 99)) || (ct->point >= 0xb0)) { + if (ct->point == 0xb0) { + /* Point B0h found, add the previous three lead tracks. */ + for (int j = 0; j < 3; j++) { + map[pos] = lead[j]; + pos++; + } + } - /* Skip *MUST* be calculated even if prestart is 0. */ - if (prestart > cur->start) - return 0; - /* If prestart is 0, there is no skip. */ - uint64_t skip = (prestart == 0) ? 0 : (cur->start - prestart); + map[pos] = i; + pos++; + } else if ((ct->point >= 0xa0) && (ct->point <= 0xa2)) + lead[ct->point & 0x03] = i; + } - if ((cdi->tracks != NULL) && (cdi->tracks_num != 0)) - prev = &cdi->tracks[cdi->tracks_num - 1]; - else if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) { - fatal("NULL cdi->tracks with non-zero cdi->tracks_num\n"); - return 0; + /* The last lead tracks. */ + for (int i = 0; i < 3; i++) { + map[pos] = lead[i]; + pos++; } +#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG + cdrom_image_backend_log("pos = %i, cdi->tracks_num = %i\n", pos, cdi->tracks_num); + for (int i = 0; i < pos; i++) + cdrom_image_backend_log("map[%02i] = %02X\n", i, map[i]); +#endif - /* First track (track number must be 1). */ - if ((prev == NULL) || (cdi->tracks_num == 0)) { - /* I guess this makes sure the structure is not filled with invalid data. */ - if (cur->number != 1) - return 0; - cur->skip = skip * cur->sector_size; - if ((cur->sector_size != RAW_SECTOR_SIZE) && (cur->form > 0) && !cur->noskip) - cur->skip += 8; - cur->start += cur_pregap; - cdi_track_push_back(cdi, cur); - return 1; + cdrom_image_backend_log("Second pass:\n"); + for (int i = (cdi->tracks_num - 1); i >= 0; i--) { + ct = &(cdi->tracks[map[i]]); + if (ct->idx[1].type != INDEX_SPECIAL) { + for (int j = 2; j >= 0; j--) { + ci = &(ct->idx[j]); + + if ((ci->type >= INDEX_ZERO) && (ci->file != tf)) { + tf = ci->file; + if (tf != NULL) { + tf_len = tf->get_length(tf) / ct->sector_size; + cdrom_image_backend_log(" File length: %016" PRIX64 " sectors\n", tf_len); + } + } + + if (ci->type == INDEX_NONE) { + /* Index was not in the cue sheet, keep its length at zero. */ + ci->file_start = tf_len; + } else if (ci->type == INDEX_NORMAL) { + /* Index was in the cue sheet and is present in the file. */ + ci->file_length = tf_len - ci->file_start; + tf_len -= ci->file_length; + } + + cdrom_image_backend_log(" TRACK %2i (%2i), ATTR %02X, INDEX %i: %2i, file_start = %016" + PRIX64 " (%2i:%02i:%02i), file_length = %016" PRIX64 " (%2i:%02i:%02i)\n", + i, map[i], + ct->attr, + j, ci->type, + ci->file_start, + (int) ((ci->file_start / 75) / 60), + (int) ((ci->file_start / 75) % 60), + (int) (ci->file_start % 75), + ci->file_length, + (int) ((ci->file_length / 75) / 60), + (int) ((ci->file_length / 75) % 60), + (int) (ci->file_length % 75)); + } + } } - if (prev->indexes[2].length != 0) { - prev->indexes[2].start = cur->indexes[0].start - prev->indexes[2].length; - prev->indexes[1].length = prev->indexes[2].start - prev->indexes[1].start; - cdrom_image_backend_log("Index 2 (%i): %02i:%02i:%02i\n", prev->indexes[2].in_file, - (int) ((prev->indexes[2].start / 75) / 60), (int) ((prev->indexes[2].start / 75) % 60), - (int) (prev->indexes[2].start % 75)); - } else if (prev->indexes[2].in_file) - prev->indexes[2].length = cur->indexes[0].start - prev->indexes[2].start; - else { - prev->indexes[1].length = cur->indexes[0].start - prev->indexes[1].start; - prev->indexes[2].start = prev->indexes[1].start + prev->indexes[1].length; - prev->indexes[2].length = 0; - cdrom_image_backend_log("Index 2 (%i): %02i:%02i:%02i\n", prev->indexes[2].in_file, - (int) ((prev->indexes[2].start / 75) / 60), (int) ((prev->indexes[2].start / 75) % 60), - (int) (prev->indexes[2].start % 75)); + cdrom_image_backend_log("Third pass:\n"); + for (int i = 0; i < cdi->tracks_num; i++) { + int session_changed = 0; + + ct = &(cdi->tracks[map[i]]); + if (ct->idx[1].type != INDEX_SPECIAL) { + if (ct->session != ls) { + /* The first track of a session always has a pre-gap of at least 0:02:00. */ + ci = &(ct->idx[0]); + if (ci->type == INDEX_NONE) { + ci->type = INDEX_ZERO; + ci->start = 0ULL; + ci->length = 150ULL; + } + + session_changed = 1; + ls = ct->session; + } + + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + + if (ci->type == INDEX_NONE) + /* Index was not in the cue sheet, keep its length at zero. */ + ci->start = cur_pos; + else if (ci->type == INDEX_ZERO) { + /* Index was in the cue sheet and is not present in the file. */ + ci->start = cur_pos; + cur_pos += ci->length; + } else if (ci->type == INDEX_NORMAL) { + /* Index was in the cue sheet and is present in the file. */ + ci->start = cur_pos; + ci->length = ci->file_length; + cur_pos += ci->file_length; + } + + cdrom_image_backend_log(" TRACK %2i (%2i) (%2i), ATTR %02X, MODE %i, INDEX %i: %2i, " + "start = %016" PRIX64 " (%2i:%02i:%02i), length = %016" PRIX64 + " (%2i:%02i:%02i)\n", + i, map[i], + ct->point, ct->attr, + ct->mode, + j, ci->type, + ci->start, + (int) ((ci->start / 75) / 60), + (int) ((ci->start / 75) % 60), + (int) (ci->start % 75), + ci->length, + (int) ((ci->length / 75) / 60), + (int) ((ci->length / 75) % 60), + (int) (ci->length % 75)); + + /* Set the pre-gap of the first track of this session. */ + if (session_changed) + spg[ct->session] = ct->idx[0].start; + } + } } - /* Current track consumes data from the same file as the previous. */ - if (prev->file == cur->file) { - cur->start += *shift; - prev->length = cur->start - prev->start - skip; - cur->skip += prev->skip + (prev->length * prev->sector_size) + (skip * cur->sector_size); - cur->start += cur_pregap; - } else { - const uint64_t temp = prev->file->get_length(prev->file) - (prev->skip); - prev->length = temp / ((uint64_t) prev->sector_size); - if ((temp % prev->sector_size) != 0) - /* Padding. */ - prev->length++; - - cur->start += prev->start + prev->length + cur_pregap; - cur->skip = skip * cur->sector_size; - if ((cur->sector_size != RAW_SECTOR_SIZE) && (cur->form > 0) && !cur->noskip) - cur->skip += 8; - *shift += prev->start + prev->length; + /* Set the lead out starts for all sessions. */ + for (int i = 0; i <= ls; i++) { + lo[i] = NULL; + for (int j = (cdi->tracks_num - 1); j >= 0; j--) { + track_t *jt = &(cdi->tracks[j]); + if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { + lo[i] = &(cdi->tracks[j]); + break; + } + } } - /* Error checks. */ - if (cur->number <= 1) - return 0; - if ((prev->number + 1) != cur->number) - return 0; - if (cur->start < (prev->start + prev->length)) + cdrom_image_backend_log("Fourth pass:\n"); + for (int i = 0; i < cdi->tracks_num; i++) { + ct = &(cdi->tracks[i]); + lt = NULL; + switch (ct->point) { + case 0xa0: + for (int j = 0; j < cdi->tracks_num; j++) { + track_t *jt = &(cdi->tracks[j]); + if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { + lt = &(cdi->tracks[j]); + break; + } + } + if (lt != NULL) { + int disc_type = 0x00; + + ct->attr = lt->attr; + + ct->mode = lt->mode; + ct->form = lt->form; + + if (lt->mode == 2) + disc_type = (lt->form > 0) ? 0x20 : 0x10; + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + ci->type = INDEX_ZERO; + ci->start = (lt->point * 60 * 75) + (disc_type * 75); + ci->length = 0; + } + } + break; + case 0xa1: + for (int j = (cdi->tracks_num - 1); j >= 0; j--) { + track_t *jt = &(cdi->tracks[j]); + if ((jt->session == ct->session) && (jt->point >= 1) && (jt->point <= 99)) { + lt = &(cdi->tracks[j]); + break; + } + } + if (lt != NULL) { + ct->attr = lt->attr; + + ct->mode = lt->mode; + ct->form = lt->form; + + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + ci->type = INDEX_ZERO; + ci->start = (lt->point * 60 * 75); + ci->length = 0; + } + } + break; + case 0xa2: + if (lo[ct->session] != NULL) { + lt = lo[ct->session]; + + ct->attr = lt->attr; + + ct->mode = lt->mode; + ct->form = lt->form; + + if (ct->idx[1].type != INDEX_NORMAL) { + track_index_t *li = &(lt->idx[2]); + + for (int j = 0; j < 3; j++) { + ci = &(ct->idx[j]); + ci->type = INDEX_ZERO; + ci->start = li->start + li->length; + ci->length = 0; + } + } + } + break; + case 0xb0: + /* + B0 MSF (*NOT* PMSF) points to the beginning of the pre-gap + of the corresponding session's first track. + */ + ct->extra[0] = (spg[ct->session] / 75) / 60; + ct->extra[1] = (spg[ct->session] / 75) % 60; + ct->extra[2] = spg[ct->session] % 75; + + /* + B0 PMSF points to the start of the lead out track + of the last session. + */ + if (lo[ls] != NULL) { + lt = lo[ls]; + track_index_t *li = &(lt->idx[2]); + + ct->idx[1].start = li->start + li->length; + } + break; + } + +#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG + if ((ct->point >= 0xa0) && (ct->point <= 0xa2)) + cdrom_image_backend_log(" TRACK %02X, SESSION %i: start = %016" PRIX64 " (%2i:%02i:%02i)\n", + ct->point, ct->session, + ct->idx[1].start, + (int) ((ct->idx[1].start / 75) / 60), + (int) ((ct->idx[1].start / 75) % 60), + (int) (ct->idx[1].start % 75)); +#endif + } +} + +int +cdi_load_iso(cd_img_t *cdi, const char *filename) +{ + track_t *ct = NULL; + track_index_t *ci = NULL; + track_file_t *tf = NULL; + int success; + int error = 1; + int is_viso = 0; + + cdi->tracks = NULL; + success = 1; + + cdrom_image_backend_log("First pass:\n"); + cdi->tracks_num = 0; + + cdi_insert_track(cdi, 1, 0xa0); + cdi_insert_track(cdi, 1, 0xa1); + cdi_insert_track(cdi, 1, 0xa2); + + /* Data track (shouldn't there be a lead in track?). */ + tf = track_file_init(filename, &error, &is_viso); + + if (error) { + cdrom_image_backend_log("ISO: cannot open file '%s'!\n", filename); + + if (tf != NULL) { + tf->close(tf); + tf = NULL; + } + success = 0; + } else if (is_viso) + success = 3; + + if (success) { + ct = cdi_insert_track(cdi, 1, 1); + ci = &(ct->idx[1]); + + ct->form = 0; + ct->mode = 0; + + for (int i = 0; i < 3; i++) + ct->idx[i].type = INDEX_NONE; + + ct->attr = DATA_TRACK; + + /* Try to detect ISO type. */ + ct->mode = 1; + ct->form = 0; + + ci->type = INDEX_NORMAL; + ci->file_start = 0ULL; + + ci->file = tf; + + /* For Mode 2 XA, skip the first 8 bytes in every sector when sector size = 2336. */ + if (cdi_can_read_pvd(ci->file, RAW_SECTOR_SIZE, 0, 0)) + ct->sector_size = RAW_SECTOR_SIZE; + else if (cdi_can_read_pvd(ci->file, 2336, 1, 0)) { + ct->sector_size = 2336; + ct->mode = 2; + } else if (cdi_can_read_pvd(ci->file, 2324, 1, 2)) { + ct->sector_size = 2324; + ct->mode = 2; + ct->form = 2; + } else if (cdi_can_read_pvd(ci->file, 2328, 1, 2)) { + ct->sector_size = 2328; + ct->mode = 2; + ct->form = 2; + } else if (cdi_can_read_pvd(ci->file, 2336, 1, 1)) { + ct->sector_size = 2336; + ct->mode = 2; + ct->form = 1; + ct->skip = 8; + } else if (cdi_can_read_pvd(ci->file, RAW_SECTOR_SIZE, 1, 0)) { + ct->sector_size = RAW_SECTOR_SIZE; + ct->mode = 2; + } else if (cdi_can_read_pvd(ci->file, RAW_SECTOR_SIZE, 1, 1)) { + ct->sector_size = RAW_SECTOR_SIZE; + ct->mode = 2; + ct->form = 1; + } else { + /* We use 2048 mode 1 as the default. */ + ct->sector_size = COOKED_SECTOR_SIZE; + } + + cdrom_image_backend_log("TRACK 1: Mode = %i, Form = %i, Sector size = %08X\n", + ct->mode, ct->form, ct->sector_size); + } + + tf = NULL; + + if (!success) return 0; - cdi_track_push_back(cdi, cur); + cdi_last_3_passes(cdi); - return 1; + return success; } int cdi_load_cue(cd_img_t *cdi, const char *cuefile) { - track_t trk; - char pathname[MAX_FILENAME_LENGTH]; - uint64_t shift = 0ULL; - uint64_t prestart = 0ULL; - uint64_t cur_pregap = 0ULL; - uint64_t frame = 0ULL; - uint64_t index; - int iso_file_used = 0; - int success; - int error; - int can_add_track = 0; - FILE *fp; - char buf[MAX_LINE_LENGTH]; - char *line; - char *command; - char *type; + track_t *ct = NULL; + track_index_t *ci = NULL; + track_file_t *tf = NULL; + uint64_t frame = 0ULL; + uint64_t last = 0ULL; + uint8_t session = 1; + int success; + int error; + int is_viso = 0; + int lead[3] = { 0 }; + char pathname[MAX_FILENAME_LENGTH]; + char buf[MAX_LINE_LENGTH]; + FILE *fp; + char *line; + char *command; + char *type; + char temp; cdi->tracks = NULL; cdi->tracks_num = 0; - memset(&trk, 0, sizeof(track_t)); - /* Get a copy of the filename into pathname, we need it later. */ memset(pathname, 0, MAX_FILENAME_LENGTH * sizeof(char)); path_get_dirname(pathname, cuefile); @@ -1145,11 +1190,20 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) success = 0; - for (;;) { + cdrom_image_backend_log("First pass:\n"); + cdi->tracks_num = 0; + + for (int i = 0; i < 3; i++) { + lead[i] = cdi->tracks_num; + (void *) cdi_insert_track(cdi, session, 0xa0 + i); + } + cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) &(cdi->tracks[lead[2]])); + + while (1) { line = buf; /* Read a line from the cuesheet file. */ - if (feof(fp) || fgets(buf, sizeof(buf), fp) == NULL || ferror(fp)) + if (feof(fp) || (fgets(buf, sizeof(buf), fp) == NULL) || ferror(fp)) break; /* Do two iterations to make sure to nuke even if it's \r\n or \n\r, @@ -1164,183 +1218,16 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) /* nuke trailing newline */ } } - cdrom_image_backend_log("line = %s\n", line); + cdrom_image_backend_log(" line = %s\n", line); (void) cdi_cue_get_keyword(&command, &line); - if (!strcmp(command, "TRACK")) { - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, cur_pregap); - else - success = 1; - if (!success) - break; - - cur_pregap = 0; - prestart = 0; - trk.number = cdi_cue_get_number(&line); - trk.track_number = trk.number; - cdrom_image_backend_log("cdi_load_cue(): Track %02X\n", trk.number); - success = cdi_cue_get_keyword(&type, &line); - - memset(trk.indexes, 0x00, sizeof(trk.indexes)); - - if (!success) - break; - - if (iso_file_used) { - /* - We don't alter anything of the detected track type with - the one specified in the CUE file, except its numbers. - */ - can_add_track = 1; - - iso_file_used = 0; - } else { - trk.start = 0; - trk.skip = 0; - - trk.form = 0; - trk.mode2 = 0; - - trk.pre = 0; - - if (!strcmp(type, "AUDIO")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = AUDIO_TRACK; - } else if (!strcmp(type, "MODE1/2048")) { - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE1/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - } else if (!strcmp(type, "MODE2/2048")) { - trk.form = 1; - trk.sector_size = COOKED_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2324")) { - trk.form = 2; - trk.sector_size = 2324; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2328")) { - trk.form = 2; - trk.sector_size = 2328; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2336")) { - trk.form = 1; - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2352")) { - /* Assume this is XA Mode 2 Form 1. */ - trk.form = 1; - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "MODE2/2448")) { - /* Assume this is XA Mode 2 Form 1. */ - trk.form = 1; - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDG/2448")) { - trk.sector_size = 2448; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2336")) { - trk.sector_size = 2336; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else if (!strcmp(type, "CDI/2352")) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.attr = DATA_TRACK; - trk.mode2 = 1; - } else - success = 0; - - cdrom_image_backend_log("cdi_load_cue(): Format: %i bytes per sector, %02X, %i, %i\n", - trk.sector_size, trk.attr, trk.mode2, trk.form); - - can_add_track = 1; - } - } else if (!strcmp(command, "INDEX")) { - index = cdi_cue_get_number(&line); - success = cdi_cue_get_frame(&frame, &line); - - switch (index) { - case 0: - prestart = frame; - trk.indexes[0].in_file = 1; - trk.indexes[0].start = prestart + total_pregap; - break; - - case 1: - if (trk.indexes[0].in_file) - trk.indexes[0].length = frame - prestart; - else if (cur_pregap > 0) { - trk.indexes[0].start = frame + total_pregap; - trk.indexes[0].length = cur_pregap; - total_pregap += trk.indexes[0].length; - } else if (trk.number == 1) { - trk.indexes[0].start = 0; - trk.indexes[0].length = 150; - total_pregap += trk.indexes[0].length; - } else { - trk.indexes[0].start = frame + total_pregap; - trk.indexes[0].length = 0; - } - cdrom_image_backend_log("Index 0 (%i): %02i:%02i:%02i\n", trk.indexes[0].in_file, - (int) ((trk.indexes[0].start / 75) / 60), - (int) ((trk.indexes[0].start / 75) % 60), - (int) (trk.indexes[0].start % 75)); - - if (cur_pregap > 0) - trk.start = frame + cur_pregap; - else - trk.start = frame; - trk.indexes[1].start = trk.indexes[0].start + trk.indexes[0].length; - trk.indexes[1].in_file = 1; - cdrom_image_backend_log("Index 1 (%i): %02i:%02i:%02i\n", trk.indexes[1].in_file, - (int) ((trk.indexes[1].start / 75) / 60), - (int) ((trk.indexes[1].start / 75) % 60), - (int) (trk.indexes[1].start % 75)); - break; - - case 2: - trk.indexes[2].in_file = 1; - if (cur_pregap > 0) - trk.indexes[2].start = frame + cur_pregap; - else - trk.indexes[2].start = frame; - trk.indexes[1].length = trk.indexes[2].start - trk.indexes[1].start; - trk.indexes[2].length = 0; - cdrom_image_backend_log("Index 2 (%i): %02i:%02i:%02i\n", trk.indexes[2].in_file, - (int) ((trk.indexes[2].start / 75) / 60), - (int) ((trk.indexes[2].start / 75) % 60), - (int) (trk.indexes[2].start % 75)); - break; - - default: - /* Ignore other indices. */ - break; - } - } else if (!strcmp(command, "FILE")) { + if (!strcmp(command, "FILE")) { + /* The file for the track. */ char filename[MAX_FILENAME_LENGTH]; char ansi[MAX_FILENAME_LENGTH]; - if (can_add_track) - success = cdi_add_track(cdi, &trk, &shift, prestart, cur_pregap); - else - success = 1; - if (!success) - break; - can_add_track = 0; + tf = NULL; memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char)); memset(filename, 0, MAX_FILENAME_LENGTH * sizeof(char)); @@ -1352,61 +1239,177 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) if (!success) break; - trk.file = NULL; error = 1; + is_viso = 0; if (!strcmp(type, "BINARY") || !strcmp(type, "MOTOROLA")) { - int fn_len = 0; - if (!path_abs(ansi)) { + if (!path_abs(ansi)) path_append_filename(filename, pathname, ansi); - } else { + else strcpy(filename, ansi); - } - fn_len = strlen(filename); - if ((tolower((int) filename[fn_len - 1]) == 'o' - && tolower((int) filename[fn_len - 2]) == 's' - && tolower((int) filename[fn_len - 3]) == 'i' - && filename[fn_len - 4] == '.') - || plat_dir_check(filename)) { - error = !cdi_get_iso_track(cdi, &trk, filename); - if (!error) { - iso_file_used = 1; - } - } else - trk.file = track_file_init(filename, &error); + + tf = track_file_init(filename, &error, &is_viso); - if (trk.file) { - trk.file->motorola = !strcmp(type, "MOTOROLA"); - } + if (tf) + tf->motorola = !strcmp(type, "MOTOROLA"); } else if (!strcmp(type, "WAVE") || !strcmp(type, "AIFF") || !strcmp(type, "MP3")) { - if (!path_abs(ansi)) { + if (!path_abs(ansi)) path_append_filename(filename, pathname, ansi); - } else { + else strcpy(filename, ansi); - } - trk.file = audio_init(filename, &error); + tf = audio_init(filename, &error); } if (error) { cdrom_image_backend_log("CUE: cannot open file '%s' in cue sheet!\n", filename); - if (trk.file != NULL) { - trk.file->close(trk.file); - trk.file = NULL; + if (tf != NULL) { + tf->close(tf); + tf = NULL; } success = 0; - } - } else if (!strcmp(command, "PREGAP")) - success = cdi_cue_get_frame(&cur_pregap, &line); - else if (!strcmp(command, "POSTGAP")) { - success = cdi_cue_get_frame(&trk.indexes[2].length, &line); - trk.indexes[2].in_file = 0; + } else if (is_viso) + success = 3; + } else if (!strcmp(command, "TRACK")) { + int t = cdi_cue_get_number(&line); + success = cdi_cue_get_keyword(&type, &line); + + if (!success) + break; + + ct = cdi_insert_track(cdi, session, t); + + cdrom_image_backend_log(" TRACK %i\n", t); + + ct->form = 0; + ct->mode = 0; + + if (!strcmp(type, "AUDIO")) { + ct->sector_size = RAW_SECTOR_SIZE; + ct->attr = AUDIO_TRACK; + } else if (!memcmp(type, "MODE", 4)) { + uint32_t mode; + ct->attr = DATA_TRACK; + sscanf(type, "MODE%" PRIu32 "/%" PRIu32, &mode, &(ct->sector_size)); + ct->mode = mode; + if (ct->mode == 2) switch(ct->sector_size) { + case 2324: case 2328: + ct->form = 2; + break; + case 2048: case 2336: case 2352: case 2448: + ct->form = 1; + break; + } + if ((ct->sector_size == 2336) && (ct->mode == 2) && (ct->form == 1)) + ct->skip = 8; + } else if (!memcmp(type, "CD", 2)) { + ct->attr = DATA_TRACK; + ct->mode = 2; + sscanf(type, "CD%c/%i", &temp, &(ct->sector_size)); + } else + success = 0; + + if (success) + last = ct->sector_size; + } else if (!strcmp(command, "INDEX")) { + int t = cdi_cue_get_number(&line); + ci = &(ct->idx[t]); + + cdrom_image_backend_log(" INDEX %i (1)\n", t); + + ci->type = INDEX_NORMAL; + ci->file = tf; + success = cdi_cue_get_frame(&frame, &line); + ci->file_start = frame; + } else if (!strcmp(command, "PREGAP")) { + ci = &(ct->idx[0]); + cdrom_image_backend_log(" INDEX 0 (0)\n"); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = cdi_cue_get_frame(&frame, &line); + ci->length = frame; + } else if (!strcmp(command, "PAUSE")) { + ci = &(ct->idx[1]); + cdrom_image_backend_log(" INDEX 1 (0)\n"); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = cdi_cue_get_frame(&frame, &line); + ci->length = frame; + } else if (!strcmp(command, "POSTGAP")) { + ci = &(ct->idx[2]); + cdrom_image_backend_log(" INDEX 2 (0)\n"); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = cdi_cue_get_frame(&frame, &line); + ci->length = frame; + } else if (!strcmp(command, "ZERO")) { + ci = &(ct->idx[1]); + cdrom_image_backend_log(" INDEX 1 (0)\n"); + + ci->type = INDEX_ZERO; + ci->file = tf; + success = cdi_cue_get_frame(&frame, &line); + ci->length = frame; } else if (!strcmp(command, "FLAGS")) - success = cdi_cue_get_flags(&trk, &line); - else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { + success = cdi_cue_get_flags(ct, &line); + else if (!strcmp(command, "REM")) { + success = 1; + char *space = strstr(line, " "); + if (space != NULL) { + space++; + if (space < (line + strlen(line))) { + (void) cdi_cue_get_keyword(&command, &space); + if (!strcmp(command, "LEAD-OUT")) { + ct = &(cdi->tracks[lead[2]]); + cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", (uint64_t) ct); + ct->sector_size = last; + ci = &(ct->idx[1]); + ci->type = INDEX_NORMAL; + ci->file = tf; + success = cdi_cue_get_frame(&frame, &space); + ci->file_start = frame; + + cdrom_image_backend_log(" LEAD-OUT\n"); + } else if (!strcmp(command, "SESSION")) { + session = cdi_cue_get_number(&space); + + if (session > 1) { + ct = cdi_insert_track(cdi, session - 1, 0xb0); + ci = &(ct->idx[1]); + ci->start = (0x40 * 60 * 75) + (0x02 * 75); + + if (session == 2) { + ct->extra[3] = 0x02; + + /* 5F:00:00 on Wembley, C0:00:00 in the spec. And what's in PMSF? */ + ct = cdi_insert_track(cdi, session - 1, 0xc0); + ci = &(ct->idx[1]); + ct->extra[0] = 0x5f; /* Optimum recording power. */ + } else + ct->extra[3] = 0x01; + + for (int i = 0; i < 3; i++) { + lead[i] = cdi->tracks_num; + (void *) cdi_insert_track(cdi, session, 0xa0 + i); + } + cdrom_image_backend_log("lead[2] = %016" PRIX64 "\n", + (uint64_t) &(cdi->tracks[lead[2]])); + } + + cdrom_image_backend_log(" SESSION %i\n", session); + } + } + } + } else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || + !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || + !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || + !strcmp(command, "")) /* Ignored commands. */ success = 1; - } else { + else { cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command); success = 0; @@ -1416,94 +1419,81 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) break; } + tf = NULL; + fclose(fp); - if (!success) - return 0; - /* Add last track. */ - cdrom_image_backend_log("LEAD OUT\n"); - if (!cdi_add_track(cdi, &trk, &shift, prestart, cur_pregap)) + if (!success) return 0; - /* Add lead out track. */ - cdrom_image_backend_log("END OF CUE\n"); - trk.number++; - memset(trk.indexes, 0x00, sizeof(trk.indexes)); - trk.track_number = 0xAA; - // trk.attr = 0x16; - trk.start = 0; - trk.length = 0; - trk.file = NULL; - if (!cdi_add_track(cdi, &trk, &shift, 0, 0)) - return 0; + cdi_last_3_passes(cdi); - track_t *cur = &cdi->tracks[cdi->tracks_num - 1]; - track_t *prev = &cdi->tracks[cdi->tracks_num - 2]; + return success; +} - for (int i = 0; i < 3; i++) { - cur->indexes[i].in_file = 0; - cur->indexes[i].start = prev->indexes[1].start + prev->length - 150; - cur->indexes[i].length = 0; - } +/* Root functions. */ +static void +cdi_clear_tracks(cd_img_t *cdi) +{ + track_file_t *last = NULL; + track_t *cur = NULL; + track_index_t *idx = NULL; - if (prev->indexes[2].length != 0) { - prev->indexes[2].start = cur->indexes[0].start - prev->indexes[2].length; - prev->indexes[1].length = prev->indexes[2].start - prev->indexes[1].start; - } else if (prev->indexes[2].in_file) - prev->indexes[2].length = cur->indexes[0].start - prev->indexes[2].start; - else { - prev->indexes[1].length = cur->indexes[0].start - prev->indexes[1].start; - prev->indexes[2].start = prev->indexes[1].start + prev->indexes[1].length; - prev->indexes[2].length = 0; - } + if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) + return; -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG for (int i = 0; i < cdi->tracks_num; i++) { - track_t *t = &(cdi->tracks[i]); - for (int j = 0; j < 3; j++) { - track_index_t *ti = &(t->indexes[j]); - cdrom_image_backend_log("Track %02X.%01X (%i): %02i:%02i:%02i-%02i:%02i:%02i\n", - t->track_number, j, - ti->in_file, - (int) ((ti->start / 75) / 60), - (int) ((ti->start / 75) % 60), - (int) (ti->start % 75), - (int) (((ti->start + ti->length - 1) / 75) / 60), - (int) (((ti->start + ti->length - 1) / 75) % 60), - (int) ((ti->start + ti->length - 1) % 75)); + cur = &cdi->tracks[i]; + + if ((cur->point >= 1) && (cur->point <= 99)) for (int j = 0; j < 3; j++) { + idx = &(cur->idx[j]); + + /* Make sure we do not attempt to close a NULL file. */ + if (idx->file != NULL) { + if (idx->file != last) { + last = idx->file; + index_file_close(idx); + } else + idx->file = NULL; + } } } -#endif - return 1; + /* Now free the array. */ + free(cdi->tracks); + cdi->tracks = NULL; + + /* Mark that there's no tracks. */ + cdi->tracks_num = 0; } -int -cdi_has_data_track(cd_img_t *cdi) +void +cdi_close(cd_img_t *cdi) { - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; - - /* Data track has attribute 0x14. */ - for (int i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == DATA_TRACK) - return 1; - } - - return 0; + cdi_clear_tracks(cdi); + free(cdi); } int -cdi_has_audio_track(cd_img_t *cdi) +cdi_set_device(cd_img_t *cdi, const char *path) { - if ((cdi == NULL) || (cdi->tracks == NULL)) - return 0; + uintptr_t ext = path + strlen(path) - strrchr(path, '.'); + int ret; - /* Audio track has attribute 0x10. */ - for (int i = 0; i < cdi->tracks_num; i++) { - if (cdi->tracks[i].attr == AUDIO_TRACK) - return 1; + cdrom_image_backend_log("cdi_set_device(): %" PRIu64 ", %lli, %s\n", + ext, strlen(path), path + strlen(path) - ext + 1); + + if ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE")) { + if ((ret = cdi_load_cue(cdi, path))) + return ret; + + cdi_clear_tracks(cdi); } + if ((ret = cdi_load_iso(cdi, path))) + return ret; + + cdi_close(cdi); + return 0; } diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index edca09d918..24f60836d6 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -8,9 +8,7 @@ * * Virtual ISO CD-ROM image back-end. * - * - * - * Authors: RichardG + * Authors: RichardG, * * Copyright 2022 RichardG. */ diff --git a/src/cdrom/cdrom_ioctl.c b/src/cdrom/cdrom_ioctl.c index eccb75fefe..2bb691f307 100644 --- a/src/cdrom/cdrom_ioctl.c +++ b/src/cdrom/cdrom_ioctl.c @@ -55,14 +55,6 @@ cdrom_ioctl_log(const char *fmt, ...) of the audio while audio still plays. With an absolute conversion, the counter is fine. */ #define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f) -static void -ioctl_get_tracks(cdrom_t *dev, int *first, int *last) -{ - TMSF tmsf; - - plat_cdrom_get_audio_tracks(dev->local, first, last, &tmsf); -} - static void ioctl_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti) { @@ -209,7 +201,6 @@ ioctl_exit(cdrom_t *dev) } static const cdrom_ops_t cdrom_ioctl_ops = { - ioctl_get_tracks, ioctl_get_track_info, ioctl_get_raw_track_info, ioctl_get_subchannel, diff --git a/src/device.c b/src/device.c index 0fd4bb64ea..e17cff3bec 100644 --- a/src/device.c +++ b/src/device.c @@ -19,7 +19,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2008-2019 Sarah Walker. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -89,38 +89,38 @@ device_init(void) } void -device_set_context(device_context_t *c, const device_t *dev, int inst) +device_set_context(device_context_t *ctx, const device_t *dev, int inst) { - memset(c, 0, sizeof(device_context_t)); - c->dev = dev; - c->instance = inst; + memset(ctx, 0, sizeof(device_context_t)); + ctx->dev = dev; + ctx->instance = inst; if (inst) { - sprintf(c->name, "%s #%i", dev->name, inst); + sprintf(ctx->name, "%s #%i", dev->name, inst); /* If a numbered section is not present, but a non-numbered of the same name is, rename the non-numbered section to numbered. */ - const void *sec = config_find_section(c->name); + const void *sec = config_find_section(ctx->name); void * single_sec = config_find_section((char *) dev->name); if ((sec == NULL) && (single_sec != NULL)) - config_rename_section(single_sec, c->name); + config_rename_section(single_sec, ctx->name); } else if (!strcmp(dev->name, "PS/2 Mouse")) { - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); /* Migrate the old "Standard PS/2 Mouse" section */ - const void *sec = config_find_section(c->name); + const void *sec = config_find_section(ctx->name); void * old_sec = config_find_section("Standard PS/2 Mouse"); if ((sec == NULL) && (old_sec != NULL)) - config_rename_section(old_sec, c->name); + config_rename_section(old_sec, ctx->name); } else if (!strcmp(dev->name, "Microsoft RAMCard")) { - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); - /* Migrate the old "Standard PS/2 Mouse" section */ - const void *sec = config_find_section(c->name); + /* Migrate the old "Microsoft RAMCard for IBM PC" section */ + const void *sec = config_find_section(ctx->name); void * old_sec = config_find_section("Microsoft RAMCard for IBM PC"); if ((sec == NULL) && (old_sec != NULL)) - config_rename_section(old_sec, c->name); + config_rename_section(old_sec, ctx->name); } else - sprintf(c->name, "%s", dev->name); + sprintf(ctx->name, "%s", dev->name); } static void @@ -153,7 +153,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) { device_t *init_dev = NULL; void *priv = NULL; - int c; + int16_t c; if (params != NULL) { init_dev = calloc(1, sizeof(device_t)); @@ -162,7 +162,7 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) } else init_dev = (device_t *) dev; - for (c = 0; c < 256; c++) { + for (c = 0; c < DEVICE_MAX; c++) { if (!inst && (devices[c] == dev)) { device_log("DEVICE: device already exists!\n"); return (NULL); @@ -244,6 +244,7 @@ void * device_add_linked(const device_t *dev, void *priv) { void *ret; + device_common_priv = priv; ret = device_add_common(dev, NULL, NULL, 0); device_common_priv = NULL; @@ -311,7 +312,8 @@ device_close_all(void) #endif if (devices[c]->close != NULL) devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; + devices[c] = NULL; + device_priv[c] = NULL; } } } @@ -372,7 +374,7 @@ device_available(const device_t *dev) if (dev != NULL) { config = dev->config; if (config != NULL) { - while (config->type != -1) { + while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { int roms_present = 0; @@ -414,7 +416,7 @@ device_get_bios_file(const device_t *dev, const char *internal_name, int file_no if (dev != NULL) { config = dev->config; if (config != NULL) { - while (config->type != -1) { + while (config->type != CONFIG_END) { if (config->type == CONFIG_BIOS) { bios = config->bios; @@ -452,7 +454,7 @@ device_has_config(const device_t *dev) config = dev->config; - while (config->type != -1) { + while (config->type != CONFIG_END) { c++; config++; } @@ -493,14 +495,26 @@ device_get_name(const device_t *dev, int bus, char *name) sbus = (dev->flags & DEVICE_AT) ? "ISA16" : "ISA"; else if (dev->flags & DEVICE_CBUS) sbus = "C-BUS"; + else if (dev->flags & DEVICE_PCMCIA) + sbus = "PCMCIA"; else if (dev->flags & DEVICE_MCA) sbus = "MCA"; + else if (dev->flags & DEVICE_HIL) + sbus = "HP HIL"; else if (dev->flags & DEVICE_EISA) sbus = "EISA"; + else if (dev->flags & DEVICE_AT32) + sbus = "AT/32"; + else if (dev->flags & DEVICE_OLB) + sbus = "OLB"; else if (dev->flags & DEVICE_VLB) sbus = "VLB"; else if (dev->flags & DEVICE_PCI) sbus = "PCI"; + else if (dev->flags & DEVICE_CARDBUS) + sbus = "CARDBUS"; + else if (dev->flags & DEVICE_USB) + sbus = "USB"; else if (dev->flags & DEVICE_AGP) sbus = "AGP"; else if (dev->flags & DEVICE_AC97) @@ -533,8 +547,7 @@ device_get_name(const device_t *dev, int bus, char *name) strcat(pbus, ")"); /* Allocate the temporary device name string and set it to all zeroes. */ - tname = (char *) malloc(strlen(dev->name) + 1); - memset(tname, 0x00, strlen(dev->name) + 1); + tname = (char *) calloc(1, strlen(dev->name) + 1); /* First strip the bus string with parentheses. */ fbus = strstr(dev->name, pbus); @@ -602,253 +615,256 @@ device_get_instance(void) } const char * -device_get_config_string(const char *s) +device_get_config_string(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_string((char *) device_current.name, (char *) s, (char *) c->default_string)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_string((char *) device_current.name, (char *) str, (char *) cfg->default_string)); - c++; + cfg++; } return (NULL); } int -device_get_config_int(const char *s) +device_get_config_int(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_int_ex(const char *s, int def) +device_get_config_int_ex(const char *str, int def) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) device_current.name, (char *) s, def)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) device_current.name, (char *) str, def)); - c++; + cfg++; } return def; } int -device_get_config_hex16(const char *s) +device_get_config_hex16(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_hex16((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_hex20(const char *s) +device_get_config_hex20(const char *str) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_hex20((char *) device_current.name, (char *) s, c->default_int)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int)); - c++; + cfg++; } return 0; } int -device_get_config_mac(const char *s, int def) +device_get_config_mac(const char *str, int def) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_mac((char *) device_current.name, (char *) s, def)); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_mac((char *) device_current.name, (char *) str, def)); - c++; + cfg++; } return def; } void -device_set_config_int(const char *s, int val) +device_set_config_int(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_int((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_int((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_hex16(const char *s, int val) +device_set_config_hex16(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_hex16((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_hex16((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_hex20(const char *s, int val) +device_set_config_hex20(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_hex20((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_hex20((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } void -device_set_config_mac(const char *s, int val) +device_set_config_mac(const char *str, int val) { - const device_config_t *c = device_current.dev->config; + const device_config_t *cfg = device_current.dev->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) { - config_set_mac((char *) device_current.name, (char *) s, val); + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) { + config_set_mac((char *) device_current.name, (char *) str, val); break; } - c++; + cfg++; } } int -device_is_valid(const device_t *device, int m) +device_is_valid(const device_t *device, int mch) { if (device == NULL) return 1; - if ((device->flags & DEVICE_PCJR) && !machine_has_bus(m, MACHINE_BUS_PCJR)) + if ((device->flags & DEVICE_PCJR) && !machine_has_bus(mch, MACHINE_BUS_PCJR)) + return 0; + + if ((device->flags & DEVICE_XTKBC) && machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) return 0; - if ((device->flags & DEVICE_XTKBC) && machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + if ((device->flags & DEVICE_AT) && !machine_has_bus(mch, MACHINE_BUS_ISA16)) return 0; - if ((device->flags & DEVICE_AT) && !machine_has_bus(m, MACHINE_BUS_ISA16)) + if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(mch, MACHINE_BUS_ISA16) && !machine_has_bus(mch, MACHINE_BUS_DM_KBC)) return 0; - if ((device->flags & DEVICE_ATKBC) && !machine_has_bus(m, MACHINE_BUS_ISA16) && !machine_has_bus(m, MACHINE_BUS_DM_KBC)) + if ((device->flags & DEVICE_PS2) && !machine_has_bus(mch, MACHINE_BUS_PS2_PORTS)) return 0; - if ((device->flags & DEVICE_ISA) && !machine_has_bus(m, MACHINE_BUS_ISA)) + if ((device->flags & DEVICE_ISA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) return 0; - if ((device->flags & DEVICE_CBUS) && !machine_has_bus(m, MACHINE_BUS_CBUS)) + if ((device->flags & DEVICE_CBUS) && !machine_has_bus(mch, MACHINE_BUS_CBUS)) return 0; - if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(m, MACHINE_BUS_PCMCIA)) + if ((device->flags & DEVICE_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_PCMCIA) && !machine_has_bus(mch, MACHINE_BUS_ISA)) return 0; - if ((device->flags & DEVICE_MCA) && !machine_has_bus(m, MACHINE_BUS_MCA)) + if ((device->flags & DEVICE_MCA) && !machine_has_bus(mch, MACHINE_BUS_MCA)) return 0; - if ((device->flags & DEVICE_HIL) && !machine_has_bus(m, MACHINE_BUS_HIL)) + if ((device->flags & DEVICE_HIL) && !machine_has_bus(mch, MACHINE_BUS_HIL)) return 0; - if ((device->flags & DEVICE_EISA) && !machine_has_bus(m, MACHINE_BUS_EISA)) + if ((device->flags & DEVICE_EISA) && !machine_has_bus(mch, MACHINE_BUS_EISA)) return 0; - if ((device->flags & DEVICE_OLB) && !machine_has_bus(m, MACHINE_BUS_OLB)) + if ((device->flags & DEVICE_AT32) && !machine_has_bus(mch, MACHINE_BUS_AT32)) return 0; - if ((device->flags & DEVICE_VLB) && !machine_has_bus(m, MACHINE_BUS_VLB)) + if ((device->flags & DEVICE_OLB) && !machine_has_bus(mch, MACHINE_BUS_OLB)) return 0; - if ((device->flags & DEVICE_PCI) && !machine_has_bus(m, MACHINE_BUS_PCI)) + if ((device->flags & DEVICE_VLB) && !machine_has_bus(mch, MACHINE_BUS_VLB)) return 0; - if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(m, MACHINE_BUS_CARDBUS)) + if ((device->flags & DEVICE_PCI) && !machine_has_bus(mch, MACHINE_BUS_PCI)) return 0; - if ((device->flags & DEVICE_USB) && !machine_has_bus(m, MACHINE_BUS_USB)) + if ((device->flags & DEVICE_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_CARDBUS) && !machine_has_bus(mch, MACHINE_BUS_PCI)) return 0; - if ((device->flags & DEVICE_AGP) && !machine_has_bus(m, MACHINE_BUS_AGP)) + if ((device->flags & DEVICE_USB) && !machine_has_bus(mch, MACHINE_BUS_USB)) return 0; - if ((device->flags & DEVICE_PS2) && !machine_has_bus(m, MACHINE_BUS_PS2_PORTS)) + if ((device->flags & DEVICE_AGP) && !machine_has_bus(mch, MACHINE_BUS_AGP)) return 0; - if ((device->flags & DEVICE_AC97) && !machine_has_bus(m, MACHINE_BUS_AC97)) + if ((device->flags & DEVICE_AC97) && !machine_has_bus(mch, MACHINE_BUS_AC97)) return 0; return 1; } int -machine_get_config_int(char *s) +machine_get_config_int(char *str) { - const device_t *d = machine_get_device(machine); - const device_config_t *c; + const device_t *dev = machine_get_device(machine); + const device_config_t *cfg; - if (d == NULL) + if (dev == NULL) return 0; - c = d->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_int((char *) d->name, s, c->default_int)); + cfg = dev->config; + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_int((char *) dev->name, str, cfg->default_int)); - c++; + cfg++; } return 0; } char * -machine_get_config_string(char *s) +machine_get_config_string(char *str) { - const device_t *d = machine_get_device(machine); - const device_config_t *c; + const device_t *dev = machine_get_device(machine); + const device_config_t *cfg; - if (d == NULL) + if (dev == NULL) return 0; - c = d->config; - while (c && c->type != -1) { - if (!strcmp(s, c->name)) - return (config_get_string((char *) d->name, s, (char *) c->default_string)); + cfg = dev->config; + while (cfg && cfg->type != CONFIG_END) { + if (!strcmp(str, cfg->name)) + return (config_get_string((char *) dev->name, str, (char *) cfg->default_string)); - c++; + cfg++; } return NULL; @@ -868,7 +884,7 @@ const device_t device_none = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -882,7 +898,7 @@ const device_t device_internal = { .init = NULL, .close = NULL, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 0139eeb235..4701479530 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -137,6 +137,8 @@ isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld) card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ card->config.mem[i].size -= card->config.mem[i].base; + else + card->config.mem[i].size = (card->config.mem[i].size | 0xff) ^ 0xffffffff; } for (uint8_t i = 0; i < 4; i++) { reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); @@ -789,10 +791,25 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) break; } - isapnp_log("ISAPnP: >>%s Memory range %d with %d bytes at %06X-%06X, align %d", - in_df ? ">" : "", mem_range, - *((uint16_t *) &card->rom[i + 10]) << 8, *((uint16_t *) &card->rom[i + 4]) << 8, ((card->rom[i + 3] & 0x4) ? 0 : (*((uint16_t *) &card->rom[i + 4]) << 8)) + (*((uint16_t *) &card->rom[i + 6]) << 8), - (*((uint16_t *) &card->rom[i + 8]) + 1) << 16); + isapnp_log("ISAPnP: >>%s Memory range %d with %d bytes at %06X-%06X to %06X-%06X, align %d", + /* %s */ in_df ? ">" : "", + /* %d */ mem_range, + /* %d */ *((uint16_t *) &card->rom[i + 8]), + /* %06X */ *((uint16_t *) &card->rom[i + 4]) << 8, + /* %06X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + (*((uint16_t *) &card->rom[i + 10]) << 8) : + /* Range. */ + (*((uint16_t *) &card->rom[i + 4]) << 8)) + + (*((uint16_t *) &card->rom[i + 10]) << 8), + /* %06X */ *((uint16_t *) &card->rom[i + 6]) << 8, + /* %06X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + (*((uint16_t *) &card->rom[i + 10]) << 8) : + /* Range. */ + (*((uint16_t *) &card->rom[i + 6]) << 8)) + + (*((uint16_t *) &card->rom[i + 10]) << 8), + /* %d */ *((uint16_t *) &card->rom[i + 8])); res = 1 << mem_range; mem_range++; } else { @@ -806,9 +823,25 @@ isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size) break; } - isapnp_log("ISAPnP: >>%s 32-bit memory range %d with %d bytes at %08X-%08X, align %d", in_df ? ">" : "", mem_range_32, - *((uint32_t *) &card->rom[i + 16]) << 8, *((uint32_t *) &card->rom[i + 4]) << 8, ((card->rom[i + 3] & 0x4) ? 0 : (*((uint32_t *) &card->rom[i + 4]) << 8)) + (*((uint32_t *) &card->rom[i + 8]) << 8), - *((uint32_t *) &card->rom[i + 12])); + isapnp_log("ISAPnP: >>%s 32-bit memory range %d with %d bytes at %08X-%08X, align %d", + /* %s */ in_df ? ">" : "", + /* %d */ mem_range_32, + /* %d */ *((uint32_t *) &card->rom[i + 12]), + /* %08X */ *((uint32_t *) &card->rom[i + 4]), + /* %08X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + *((uint32_t *) &card->rom[i + 16]) : + /* Range. */ + *((uint32_t *) &card->rom[i + 4])) + + *((uint32_t *) &card->rom[i + 16]), + /* %08X */ *((uint32_t *) &card->rom[i + 8]), + /* %08X */ ((card->rom[i + 3] & 0x4) ? + /* High address. */ + *((uint32_t *) &card->rom[i + 16]) : + /* Range. */ + *((uint32_t *) &card->rom[i + 8])) + + *((uint32_t *) &card->rom[i + 16]), + /* %d */ *((uint32_t *) &card->rom[i + 12])); res = 1 << (4 + mem_range_32); mem_range_32++; } diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c index c2b0538145..608d7a8a7e 100644 --- a/src/disk/hdc_ide_w83769f.c +++ b/src/disk/hdc_ide_w83769f.c @@ -458,3 +458,17 @@ const device_t ide_w83769f_pci_34_device = { .config = NULL }; +const device_t ide_w83769f_pci_single_channel_device = { + .name = "Winbond W83769F PCI (Single Channel)", + .internal_name = "ide_w83769f_pci_single_channel", + .flags = DEVICE_PCI, + .local = 0x200b4, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 65b731340e..b861b5e50f 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -419,19 +419,26 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-1] Conner CP3024", .internal_name = "CP3024", .model = "Conner Peripherals 20MB - CP3024", .zones = 1, .avg_spt = 33, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3044", .internal_name = "CP3044", .model = "Conner Peripherals 40MB - CP3044", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work { .name = "[ATA-1] Conner CP3104", .internal_name = "CP3104", .model = "Conner Peripherals 104MB - CP3104", .zones = 1, .avg_spt = 33, .heads = 8, .rpm = 3500, .full_stroke_ms = 45, .track_seek_ms = 8, .rcache_num_seg = 4, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work + { .name = "[ATA-1] HP Kittyhawk", .internal_name = "C3014A", .model = "HP C3014A", .zones = 6, .avg_spt = 180, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, { .name = "[ATA-1] IBM H3256-A3", .internal_name = "H3256A3", .model = "IBM-H3256-A3", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, { .name = "[ATA-1] IBM H3342-A4", .internal_name = "H3342A4", .model = "IBM-H3342-A4", .zones = 1, .avg_spt = 140, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 8 }, + { .name = "[ATA-1] Kalok KL343", .internal_name = "KL343", .model = "KALOK KL-343", .zones = 1, .avg_spt = 280, .heads = 6, .rpm = 3600, .full_stroke_ms = 50, .track_seek_ms = 2, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, + { .name = "[ATA-1] Kalok KL3100", .internal_name = "KL3100", .model = "KALOK KL-3100", .zones = 1, .avg_spt = 200, .heads = 6, .rpm = 3662, .full_stroke_ms = 50, .track_seek_ms = 2, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 8 }, { .name = "[ATA-1] Maxtor 7060AT", .internal_name = "7060AT", .model = "Maxtor 7060AT", .zones = 1, .avg_spt = 162, .heads = 2, .rpm = 3524, .full_stroke_ms = 30, .track_seek_ms = 3.6, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Maxtor 7131AT", .internal_name = "7131AT", .model = "Maxtor 7131AT", .zones = 2, .avg_spt = 154, .heads = 2, .rpm = 3551, .full_stroke_ms = 27, .track_seek_ms = 4.5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Maxtor 7213AT", .internal_name = "7213AT", .model = "Maxtor 7213AT", .zones = 4, .avg_spt = 155, .heads = 4, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6.5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Maxtor 7245AT", .internal_name = "7245AT", .model = "Maxtor 7245AT", .zones = 4, .avg_spt = 149, .heads = 4, .rpm = 3551, .full_stroke_ms = 27, .track_seek_ms = 4.4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Quantum ProDrive LPS 105", .internal_name = "LPS105AT", .model = "QUANTUM PRODRIVE 105", .zones = 1, .avg_spt = 170, .heads = 2, .rpm = 3662, .full_stroke_ms = 45, .track_seek_ms = 5, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, { .name = "[ATA-1] Quantum ProDrive LPS 120AT", .internal_name = "GM12A012", .model = "QUANTUM PRODRIVE 120AT", .zones = 1, .avg_spt = 150, .heads = 2, .rpm = 3605, .full_stroke_ms = 45, .track_seek_ms = 4, .rcache_num_seg = 1, .rcache_seg_size = 64, .max_multiple = 8 }, + { .name = "[ATA-1] Seagate ST3243A", .internal_name = "ST3243A", .model = "ST3243A", .zones = 1, .avg_spt = 140, .heads = 4, .rpm = 3811, .full_stroke_ms = 32, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, { .name = "[ATA-1] Western Digital Caviar 140", .internal_name = "WDAC140", .model = "WDC WDAC140-50", .zones = 4, .avg_spt = 170, .heads = 2, .rpm = 3551, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 8, .max_multiple = 8 }, { .name = "[ATA-1] Western Digital Caviar 280", .internal_name = "WDAC280", .model = "WDC WDAC280-00", .zones = 4, .avg_spt = 170, .heads = 4, .rpm = 3595, .full_stroke_ms = 28, .track_seek_ms = 6, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, + { .name = "[ATA-1] Western Digital Caviar 1210", .internal_name = "WDAC1210", .model = "WDC WDAC1210-21F", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 3314, .full_stroke_ms = 33, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-1] Western Digital Caviar 2120", .internal_name = "WDAC2120", .model = "WDC WDAC2120-00M", .zones = 4, .avg_spt = 140, .heads = 2, .rpm = 3605, .full_stroke_ms = 28, .track_seek_ms = 2.8, .rcache_num_seg = 8, .rcache_seg_size = 32, .max_multiple = 8 }, { .name = "[ATA-2] IBM DBOA-2720", .internal_name = "DBOA2720", .model = "IBM-DBOA-2720", .zones = 2, .avg_spt = 135, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, - { .name = "[ATA-2] IBM DeskStar 4", .internal_name = "DCAA34330", .model = "IBM-DCAA-34330", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, + { .name = "[ATA-2] IBM DeskStar 4 (DCAA-32880)", .internal_name = "DCAA32880", .model = "IBM-DCAA-32880", .zones = 8, .avg_spt = 85, .heads = 2, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, + { .name = "[ATA-2] IBM DeskStar 4 (DCAA-33610)", .internal_name = "DCAA33610", .model = "IBM-DCAA-33610", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, + { .name = "[ATA-2] IBM DeskStar 4 (DCAA-34330)", .internal_name = "DCAA34330", .model = "IBM-DCAA-34330", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.7, .rcache_num_seg = 4, .rcache_seg_size = 96, .max_multiple = 16 }, { .name = "[ATA-2] Maxtor 7540AV", .internal_name = "7540AV", .model = "Maxtor 7540AV", .zones = 2, .avg_spt = 120, .heads = 4, .rpm = 3551, .full_stroke_ms = 31, .track_seek_ms = 4.3, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 8 }, { .name = "[ATA-2] Maxtor 7546AT", .internal_name = "7546AT", .model = "Maxtor 7546AT", .zones = 2, .avg_spt = 100, .heads = 4, .rpm = 4500, .full_stroke_ms = 28, .track_seek_ms = 2.3, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 }, { .name = "[ATA-2] Maxtor 7850AV", .internal_name = "7850AV", .model = "Maxtor 7850AV", .zones = 4, .avg_spt = 120, .heads = 4, .rpm = 3551, .full_stroke_ms = 31, .track_seek_ms = 3.7, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 8 }, @@ -450,34 +457,67 @@ static hdd_preset_t hdd_speed_presets[] = { { .name = "[ATA-2] Seagate Medalist (ST31220A)", .internal_name = "ST31220A", .model = "ST31220A", .zones = 8, .avg_spt = 140, .heads = 6, .rpm = 4500, .full_stroke_ms = 27, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 16 }, { .name = "[ATA-2] Seagate Medalist 210xe", .internal_name = "ST3250A", .model = "ST3250A", .zones = 4, .avg_spt = 148, .heads = 2, .rpm = 3811, .full_stroke_ms = 30, .track_seek_ms = 4.1, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, { .name = "[ATA-2] Seagate Medalist 275xe", .internal_name = "ST3295A", .model = "ST3295A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 3811, .full_stroke_ms = 30, .track_seek_ms = 3.4, .rcache_num_seg = 3, .rcache_seg_size = 120, .max_multiple = 8 }, + { .name = "[ATA-2] Seagate Medalist 545xe", .internal_name = "ST3660A", .model = "ST3660A", .zones = 4, .avg_spt = 130, .heads = 4, .rpm = 3811, .full_stroke_ms = 34, .track_seek_ms = 3.4, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, + { .name = "[ATA-2] Seagate Medalist 640xe", .internal_name = "ST3630A", .model = "ST3630A", .zones = 4, .avg_spt = 130, .heads = 4, .rpm = 3811, .full_stroke_ms = 34, .track_seek_ms = 3.5, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, + { .name = "[ATA-2] Seagate Medalist 850xe", .internal_name = "ST3850A", .model = "ST3850A", .zones = 8, .avg_spt = 150, .heads = 4, .rpm = 3811, .full_stroke_ms = 34, .track_seek_ms = 3.8, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 8 }, { .name = "[ATA-2] Seagate Medalist 1270SL", .internal_name = "ST51270A", .model = "ST51270A", .zones = 8, .avg_spt = 105, .heads = 3, .rpm = 5736, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Seagate Medalist 3240", .internal_name = "ST33240A", .model = "ST33240A", .zones = 16, .avg_spt = 125, .heads = 8, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, - { .name = "[ATA-2] Western Digital Caviar 2850", .internal_name = "WDAC2850", .model = "WDC WDAC2850-00F", .zones = 4, .avg_spt = 115, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Toshiba MK2101MAN (HDD2616)", .internal_name = "HDD2616", .model = "TOSHIBA MK2101MAN", .zones = 8, .avg_spt = 130, .heads = 10, .rpm = 4200, .full_stroke_ms = 36, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-2] Western Digital Caviar 2540", .internal_name = "WDAC2540", .model = "WDC WDAC2540-00H", .zones = 4, .avg_spt = 250, .heads = 2, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 2850", .internal_name = "WDAC2850", .model = "WDC WDAC2850-00F", .zones = 4, .avg_spt = 230, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, { .name = "[ATA-2] Western Digital Caviar 11000", .internal_name = "WDAC11000", .model = "WDC WDAC11000-00H", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 5200, .full_stroke_ms = 12, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 21200", .internal_name = "WDAC21200", .model = "WDC WDAC21200-00H", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 5200, .full_stroke_ms = 39, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 21600", .internal_name = "WDAC21600", .model = "WDC WDAC21600-00H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000-32LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 }, + { .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "WDAC22100", .model = "WDC WDAC22100-18H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "WDAC31200", .model = "WDC WDAC31200-00F", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3043AT", .internal_name = "MPA3043AT", .model = "FUJITSU MPA3043AT", .zones = 15, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-3] Fujitsu MPA3052AT", .internal_name = "MPA3052AT", .model = "FUJITSU MPA3052AT", .zones = 16, .avg_spt = 95, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Samsung Voyager 6", .internal_name = "SV0844A", .model = "SAMSUNG SV0844A", .zones = 8, .avg_spt = 105, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-3] Samsung Winner 5X", .internal_name = "WU33205A", .model = "SAMSUNG WU33205A", .zones = 16, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Seagate Medalist 1720", .internal_name = "ST31720A", .model = "ST31720A", .zones = 4, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 2, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-3] Seagate Medalist 2132", .internal_name = "ST32132A", .model = "ST32132A", .zones = 8, .avg_spt = 125, .heads = 6, .rpm = 4500, .full_stroke_ms = 30, .track_seek_ms = 2.3, .rcache_num_seg = 8, .rcache_seg_size = 120, .max_multiple = 16 }, + { .name = "[ATA-3] Western Digital Caviar 21700", .internal_name = "WDAC21700", .model = "WDC WDAC21700-40H", .zones = 8, .avg_spt = 85, .heads = 3, .rpm = 5200, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 }, // Apple Computer OEM only, not retail version { .name = "[ATA-4] Fujitsu MPB3021AT", .internal_name = "MPB3021AT", .model = "FUJITSU MPB3021AT", .zones = 7, .avg_spt = 100, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 16 }, { .name = "[ATA-4] Fujitsu MPD3043AT", .internal_name = "MPD3043AT", .model = "FUJITSU MPD3043AT", .zones = 5, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 29, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-4] Fujitsu MPD3064AT", .internal_name = "MPD3064AT", .model = "FUJITSU MPD3064AT", .zones = 7, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Fujitsu MPD3084AT", .internal_name = "MPD3084AT", .model = "FUJITSU MPD3084AT", .zones = 7, .avg_spt = 95, .heads = 4, .rpm = 5400, .full_stroke_ms = 19, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 16 }, + { .name = "[ATA-4] Fujitsu MPE3064AT", .internal_name = "MPE3064AT", .model = "FUJITSU MPE3064AT", .zones = 7, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 30, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-4] Maxtor DiamondMax 2160", .internal_name = "86480D6", .model = "Maxtor 86480D6", .zones = 8, .avg_spt = 97, .heads = 4, .rpm = 5200, .full_stroke_ms = 18, .track_seek_ms = 1, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-4] Maxtor DiamondMax 2880", .internal_name = "90432D3", .model = "Maxtor 90432D3", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 3400", .internal_name = "90644D3", .model = "Maxtor 90644D3", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 4320 (90432D2)", .internal_name = "90432D2", .model = "Maxtor 90432D2", .zones = 16, .avg_spt = 90, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax 4320 (90845D4)", .internal_name = "90845D4", .model = "Maxtor 90845D4", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (90683U2)", .internal_name = "90683U2", .model = "Maxtor 90683U2", .zones = 16, .avg_spt = 90, .heads = 2, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (91024U3)", .internal_name = "91024U3", .model = "Maxtor 91024U3", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (91366U4)", .internal_name = "91366U4", .model = "Maxtor 91366U4", .zones = 16, .avg_spt = 90, .heads = 4, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92049U6)", .internal_name = "92049U6", .model = "Maxtor 92049U6", .zones = 16, .avg_spt = 90, .heads = 6, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-4] Maxtor DiamondMax Plus 6800 (92732U8)", .internal_name = "92732U8", .model = "Maxtor 92732U8", .zones = 16, .avg_spt = 90, .heads = 8, .rpm = 7200, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-4] Quantum Bigfoot TX4.3AT", .internal_name = "TX043A011", .model = "QUANTUM BIGFOOT TX4.3A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4000, .full_stroke_ms = 30, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, + { .name = "[ATA-4] Seagate Medalist 2122", .internal_name = "ST32122A", .model = "ST32122A", .zones = 16, .avg_spt = 115, .heads = 2, .rpm = 4500, .full_stroke_ms = 23, .track_seek_ms = 3.8, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 3321", .internal_name = "ST33221A", .model = "ST33221A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 4321", .internal_name = "ST34321A", .model = "ST34321A", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, { .name = "[ATA-4] Seagate Medalist 6531", .internal_name = "ST36531A", .model = "ST36531A", .zones = 16, .avg_spt = 115, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1.7, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 16 }, + { .name = "[ATA-4] Seagate Medalist 8420", .internal_name = "ST38420A", .model = "ST38420A", .zones = 16, .avg_spt = 90, .heads = 2, .rpm = 5400, .full_stroke_ms = 16, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-4] Toshiba MK4006MAV", .internal_name = "MK4006MAV", .model = "TOSHIBA MK4006MAV", .zones = 8, .avg_spt = 130, .heads = 6, .rpm = 4200, .full_stroke_ms = 25, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-4] Western Digital Caviar 14300", .internal_name = "AC14300", .model = "WDC AC14300-00RT", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 5.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 }, { .name = "[ATA-4] Western Digital Caviar 23200", .internal_name = "AC23200", .model = "WDC AC23200-00LB", .zones = 16, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 256, .max_multiple = 32 }, { .name = "[ATA-4] Western Digital Caviar 26400", .internal_name = "AC26400", .model = "WDC AC26400-00RN", .zones = 16, .avg_spt = 95, .heads = 5, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 32 }, { .name = "[ATA-4] Western Digital Caviar 33200", .internal_name = "AC33200", .model = "WDC AC33200-00LA", .zones = 16, .avg_spt = 110, .heads = 5, .rpm = 5200, .full_stroke_ms = 40, .track_seek_ms = 3, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, - { .name = "[ATA-5] Samsung SpinPoint V6800", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Seagate Medalist 4312", .internal_name = "ST34312A", .model = "ST34312A", .zones = 16, .avg_spt = 86, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, - { .name = "[ATA-5] Western Digital Caviar 102AA", .internal_name = "WD102AA", .model = "WDC WD102AA-00ANA0", .zones = 16, .avg_spt = 95, .heads = 8, .rpm = 5400, .full_stroke_ms = 12, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Hard disk entry removed from The Retro Web + { .name = "[ATA-5] IBM Travelstar 6GN", .internal_name = "DARA206000", .model = "IBM-DARA-206000", .zones = 12, .avg_spt = 92, .heads = 2, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] IBM Travelstar 9GN", .internal_name = "DARA209000", .model = "IBM-DARA-209000", .zones = 12, .avg_spt = 92, .heads = 3, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] IBM/Hitachi Travelstar 12GN", .internal_name = "DARA212000", .model = "IBM-DARA-212000", .zones = 12, .avg_spt = 92, .heads = 4, .rpm = 4200, .full_stroke_ms = 31, .track_seek_ms = 4, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, // Either Hitachi or IBM OEM + { .name = "[ATA-5] Maxtor DiamondMax VL 17", .internal_name = "90871U2", .model = "Maxtor 90871U2", .zones = 16, .avg_spt = 90, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 0.9, .rcache_num_seg = 16, .rcache_seg_size = 256, .max_multiple = 32 }, + { .name = "[ATA-5] Maxtor DiamondMax VL 20", .internal_name = "91021U2", .model = "Maxtor 91021U2", .zones = 16, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 1, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV0682D)", .internal_name = "SV0682D", .model = "SAMSUNG SV0682D", .zones = 8, .avg_spt = 95, .heads = 2, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Samsung SpinPoint V6800 (SV1023D)", .internal_name = "SV1023D", .model = "SAMSUNG SV1023D", .zones = 8, .avg_spt = 95, .heads = 3, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 1.3, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 4.3gb", .internal_name = "ST34313A", .model = "ST34313A", .zones = 16, .avg_spt = 89, .heads = 1, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Seagate U8 - 8.4gb", .internal_name = "ST38410A", .model = "ST38410A", .zones = 16, .avg_spt = 89, .heads = 2, .rpm = 5400, .full_stroke_ms = 25, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Western Digital Caviar 102AA", .internal_name = "WD102AA", .model = "WDC WD102AA-00ANA0", .zones = 16, .avg_spt = 95, .heads = 8, .rpm = 5400, .full_stroke_ms = 12, .track_seek_ms = 1.5, .rcache_num_seg = 16, .rcache_seg_size = 512, .max_multiple = 32 }, + { .name = "[ATA-5] Western Digital Expert", .internal_name = "WD135BA", .model = "WDC WD135BA-60AK", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 1920, .max_multiple = 32 }, // clang-format on }; diff --git a/src/dma.c b/src/dma.c index 86c29fe262..4edeb39f80 100644 --- a/src/dma.c +++ b/src/dma.c @@ -665,6 +665,19 @@ dma_ps2_read(uint16_t addr, UNUSED(void *priv)) temp = dma_c->arb_level; break; + case 9: /*Set DMA mask*/ + dma_m |= (1 << dma_ps2.xfr_channel); + break; + + case 0xa: /*Reset DMA mask*/ + dma_m &= ~(1 << dma_ps2.xfr_channel); + break; + + case 0xb: + if (!(dma_m & (1 << dma_ps2.xfr_channel))) + dma_ps2_run(dma_ps2.xfr_channel); + break; + default: fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel); } @@ -767,6 +780,19 @@ dma_ps2_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) dma_c->arb_level = val; break; + case 9: /*Set DMA mask*/ + dma_m |= (1 << dma_ps2.xfr_channel); + break; + + case 0xa: /*Reset DMA mask*/ + dma_m &= ~(1 << dma_ps2.xfr_channel); + break; + + case 0xb: + if (!(dma_m & (1 << dma_ps2.xfr_channel))) + dma_ps2_run(dma_ps2.xfr_channel); + break; + default: fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val); } diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 3a0b03a9b7..a381f67f12 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -294,7 +294,7 @@ fdd_type_invert_densel(int type) int ret; if (drive_types[type].flags & FLAG_PS2) - ret = !!strstr(machine_getname(), "PS/"); + ret = (!!strstr(machine_getname(), "PS/1")) || (!!strstr(machine_getname(), "PS/2")); else ret = drive_types[type].flags & FLAG_INVERT_DENSEL; diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 26a6061d8c..5b1ae63122 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -166,7 +166,7 @@ extern _Atomic double mouse_y_error; /* Mouse error accumulator - Y */ #endif extern int pit_mode; /* (C) force setting PIT mode */ extern int fm_driver; /* (C) select FM sound driver */ -extern int raw_input; /* (C) Use raw input */ +extern int hook_enabled; /* (C) Keyboard hook is enabled */ /* Keyboard variables for future key combination redefinition. */ extern uint16_t key_prefix_1_1; diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 8fb0bc742e..efb45ecfb0 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -218,7 +218,6 @@ typedef struct raw_track_info_t { /* Define the various CD-ROM drive operations (ops). */ typedef struct cdrom_ops_t { - void (*get_tracks)(struct cdrom *dev, int *first, int *last); void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti); void (*get_raw_track_info)(struct cdrom *dev, int *num, raw_track_info_t *rti); void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc); diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h index 2e3aa85b9f..64ce88d83c 100644 --- a/src/include/86box/cdrom_image_backend.h +++ b/src/include/86box/cdrom_image_backend.h @@ -6,16 +6,15 @@ * * This file is part of the 86Box distribution. * - * CD-ROM image file handling module header , translated to C - * from cdrom_dosbox.h. + * CD-ROM image file handling module header. * * Authors: Miran Grca, - * Fred N. van Kempen, - * The DOSBox Team, + * RichardG, + * Cacodemon345 * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2002-2020 The DOSBox Team. + * Copyright 2016-2025 Miran Grca. + * Copyright 2016-2025 Miran Grca. + * Copyright 2024-2025 Cacodemon345. */ #ifndef CDROM_IMAGE_BACKEND_H #define CDROM_IMAGE_BACKEND_H @@ -57,72 +56,59 @@ typedef struct track_file_t { int motorola; } track_file_t; -#define BLOCK_EMPTY 0 /* Empty block. */ -#define BLOCK_ZERO 1 /* Block not in the file, return all 0x00's. */ -#define BLOCK_NORMAL 2 /* Block in the file. */ - -#define BLOCK_NONE ((uint64_t) -1LL) +#define INDEX_SPECIAL -2 /* Track A0h onwards. */ +#define INDEX_NONE -1 /* Empty block. */ +#define INDEX_ZERO 0 /* Block not in the file, return all 0x00's. */ +#define INDEX_NORMAL 1 /* Block in the file. */ typedef struct track_index_t { - /* Is the current block in the file? If not, return all 0x00's. */ - int in_file; + /* Is the current block in the file? If not, return all 0x00's. -1 means not yet loaded. */ + int32_t type; /* The amount of bytes to skip at the beginning of each sector. */ - int skip; + int32_t skip; /* Starting and ending sector LBA - negative in order to accomodate LBA -150 to -1 to read the pregap of track 1. */ uint64_t start; uint64_t length; + uint64_t file_start; + uint64_t file_length; + track_file_t *file; } track_index_t; typedef struct track_t { - int pregap_len; /* Pre-gap - not in file. */ - int index0_len; /* Pre-gap - in file. */ - int postgap_len; /* Post-gap - not in file. */ - int blocks_num; /* Number of blocks. */ - int number; - int track_number; - int attr; - int sector_size; - int mode2; - int form; - int pre; - int noskip; /* Do not skip by 8 bytes.*/ - uint64_t start; - uint64_t length; - uint64_t skip; - track_index_t indexes[3]; - track_file_t *file; + uint8_t session; + uint8_t attr; + uint8_t tno; + uint8_t point; + uint8_t extra[4]; + uint8_t mode; + uint8_t form; + uint8_t pad; + uint8_t skip; + uint32_t sector_size; + track_index_t idx[3]; } track_t; typedef struct cd_img_t { - int tracks_num; - track_t *tracks; + int32_t tracks_num; + track_t *tracks; } cd_img_t; /* Binary file functions. */ -extern void cdi_close(cd_img_t *cdi); -extern int cdi_set_device(cd_img_t *cdi, const char *path); -extern void cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); -extern void cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out); -extern int cdi_get_audio_track_pre(cd_img_t *cdi, int track); -extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, - TMSF *start, uint8_t *attr); -extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, - uint32_t *start, uint8_t *attr); extern void cdi_get_raw_track_info(cd_img_t *cdi, int *num, uint8_t *buffer); -extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos); extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector); -extern int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num); extern int cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector); extern int cdi_get_sector_size(cd_img_t *cdi, uint32_t sector); +extern int cdi_is_audio(cd_img_t *cdi, uint32_t sector); +extern int cdi_is_pre(cd_img_t *cdi, uint32_t sector); extern int cdi_is_mode2(cd_img_t *cdi, uint32_t sector); extern int cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector); extern int cdi_load_iso(cd_img_t *cdi, const char *filename); extern int cdi_load_cue(cd_img_t *cdi, const char *cuefile); -extern int cdi_has_data_track(cd_img_t *cdi); -extern int cdi_has_audio_track(cd_img_t *cdi); +extern void cdi_close(cd_img_t *cdi); +extern int cdi_set_device(cd_img_t *cdi, const char *path); /* Virtual ISO functions. */ extern int viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count); diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 67a30b1c86..1c2ec52034 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -18,7 +18,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2008-2019 Sarah Walker. * Copyright 2021 Andreas J. Reichel. - * Copyright 2021-2022 Jasmine Iwanek. + * Copyright 2021-2025 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -197,12 +197,12 @@ extern "C" { #endif extern void device_init(void); -extern void device_set_context(device_context_t *c, const device_t *dev, int inst); +extern void device_set_context(device_context_t *ctx, const device_t *dev, int inst); extern void device_context(const device_t *dev); extern void device_context_inst(const device_t *dev, int inst); extern void device_context_restore(void); -extern void *device_add(const device_t *d); -extern void *device_add_linked(const device_t *d, void *priv); +extern void *device_add(const device_t *dev); +extern void *device_add_linked(const device_t *dev, void *priv); extern void *device_add_params(const device_t *dev, void *params); extern void device_add_ex(const device_t *dev, void *priv); extern void device_add_ex_params(const device_t *dev, void *priv, void *params); @@ -223,27 +223,27 @@ extern void device_get_name(const device_t *dev, int bus, char *name); extern int device_has_config(const device_t *dev); extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no); -extern int device_is_valid(const device_t *, int m); +extern int device_is_valid(const device_t *, int mch); extern const device_t* device_context_get_device(void); extern int device_get_config_int(const char *name); -extern int device_get_config_int_ex(const char *s, int dflt_int); +extern int device_get_config_int_ex(const char *str, int def); extern int device_get_config_hex16(const char *name); extern int device_get_config_hex20(const char *name); -extern int device_get_config_mac(const char *name, int dflt_int); -extern void device_set_config_int(const char *s, int val); -extern void device_set_config_hex16(const char *s, int val); -extern void device_set_config_hex20(const char *s, int val); -extern void device_set_config_mac(const char *s, int val); +extern int device_get_config_mac(const char *name, int def); +extern void device_set_config_int(const char *str, int val); +extern void device_set_config_hex16(const char *str, int val); +extern void device_set_config_hex20(const char *str, int val); +extern void device_set_config_mac(const char *str, int val); extern const char *device_get_config_string(const char *name); extern int device_get_instance(void); #define device_get_config_bios device_get_config_string extern const char *device_get_internal_name(const device_t *dev); -extern int machine_get_config_int(char *s); -extern char *machine_get_config_string(char *s); +extern int machine_get_config_int(char *str); +extern char *machine_get_config_string(char *str); extern const device_t device_none; extern const device_t device_internal; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 48235bb1e5..a3b667e2eb 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -89,6 +89,7 @@ extern const device_t ide_w83769f_vlb_device; /* Winbond W8376 extern const device_t ide_w83769f_vlb_34_device; /* Winbond W83769F VLB (Port 34h) */ extern const device_t ide_w83769f_pci_device; /* Winbond W83769F PCI */ extern const device_t ide_w83769f_pci_34_device; /* Winbond W83769F PCI (Port 34h) */ +extern const device_t ide_w83769f_pci_single_channel_device; /* Winbond W83769F PCI (Only primary channel) */ extern const device_t ide_ter_device; extern const device_t ide_ter_pnp_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d46e816ce7..ad8b476385 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -450,6 +450,7 @@ extern int machine_at_mr286_init(const machine_t *); extern int machine_at_neat_init(const machine_t *); extern int machine_at_neat_ami_init(const machine_t *); +extern int machine_at_ataripc4_init(const machine_t *); extern int machine_at_quadt386sx_init(const machine_t *); @@ -593,6 +594,7 @@ extern int machine_at_pcm5330_init(const machine_t *); extern int machine_at_ecs486_init(const machine_t *); extern int machine_at_hot433a_init(const machine_t *); +extern int machine_at_pl4600c_init(const machine_t *); extern int machine_at_atc1415_init(const machine_t *); extern int machine_at_actionpc2600_init(const machine_t *); extern int machine_at_actiontower8400_init(const machine_t *); @@ -631,6 +633,7 @@ extern int machine_at_valuepointp60_init(const machine_t *); extern int machine_at_revenge_init(const machine_t *); extern int machine_at_586is_init(const machine_t *); extern int machine_at_pb520r_init(const machine_t *); +extern int machine_at_m5pi_init(const machine_t *); extern int machine_at_excalibur_init(const machine_t *); @@ -643,6 +646,7 @@ extern int machine_at_p5sp4_init(const machine_t *); extern int machine_at_plato_init(const machine_t *); extern int machine_at_dellplato_init(const machine_t *); extern int machine_at_ambradp90_init(const machine_t *); +extern int machine_at_p54np4_init(const machine_t *); extern int machine_at_586ip_init(const machine_t *); extern int machine_at_tek932_init(const machine_t *); @@ -913,6 +917,7 @@ extern int machine_xt86_init(const machine_t *); extern int machine_xt_americxt_init(const machine_t *); extern int machine_xt_amixt_init(const machine_t *); +extern int machine_xt_ataripc3_init(const machine_t *); extern int machine_xt_dtk_init(const machine_t *); extern int machine_xt_jukopc_init(const machine_t *); extern int machine_xt_openxt_init(const machine_t *); diff --git a/src/include/86box/plat_cdrom.h b/src/include/86box/plat_cdrom.h index 1e70e014b8..643013a087 100644 --- a/src/include/86box/plat_cdrom.h +++ b/src/include/86box/plat_cdrom.h @@ -53,7 +53,6 @@ extern void plat_cdrom_get_raw_track_info(void *local, int *num, raw_track_i extern int plat_cdrom_is_track_audio(void *local, uint32_t sector); extern int plat_cdrom_is_track_pre(void *local, uint32_t sector); extern uint32_t plat_cdrom_get_last_block(void *local); -extern void plat_cdrom_get_audio_tracks(void *local, int *st_track, int *end, TMSF *lead_out); extern int plat_cdrom_get_audio_track_info(void *local, int end, int track, int *track_num, TMSF *start, uint8_t *attr); extern int plat_cdrom_get_audio_sub(void *local, uint32_t sector, uint8_t *attr, uint8_t *track, diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index e0c97becce..3697352481 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -129,6 +129,7 @@ #define GPCMD_CADDY_EJECT_TOSHIBA 0xc4 /* Toshiba Vendor Unique command */ #define GPCMD_PAUSE_SONY 0xc5 /* Sony Vendor Unique command */ #define GPCMD_PLAY_AUDIO_MATSUSHITA 0xc5 /* Matsushita Vendor Unique command */ +#define GPCMD_UNKNOWN_SCSI2_NEC 0xc5 /* NEC Vendor Unique Command */ #define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */ #define GPCMD_PLAY_TRACK_SONY 0xc6 /* Sony Vendor Unique command */ #define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA 0xc6 /* Toshiba Vendor Unique command */ diff --git a/src/include/86box/snd_akm4531.h b/src/include/86box/snd_akm4531.h new file mode 100644 index 0000000000..96f87b396c --- /dev/null +++ b/src/include/86box/snd_akm4531.h @@ -0,0 +1,22 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Ensoniq AudioPCI family emulation. + * + * Authors: Cacodemon345 + * + * Copyright 2024-2025 Cacodemon345. + */ +struct akm4531_t +{ + unsigned char registers[256]; +}; + +typedef struct akm4531_t akm4531_t; + +double akm4531_apply_master_vol(unsigned short sample); \ No newline at end of file diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 33467cf252..06fbbfa3bc 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -11,9 +11,11 @@ * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, + * Jasmine Iwanek, * * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. + * Copyright 2024-2025 Jasmine Iwanek. */ #ifndef SOUND_SND_SB_H @@ -27,15 +29,19 @@ enum { SADLIB = 1, /* No DSP */ - SB1, /* DSP v1.05 */ - SB15, /* DSP v2.00 */ - SB2, /* DSP v2.01 - needed for high-speed DMA */ - SBPRO, /* DSP v3.00 */ - SBPRO2, /* DSP v3.02 + OPL3 */ - SB16, /* DSP v4.05 + OPL3 */ - SBAWE32, /* DSP v4.12 + OPL3 */ - SBAWE32PNP, /* DSP v4.13 + OPL3 */ - SBAWE64 /* DSP v4.16 + OPL3 */ + SB_DSP_105, /* DSP v1.05, Original CT1320 (Also known as CT1310) */ + SB_DSP_200, /* DSP v2.00 */ + SB_DSP_201, /* DSP v2.01 - needed for high-speed DMA, Seen on CT1350B with CT1336 */ + SB_DSP_202, /* DSP v2.02 - Seen on CT1350B with CT1336A */ + SBPRO_DSP_300, /* DSP v3.00 */ + SBPRO2_DSP_302, /* DSP v3.02 + OPL3 */ + SB16_DSP_404, /* DSP v4.05 + OPL3 */ + SB16_DSP_405, /* DSP v4.05 + OPL3 */ + SB16_DSP_406, /* DSP v4.06 + OPL3 */ + SB16_DSP_411, /* DSP v4.11 + OPL3 */ + SBAWE32_DSP_412, /* DSP v4.12 + OPL3 */ + SBAWE32_DSP_413, /* DSP v4.13 + OPL3 */ + SBAWE64_DSP_416 /* DSP v4.16 + OPL3 */ }; /* SB 2.0 CD version */ @@ -196,6 +202,12 @@ typedef struct sb_t { void (*opl_mix)(void*, double*, double*); } sb_t; +typedef struct goldfinch_t { + emu8k_t emu8k; + + uint8_t pnp_rom[512]; +} goldfinch_t; + extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *priv); extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *priv); extern void sb_ct1345_mixer_reset(sb_t *sb); diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 98d085dc5e..373514d4c0 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -158,6 +158,7 @@ extern const device_t sb_16_pnp_ide_device; extern const device_t sb_16_compat_device; extern const device_t sb_16_compat_nompu_device; extern const device_t sb_16_reply_mca_device; +extern const device_t sb_goldfinch_device; extern const device_t sb_32_pnp_device; extern const device_t sb_awe32_device; extern const device_t sb_awe32_pnp_device; @@ -184,6 +185,7 @@ extern const device_t ess_soundpiper_32_mca_device; extern const device_t ess_chipchat_16_mca_device; /* Ensoniq AudioPCI */ +extern const device_t es1370_device; extern const device_t es1371_device; extern const device_t es1371_onboard_device; extern const device_t es1373_device; diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 0e6e0965ad..57e98cc446 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -138,6 +138,7 @@ typedef struct ibm8514_t { int output2; int ssv_len; + int ssv_len_back; uint8_t ssv_dir; uint8_t ssv_draw; int odd_in; diff --git a/src/include/86box/vid_voodoo_codegen_x86-64.h b/src/include/86box/vid_voodoo_codegen_x86-64.h index dc0ebce723..e8b7299f24 100644 --- a/src/include/86box/vid_voodoo_codegen_x86-64.h +++ b/src/include/86box/vid_voodoo_codegen_x86-64.h @@ -2157,6 +2157,12 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0xc2); } + addbyte(0xf3); /*MOVQ XMM15(colbfog), XMM0 */ + addbyte(0x44); + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xf8); + if (params->fogMode & FOG_ENABLE) { if (params->fogMode & FOG_CONSTANT) { addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ @@ -2580,17 +2586,17 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0xef); addbyte(0xe4); break; - case AFUNC_ASATURATE: - addbyte(0x66); /*PMULLW XMM4, XMM11(minus_254)*/ + case AFUNC_ACOLORBEFOREFOG: + addbyte(0x66); /*PMULLW XMM4, XMM15(colbfog)*/ addbyte(0x41); addbyte(0x0f); addbyte(0xd5); - addbyte(0xe3); + addbyte(0xe7); addbyte(0xf3); /*MOVQ XMM5, XMM4*/ addbyte(0x0f); addbyte(0x7e); addbyte(0xec); - addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x66); /*PADDW XMM4, R10(alookup)[1*8]*/ addbyte(0x41); addbyte(0x0f); addbyte(0xfd); @@ -2610,6 +2616,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0x71); addbyte(0xd4); addbyte(8); + break; } switch (src_afunc) { @@ -2762,7 +2769,36 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, addbyte(0xef); addbyte(0xc0); break; - case AFUNC_ACOLORBEFOREFOG: + case AFUNC_ASATURATE: + addbyte(0x66); /*PMULLW XMM0, XMM11(minus_254)*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x41); + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x42); + addbyte(8 * 2); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); break; } diff --git a/src/include/86box/vid_voodoo_render.h b/src/include/86box/vid_voodoo_render.h index cd1962430a..e88d21dd52 100644 --- a/src/include/86box/vid_voodoo_render.h +++ b/src/include/86box/vid_voodoo_render.h @@ -210,11 +210,10 @@ void voodoo_codegen_close(voodoo_t *voodoo); newdest_g = (dest_g * (255 - dest_a)) / 255; \ newdest_b = (dest_b * (255 - dest_a)) / 255; \ break; \ - case AFUNC_ASATURATE: \ - _a = MIN(src_a, 1 - dest_a); \ - newdest_r = (dest_r * _a) / 255; \ - newdest_g = (dest_g * _a) / 255; \ - newdest_b = (dest_b * _a) / 255; \ + case AFUNC_ACOLORBEFOREFOG: \ + newdest_r = (dest_r * colbfog_r) / 255; \ + newdest_g = (dest_g * colbfog_g) / 255; \ + newdest_b = (dest_b * colbfog_b) / 255; \ break; \ } \ \ @@ -254,8 +253,11 @@ void voodoo_codegen_close(voodoo_t *voodoo); src_g = (src_g * (255 - dest_a)) / 255; \ src_b = (src_b * (255 - dest_a)) / 255; \ break; \ - case AFUNC_ACOLORBEFOREFOG: \ - fatal("AFUNC_ACOLORBEFOREFOG\n"); \ + case AFUNC_ASATURATE: \ + _a = MIN(src_a, 255 - dest_a); \ + src_r = (dest_r * _a) / 255; \ + src_g = (dest_g * _a) / 255; \ + src_b = (dest_b * _a) / 255; \ break; \ } \ \ diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 122c5cdef2..fea87c8f6b 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -13,10 +13,12 @@ * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, + * Jasmine Iwanek, * * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2016-2020 Miran Grca. * Copyright 2008-2020 Sarah Walker. + * Copyright 2025 Jasmine Iwanek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +38,6 @@ * Boston, MA 02111-1307 * USA. */ - #include #include #include @@ -53,6 +54,7 @@ #include <86box/fdc_ext.h> #include <86box/nvr.h> #include <86box/gameport.h> +#include <86box/ibm_5161.h> #include <86box/keyboard.h> #include <86box/lpt.h> #include <86box/rom.h> @@ -149,10 +151,41 @@ machine_at_ps2_ide_init(const machine_t *model) device_add(&ide_isa_device); } +static const device_config_t ibmat_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmat_device = { + .name = " IBM AT Devices", + .internal_name = "ibmat_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmat_config +}; + int machine_at_ibm_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + device_context_restore(); ret = bios_load_interleaved("roms/machines/ibmat/62x0820.u27", "roms/machines/ibmat/62x0821.u47", @@ -163,6 +196,9 @@ machine_at_ibm_init(const machine_t *model) machine_at_ibm_common_init(model); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } @@ -218,10 +254,41 @@ machine_at_ibmatpx_init(const machine_t *model) return ret; } +static const device_config_t ibmxt286_config[] = { + // clang-format off + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmxt286_device = { + .name = "IBM XT Model 286 Devices", + .internal_name = "ibmxt286_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt286_config +}; + int machine_at_ibmxt286_init(const machine_t *model) { - int ret; + int ret; + uint8_t enable_5161; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + device_context_restore(); ret = bios_load_interleaved("roms/machines/ibmxt286/bios_5162_21apr86_u34_78x7460_27256.bin", "roms/machines/ibmxt286/bios_5162_21apr86_u35_78x7461_27256.bin", @@ -232,6 +299,9 @@ machine_at_ibmxt286_init(const machine_t *model) machine_at_ibm_common_init(model); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 36629658f1..ead31c21cf 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -212,6 +212,37 @@ machine_at_neat_ami_init(const machine_t *model) return ret; } +// TODO +// Onboard Paradise PVGA1A-JK VGA Graphics +// Data Technology Corporation DTC7187 RLL Controller (Optional) +int +machine_at_ataripc4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ataripc4/AMI_PC4X_1.7_EVEN.BIN", + "roms/machines/ataripc4/AMI_PC4X_1.7_ODD.BIN", +#if 0 + ret = bios_load_interleaved("roms/machines/ataripc4/ami_pc4x_1.7_even.bin", + "roms/machines/ataripc4/ami_pc4x_1.7_odd.bin", +#endif + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&neat_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&keyboard_at_ami_device); + + return ret; +} + int machine_at_px286_init(const machine_t *model) { diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 253f7522a9..1c35d72906 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -48,6 +48,7 @@ #include <86box/hwm.h> #include <86box/machine.h> #include <86box/plat_unused.h> +#include <86box/sound.h> int machine_at_acc386_init(const machine_t *model) @@ -1962,6 +1963,48 @@ machine_at_hot433a_init(const machine_t *model) return ret; } +int +machine_at_pl4600c_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pl4600c/SST29EE010.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* Slot 01 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); /* Slot 02 */ + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); /* Onboard */ + pci_register_slot(0x13, PCI_CARD_VIDEO, 0, 0, 0, 0); /* Onboard */ + + + device_add(&umc_hb4_device); + device_add(&umc_8886af_device); + device_add(&um8663af_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_ps2_ami_pci_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5430_onboard_pci_device); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&ess_1688_device); + + if (fdc_current[0] == FDC_INTERNAL){ + fdd_set_turbo(0, 1); + fdd_set_turbo(1, 1); + } + + return ret; +} + int machine_at_atc1415_init(const machine_t *model) { diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 79e46819e3..c3213f1aca 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -126,7 +126,6 @@ machine_at_p5mp3_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -355,6 +354,36 @@ machine_at_pb520r_init(const machine_t *model) return ret; } +int +machine_at_m5pi_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/m5pi/M5PI10R.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0f, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0c, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430lx_device); + device_add(&sio_zb_device); + device_add(&keyboard_ps2_phoenix_device); + device_add(&ide_w83769f_pci_single_channel_device); + device_add(&fdc37c665_ide_sec_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + int machine_at_excalibur_init(const machine_t *model) { diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index a5ab30c420..b6e82301b8 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -97,6 +97,36 @@ machine_at_ambradp90_init(const machine_t *model) return ret; } +int +machine_at_p54np4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p54np4/asus-642accdebcb75833703472.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ + pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430nx_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_ide_pri_device); + device_add(&ncr53c810_onboard_pci_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_586ip_init(const machine_t *model) { diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 008acbff2b..7b59686d6a 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -1,3 +1,25 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Standard PC/AT implementation. + * + * + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * Jasmine Iwanek, + * + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2025 Jasmine Iwanek. + */ #include #include #include @@ -37,22 +59,94 @@ machine_xt_common_init(const machine_t *model, int fixed_floppy) standalone_gameport_type = &gameport_device; } +static const device_config_t ibmpc_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5150_5700671", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "5700671 (10/19/81)", .internal_name = "ibm5150_5700671", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_19OCT81_5700671_U33.BIN", "" } }, + { .name = "5700051 (04/24/81)", .internal_name = "ibm5150_5700051", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc/BIOS_IBM5150_24APR81_5700051_U33.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, + { .files_no = 0 } + }, + }, + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 0 + }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmpc_device = { + .name = "IBM PC (1981) Device", + .internal_name = "ibmpc_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmpc_config +}; + int machine_pc_init(const machine_t *model) { - int ret; + int ret = 0; + int ret2; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; - ret = bios_load_linear("roms/machines/ibmpc/BIOS_5150_24APR81_U33.BIN", - 0x000fe000, 40960, 0); - if (ret) { - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", - 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", - 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", - 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", - 0x000fc000, 8192, 0); + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 40960, 0); + device_context_restore(); + + if (enable_basic && ret) { + ret2 = bios_load_aux_linear("roms/machines/ibmpc/ibm-basic-1.00.rom", + 0x000f6000, 32768, 0); + if (!ret2) { + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U29 - 5700019.bin", + 0x000f6000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U30 - 5700027.bin", + 0x000f8000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U31 - 5700035.bin", + 0x000fa000, 8192, 0); + bios_load_aux_linear("roms/machines/ibmpc/IBM 5150 - Cassette BASIC version C1.00 - U32 - 5700043.bin", + 0x000fc000, 8192, 0); + } } if (bios_only || !ret) @@ -62,28 +156,98 @@ machine_pc_init(const machine_t *model) machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } +static const device_config_t ibmpc82_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5150_1501476", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501476 (10/27/82)", .internal_name = "ibm5150_1501476", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_27OCT82_1501476_U33.BIN", "" } }, + { .name = "5000024 (08/16/82)", .internal_name = "ibm5150_5000024", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/ibmpc82/BIOS_5150_16AUG82_5000024_U33.BIN", "" } }, + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, + { .files_no = 0 } + }, + }, + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmpc82_device = { + .name = "IBM PC (1982) Devices", + .internal_name = "ibmpc82_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmpc82_config +}; + int machine_pc82_init(const machine_t *model) { - int ret; - int ret2; + int ret = 0; + int ret2; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; - ret = bios_load_linear("roms/machines/ibmpc82/pc102782.bin", - 0x000fe000, 40960, 0); - if (ret) { + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 40960, 0); + device_context_restore(); + + if (enable_basic && ret) { ret2 = bios_load_aux_linear("roms/machines/ibmpc82/ibm-basic-1.10.rom", 0x000f6000, 32768, 0); if (!ret2) { - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f6", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U29 - 5000019.bin", 0x000f6000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.f8", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U30 - 5000021.bin", 0x000f8000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fa", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U31 - 5000022.bin", 0x000fa000, 8192, 0); - bios_load_aux_linear("roms/machines/ibmpc82/basicc11.fc", + bios_load_aux_linear("roms/machines/ibmpc82/IBM 5150 - Cassette BASIC version C1.10 - U32 - 5000023.bin", 0x000fc000, 8192, 0); } } @@ -92,40 +256,110 @@ machine_pc82_init(const machine_t *model) return ret; device_add(&keyboard_pc82_device); - device_add(&ibm_5161_device); machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } +static const device_config_t ibmxt_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5160_1501512_5000027", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } }, + { .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } }, + { .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } }, +#if 0 + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, +#endif + { .files_no = 0 } + }, + }, + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + .name = "enable_basic", + .description = "IBM Cassette Basic", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmxt_device = { + .name = "IBM XT (1982) Device", + .internal_name = "ibmxt_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt_config +}; + int machine_xt_init(const machine_t *model) { - int ret; + int ret = 0; + uint8_t enable_5161; + uint8_t enable_basic; + const char *fn; - ret = bios_load_linear("roms/machines/ibmxt/xt.rom", - 0x000f0000, 65536, 0); - if (!ret) { - ret = bios_load_linear("roms/machines/ibmxt/1501512.u18", - 0x000fe000, 65536, 0x6000); - if (ret) { - bios_load_aux_linear("roms/machines/ibmxt/1501512.u18", - 0x000f8000, 24576, 0); - bios_load_aux_linear("roms/machines/ibmxt/5000027.u19", - 0x000f0000, 32768, 0); - } + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + enable_basic = machine_get_config_int("enable_basic"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); + + if (enable_basic && ret) { + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } + device_context_restore(); if (bios_only || !ret) return ret; - device_add(&keyboard_xt_device); - device_add(&ibm_5161_device); machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } @@ -147,28 +381,93 @@ machine_genxt_init(const machine_t *model) return ret; } +static const device_config_t ibmxt86_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "ibm5160_050986", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .bios = { + { .name = "1501512 (05/09/86)", .internal_name = "ibm5160_050986", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } }, + { .name = "5000026 (01/10/86)", .internal_name = "ibm5160_011086", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } }, + { .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL, + .files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } }, +#if 0 + // The following are Diagnostic ROMs. + { .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } }, + { .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } }, + { .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } }, +#endif + { .files_no = 0 } + }, + }, + { + .name = "enable_5161", + .description = "IBM 5161 Expansion Unit", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ibmxt86_device = { + .name = "IBM XT (1986) Device", + .internal_name = "ibmxt86_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt86_config +}; + int machine_xt86_init(const machine_t *model) { - int ret; + int ret = 0; + uint8_t enable_5161; + const char *fn; + + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + enable_5161 = machine_get_config_int("enable_5161"); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000); - ret = bios_load_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000fe000, 65536, 0x6000); if (ret) { - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000f8000, 24576, 0); - (void) bios_load_aux_linear("roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", - 0x000f0000, 32768, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + (void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + (void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0); } + device_context_restore(); if (bios_only || !ret) return ret; device_add(&keyboard_xt86_device); - device_add(&ibm_5161_device); machine_xt_common_init(model, 0); + if (enable_5161) + device_add(&ibm_5161_device); + return ret; } @@ -212,6 +511,31 @@ machine_xt_amixt_init(const machine_t *model) return ret; } +// TODO +// Onboard EGA Graphics (NSI Logic EVC315-S on early boards STMicroelectronics EGA on later revisions) +// RTC +// Adaptec ACB-2072 RLL Controller Card (Optional) +// Atari PCM1 Mouse Support +int +machine_xt_ataripc3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ataripc3/AWARD_ATARI_PC_BIOS_3.08.BIN", + 0x000f8000, 32768, 0); +#if 0 + ret = bios_load_linear("roms/machines/ataripc3/c101701-004 308.u61", + 0x000f8000, 0x8000, 0); +#endif + + if (bios_only || !ret) + return ret; + + machine_xt_clone_init(model, 0); + + return ret; +} + int machine_xt_znic_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 91893242bb..43789a2f6d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15,9 +15,11 @@ * * Authors: Miran Grca, * Fred N. van Kempen, + * Jasmine Iwanek, * * Copyright 2016-2020 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2025 Jasmine Iwanek. */ #include #include @@ -55,6 +57,12 @@ extern const device_t vid_device_sl; extern const device_t t1200_video_device; extern const device_t compaq_plasma_device; extern const device_t ps1_2011_device; +extern const device_t ibmpc_device; +extern const device_t ibmpc82_device; +extern const device_t ibmxt_device; +extern const device_t ibmxt86_device; +extern const device_t ibmat_device; +extern const device_t ibmxt286_device; const machine_filter_t machine_types[] = { { "None", MACHINE_TYPE_NONE }, @@ -243,7 +251,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmpc_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -282,7 +290,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmpc82_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -360,7 +368,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmxt_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -399,7 +407,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmxt86_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -484,6 +492,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8088] Atari PC 3", + .internal_name = "ataripc3", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_ataripc3_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FDC, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xtclone_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, //&fdc_xt_device, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, { .name = "[8088] Bondwell BW230", .internal_name = "bw230", @@ -2634,7 +2681,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmat_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -2754,7 +2801,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &ibmxt286_device, .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, @@ -3405,6 +3452,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[NEAT] Atari PC 4", + .internal_name = "ataripc4", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_ataripc4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FDC, + .ram = { + .min = 512, + .max = 8192, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = &keyboard_at_ami_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, //&fdc_at_device, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has "AMI KEYBOARD BIOS", most likely 'F'. */ { .name = "[NEAT] DataExpert 286", @@ -4348,9 +4434,9 @@ const machine_t machines[] = { .max_voltage = 0, .min_multi = 0, .max_multi = 0, - + }, - .bus_flags = MACHINE_PS2, + .bus_flags = MACHINE_PS2, .flags = MACHINE_IDE | MACHINE_VIDEO , /* Machine has internal OTI 077 Video card*/ .ram = { .min = 2048, @@ -8668,6 +8754,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Compaq Presario 7100 / 7200 Series, using MiTAC/Trigon PL4600C (486). */ + /* Has a VIA VT82C42N KBC. */ + { + .name = "[UMC 8881] Compaq Presario 7100/7200 Series 486", + .internal_name = "pl4600c", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_pl4600c_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5430_onboard_pci_device, + .snd_device = &ess_1688_device, + .net_device = NULL + }, /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ { .name = "[VIA VT82C496G] DFI G486VPA", @@ -9366,6 +9493,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* The M5Pi appears to have a Phoenix MultiKey KBC firmware according to photos. */ + { + .name = "[i430LX] Micronics M5Pi", + .internal_name = "m5pi", + .type = MACHINE_TYPE_SOCKET4, + .chipset = MACHINE_CHIPSET_INTEL_430LX, + .init = machine_at_m5pi_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 5000, + .max_voltage = 5000, + .min_multi = MACHINE_MULTIPLIER_FIXED, + .max_multi = MACHINE_MULTIPLIER_FIXED + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* OPTi 596/597 */ /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the @@ -9658,6 +9825,46 @@ const machine_t machines[] = { .net_device = NULL }, /* Has AMI 'H' KBC firmware. */ + { + .name = "[i430NX] ASUS PCI/I-P54NP4", + .internal_name = "p54np4", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_p54np4_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE | MACHINE_SCSI | MACHINE_APM, + .ram = { + .min = 2048, + .max = 524288, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMI 'H' KBC firmware. */ { .name = "[i430NX] Gigabyte GA-586IP", .internal_name = "586ip", diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index 8555642e65..4ed0333a7c 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -144,23 +144,6 @@ plat_cdrom_ext_medium_changed(void *local) return ret; } -void -plat_cdrom_get_audio_tracks(void *local, int *st_track, int *end, TMSF *lead_out) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - *st_track = 1; - *end = 1; - lead_out->min = 0; - lead_out->sec = 0; - lead_out->fr = 2; - - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_tracks(): %02i, %02i, %02i:%02i:%02i\n", - *st_track, *end, lead_out->min, lead_out->sec, lead_out->fr); -} - /* This replaces both Info and EndInfo, they are specified by a variable. */ int plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index d18894bf68..f77370574d 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -43,6 +43,7 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin) #endif #ifdef Q_OS_WINDOWS +# include "qt_rendererstack.hpp" # include "qt_winrawinputfilter.hpp" # include "qt_winmanagerfilter.hpp" # include <86box/win.h> @@ -143,48 +144,52 @@ keyboard_getkeymap() } } -static void -kbd_handle(uint16_t scancode, uint16_t flags) +void +win_keyboard_handle(uint32_t scancode, int up, int e0, int e1) { - if (flags & LLKHF_EXTENDED) - scancode |= 0x100; - - /* Translate the scan code to 9-bit */ - scancode = convert_scan_code(scancode); + /* If it's not a scan code that starts with 0xE1 */ + if (e1) { + if (scancode == 0x1D) { + scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would + otherwise be E0 00 but that is invalid + anyway). + Also, take a potential mapping into + account. */ + } else + scancode = 0xFFFF; + if (scancode != 0xFFFF) + keyboard_input(!up, scancode); + } else { + if (e0) + scancode |= 0x100; - /* Remap it according to the list from the Registry */ - if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { - // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); - scancode = scancode_map[scancode]; - } + /* Translate the scan code to 9-bit */ + scancode = convert_scan_code(scancode); - /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - - /* Translate right CTRL to left ALT if the user has so - chosen. */ - if ((scancode == 0x11d) && rctrl_is_lalt) - scancode = 0x038; - - /* Normal scan code pass through, pass it through as is if - it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(flags & LLKHF_UP), scancode); -} + /* Remap it according to the list from the Registry */ + if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { + // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); + scancode = scancode_map[scancode]; + } -static LRESULT CALLBACK -input_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) -{ - LPKBDLLHOOKSTRUCT lpKdhs = (LPKBDLLHOOKSTRUCT) lParam; + /* If it's not 0xFFFF, send it to the emulated + keyboard. + We use scan code 0xFFFF to mean a mapping that + has a prefix other than E0 and that is not E1 1D, + which is, for our purposes, invalid. */ - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); + /* Translate right CTRL to left ALT if the user has so + chosen. */ + if ((scancode == 0x11d) && rctrl_is_lalt) + scancode = 0x038; - main_window->checkFullscreenHotkey(); + /* Normal scan code pass through, pass it through as is if + it's not an invalid scan code. */ + if (scancode != 0xFFFF) + keyboard_input(!up, scancode); - return CallNextHookEx(NULL, nCode, wParam, lParam); + main_window->checkFullscreenHotkey(); + } } static LRESULT CALLBACK @@ -193,45 +198,68 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) LPKBDLLHOOKSTRUCT lpKdhs = (LPKBDLLHOOKSTRUCT) lParam; /* Checks if CTRL was pressed. */ BOOL bCtrlDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1); + BOOL is_over_window = (GetForegroundWindow() == ((HWND) main_window->winId())); + BOOL ret = TRUE; - if ((nCode < 0) || (nCode != HC_ACTION) || (!mouse_capture && !video_fullscreen)) + static int last = 0; + + if (show_second_monitors) for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { + const auto &secondaryRenderer = main_window->renderers[monitor_index]; + is_over_window = is_over_window || ((secondaryRenderer != nullptr) && + (GetForegroundWindow() == ((HWND) secondaryRenderer->winId()))); + } + + if ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window) return CallNextHookEx(NULL, nCode, wParam, lParam); else if ((lpKdhs->scanCode == 0x01) && (lpKdhs->flags & LLKHF_ALTDOWN) && - !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode == 0x01) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode == 0x0f) && (lpKdhs->flags & LLKHF_ALTDOWN) && - !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode == 0x0f) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode == 0x39) && (lpKdhs->flags & LLKHF_ALTDOWN) && - !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode == 0x3e) && (lpKdhs->flags & LLKHF_ALTDOWN) && - !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode == 0x49) && bCtrlDown && !(lpKdhs->flags & LLKHF_UP)) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) { - kbd_handle(lpKdhs->scanCode & 0x00ff, lpKdhs->flags); - return TRUE; - } else - return CallNextHookEx(NULL, nCode, wParam, lParam); + !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) + ret = TRUE; + else if ((lpKdhs->scanCode == 0x01) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) + ret = TRUE; + else if ((lpKdhs->scanCode == 0x0f) && (lpKdhs->flags & LLKHF_ALTDOWN) && + !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) + ret = TRUE; + else if ((lpKdhs->scanCode == 0x0f) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) + ret = TRUE; + else if ((lpKdhs->scanCode == 0x39) && (lpKdhs->flags & LLKHF_ALTDOWN) && + !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) + ret = TRUE; + else if ((lpKdhs->scanCode == 0x3e) && (lpKdhs->flags & LLKHF_ALTDOWN) && + !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) + ret = TRUE; + else if ((lpKdhs->scanCode == 0x49) && bCtrlDown && !(lpKdhs->flags & LLKHF_UP)) + ret = TRUE; + else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) + ret = TRUE; + else + ret = CallNextHookEx(NULL, nCode, wParam, lParam); + + if (lpKdhs->scanCode == 0x00000045) { + if ((lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000090)) { + /* NumLock. */ + lpKdhs->flags &= ~LLKHF_EXTENDED; + } else if (!(lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000013)) { + /* Pause - send E1 1D. */ + win_keyboard_handle(0xe1, 0, 0, 0); + win_keyboard_handle(0x1d, LLKHF_UP, 0, 0); + } + } else if (!last && (lpKdhs->scanCode == 0x00000036)) + /* Non-fake right shift. */ + lpKdhs->flags &= ~LLKHF_EXTENDED; + + if (lpKdhs->scanCode == 0x00000236) + last = 1; + else if (last && (lpKdhs->scanCode == 0x00000036)) + last = 0; + + win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0); + + return ret; } #endif #ifdef Q_OS_WINDOWS static HHOOK llhook = NULL; -static HHOOK llihook = NULL; #endif void @@ -494,12 +522,26 @@ main(int argc, char *argv[]) }); } + /* Force raw input if a debugger is present. */ + if (IsDebuggerPresent()) { + pclog("WARNING: Debugged detected, forcing raw input\n"); + hook_enabled = 0; + } + + if (hook_enabled) { + /* Yes, low-level hooks *DO* work with raw input, at least global ones. */ + llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0); + atexit([] () -> void { + if (llhook) + UnhookWindowsHookEx(llhook); + }); + } + /* Setup raw input */ auto rawInputFilter = WindowsRawInputFilter::Register(main_window); if (rawInputFilter) { app.installNativeEventFilter(rawInputFilter.get()); - if (raw_input) - main_window->setSendKeyboardInput(false); + main_window->setSendKeyboardInput(false); } #endif @@ -547,7 +589,6 @@ main(int argc, char *argv[]) /* Initialize the rendering window, or fullscreen. */ QTimer::singleShot(0, &app, [] { pc_reset_hard_init(); - main_thread = new std::thread(main_thread_fn); /* Set the PAUSE mode depending on the renderer. */ #ifdef USE_VNC @@ -556,20 +597,9 @@ main(int argc, char *argv[]) else #endif plat_pause(0); - }); -#ifdef Q_OS_WINDOWS - if (!raw_input) { - llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0); - llihook = SetWindowsHookEx(WH_KEYBOARD_LL, input_LowLevelKeyboardProc, NULL, GetCurrentThreadId()); - atexit([] () -> void { - if (llihook) - UnhookWindowsHookEx(llihook); - if (llhook) - UnhookWindowsHookEx(llhook); - }); - } -#endif + main_thread = new std::thread(main_thread_fn); + }); const auto ret = app.exec(); cpu_thread_run = 0; diff --git a/src/qt/qt_mediahistorymanager.cpp b/src/qt/qt_mediahistorymanager.cpp index 2acdc8e5bb..d548c0779c 100644 --- a/src/qt/qt_mediahistorymanager.cpp +++ b/src/qt/qt_mediahistorymanager.cpp @@ -336,16 +336,20 @@ MediaHistoryManager::removeMissingImages(device_index_list_t &device_history) continue; } - char temp[MAX_IMAGE_PATH_LEN -1] = { 0 }; + char temp[MAX_IMAGE_PATH_LEN * 2] = { 0 }; if (path_abs(checked_path.toUtf8().data())) { if (checked_path.length() > (MAX_IMAGE_PATH_LEN - 1)) - fatal("removeMissingImages(): checked_path.length() > 2047\n"); + fatal("removeMissingImages(): checked_path.length() > %i\n", MAX_IMAGE_PATH_LEN - 1); else snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s", checked_path.toUtf8().constData()); - } else - snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, - path_get_slash(usr_path), checked_path.toUtf8().constData()); + } else { + if ((strlen(usr_path) + strlen(path_get_slash(usr_path)) + checked_path.length()) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("removeMissingImages(): Combined absolute path length > %i\n", MAX_IMAGE_PATH_LEN - 1); + else + snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, + path_get_slash(usr_path), checked_path.toUtf8().constData()); + } path_normalize(temp); QString qstr = QString::fromUtf8(temp); diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 01d7d3f9f9..9679c9e212 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -160,6 +160,7 @@ SettingsPorts::on_pushButtonSerialPassThru4_clicked() DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); } +#if 0 void SettingsPorts::on_pushButtonSerialPassThru5_clicked() { @@ -177,6 +178,7 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked() { DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); } +#endif void SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked) @@ -220,4 +222,4 @@ SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked) { ui->pushButtonSerialPassThru7->setEnabled(checked); } -#endif \ No newline at end of file +#endif diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index 1ecb051afa..fb9cdb3431 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -19,45 +19,23 @@ class SettingsPorts : public QWidget { #if 0 private slots: void on_checkBoxSerialPassThru7_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru6_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru5_clicked(bool checked); #endif - -private slots: void on_checkBoxSerialPassThru4_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru3_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru2_clicked(bool checked); - -private slots: void on_checkBoxSerialPassThru1_clicked(bool checked); private slots: +#if 0 void on_pushButtonSerialPassThru7_clicked(); - -private slots: void on_pushButtonSerialPassThru6_clicked(); - -private slots: void on_pushButtonSerialPassThru5_clicked(); - -private slots: +#endif void on_pushButtonSerialPassThru4_clicked(); - -private slots: void on_pushButtonSerialPassThru3_clicked(); - -private slots: void on_pushButtonSerialPassThru2_clicked(); - -private slots: void on_pushButtonSerialPassThru1_clicked(); private slots: diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 4ff515c491..a1da0af61f 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -44,6 +44,8 @@ #include <86box/plat.h> #include <86box/86box.h> +extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); + #include #include @@ -64,9 +66,9 @@ WindowsRawInputFilter::Register(MainWindow *window) .hwndTarget = nullptr} }; - if (raw_input && (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)) + if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE)) return std::unique_ptr(nullptr); - else if (!raw_input && RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE) + else if (!hook_enabled && (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)) return std::unique_ptr(nullptr); std::unique_ptr inputfilter(new WindowsRawInputFilter(window)); @@ -97,10 +99,10 @@ WindowsRawInputFilter::~WindowsRawInputFilter() .hwndTarget = NULL} }; - if (raw_input) - RegisterRawInputDevices(rid, 2, sizeof(rid[0])); - else + if (hook_enabled) RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])); + else + RegisterRawInputDevices(rid, 2, sizeof(rid[0])); } bool @@ -158,10 +160,8 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input) mouse_handle(raw); break; case RIM_TYPEHID: - { - win_joystick_handle(raw); - break; - } + win_joystick_handle(raw); + break; } } } @@ -171,54 +171,10 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input) void WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) { - USHORT scancode; - RAWKEYBOARD rawKB = raw->data.keyboard; - scancode = rawKB.MakeCode; - - /* If it's not a scan code that starts with 0xE1 */ - if ((rawKB.Flags & RI_KEY_E1)) { - if (rawKB.MakeCode == 0x1D) { - scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would - otherwise be E0 00 but that is invalid - anyway). - Also, take a potential mapping into - account. */ - } else - scancode = 0xFFFF; - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - } else { - if (rawKB.Flags & RI_KEY_E0) - scancode |= 0x100; - - /* Translate the scan code to 9-bit */ - scancode = convert_scan_code(scancode); - - /* Remap it according to the list from the Registry */ - if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { - // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); - scancode = scancode_map[scancode]; - } - /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - - /* Translate right CTRL to left ALT if the user has so - chosen. */ - if ((scancode == 0x11d) && rctrl_is_lalt) - scancode = 0x038; - - /* Normal scan code pass through, pass it through as is if - it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - - window->checkFullscreenHotkey(); - } + win_keyboard_handle(rawKB.MakeCode, (rawKB.Flags & RI_KEY_BREAK), + (rawKB.Flags & RI_KEY_E0), (rawKB.Flags & RI_KEY_E1)); } void diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 7e3a588c39..9d82d68cc7 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -398,26 +398,6 @@ plat_cdrom_ext_medium_changed(void *local) return ret; } -void -plat_cdrom_get_audio_tracks(void *local, int *st_track, int *end, TMSF *lead_out) -{ - win_cdrom_ioctl_t *ioctl = (win_cdrom_ioctl_t *) local; - PCDROM_TOC toc = (PCDROM_TOC) ioctl->cur_toc; - - plat_cdrom_read_toc(ioctl); - - PTRACK_DATA ltd = &toc->TrackData[toc->LastTrack]; - - *st_track = 1; - *end = toc->LastTrack; - lead_out->min = ltd->Address[1]; - lead_out->sec = ltd->Address[2]; - lead_out->fr = ltd->Address[3]; - - win_cdrom_ioctl_log("plat_cdrom_get_audio_tracks(): %02i, %02i, %02i:%02i:%02i\n", - *st_track, *end, lead_out->min, lead_out->sec, lead_out->fr); -} - /* This replaces both Info and EndInfo, they are specified by a variable. */ int plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index e3f38c4e55..58779e7ac3 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -678,6 +678,7 @@ aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) aha_eeprom_save(dev); dev->rom_addr = config->mem[0].base; + aha_log("Base = %08X, Size = %08X\n", config->mem[0].base, config->mem[0].size); if (dev->rom_addr) { mem_mapping_enable(&dev->bios.mapping); aha_log("SCSI BIOS set to: %08X-%08X\n", dev->rom_addr, dev->rom_addr + config->mem[0].size - 1); @@ -869,13 +870,12 @@ aha_setmcode(x54x_t *dev) } aha1542cp_pnp_rom = (uint8_t *) malloc(dev->pnp_len + 7); fseek(fp, dev->pnp_offset, SEEK_SET); - (void) !fread(aha1542cp_pnp_rom, dev->pnp_len, 1, fp); + (void) !fread(aha1542cp_pnp_rom, 4, 1, fp); memset(&(aha1542cp_pnp_rom[4]), 0x00, 5); fseek(fp, dev->pnp_offset + 4, SEEK_SET); (void) !fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, fp); - /* Even the real AHA-1542CP microcode seem to be flipping bit - 4 to not erroneously indicate there is a range length. */ - aha1542cp_pnp_rom[0x87] |= 0x04; + /* Patch determined from Dizzy's AHA-1542CP PNP ROM dump. */ + aha1542cp_pnp_rom[0x26] = 0x03; /* Insert the terminator and the checksum byte that will later be filled in by the isapnp code. */ aha1542cp_pnp_rom[dev->pnp_len + 5] = 0x79; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index e241531c98..832b04491a 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -2115,7 +2115,7 @@ scsi_cdrom_command_matsushita(void *sc, uint8_t *cdb, int32_t *BufLen) dev->current_cdb[0] = cdb[0]; /* Keep cmd_stat at 0x00, therefore, it's going to process it as GPCMD_PLAY_AUDIO_MSF. */ break; - + case GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA: cdb[0] = GPCMD_PLAY_AUDIO_TRACK_INDEX; dev->current_cdb[0] = cdb[0]; @@ -2167,6 +2167,12 @@ scsi_cdrom_command_nec(void *sc, uint8_t *cdb, int32_t *BufLen) cmd_stat = 0x01; break; + case GPCMD_UNKNOWN_SCSI2_NEC: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + cmd_stat = 0x01; + break; + case GPCMD_AUDIO_TRACK_SEARCH_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) @@ -2306,7 +2312,7 @@ scsi_cdrom_command_pioneer(void *sc, uint8_t *cdb, int32_t *BufLen) else { ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); len = 4; - + if (ret) { scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -2845,7 +2851,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } } else ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1, 0); - + if (ret > 0) { dev->requested_blocks = max_len; dev->packet_len = alloc_length; diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index be50d9a891..c2e5c91683 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -114,6 +114,7 @@ #define INTR_FC 0x08 #define INTR_BS 0x10 #define INTR_DC 0x20 +#define INTR_ILL 0x40 #define INTR_RST 0x80 #define SEQ_0 0x0 @@ -174,12 +175,11 @@ typedef struct esp_t { uint8_t bus; uint8_t id, lun; Fifo8 cmdfifo; - uint32_t do_cmd; uint8_t cmdfifo_cdb_offset; int data_ready; - int32_t xfer_counter; - int dma_enabled; + int32_t xfer_counter; + int dma_enabled; uint32_t buffer_pos; uint32_t dma_regs[8]; @@ -198,6 +198,7 @@ typedef struct esp_t { struct { uint8_t mode; uint8_t status; + int interrupt; int pos; } dma_86c01; @@ -239,7 +240,7 @@ static void esp_dma_ti_check(esp_t *dev); static void esp_nodma_ti_dataout(esp_t *dev); static void esp_pci_soft_reset(esp_t *dev); static void esp_pci_hard_reset(esp_t *dev); -static void handle_ti(void *priv); +static void handle_ti(esp_t *dev); static int esp_cdb_length(uint8_t *buf) @@ -253,7 +254,7 @@ esp_cdb_length(uint8_t *buf) break; case 1: case 2: - case 6: + case 6: /*Vendor unique*/ cdb_len = 10; break; case 4: @@ -292,9 +293,11 @@ esp_irq(esp_t *dev, int level) if (dev->mca) { if (level) { picintlevel(1 << dev->irq, &dev->irq_state); + dev->dma_86c01.mode |= 0x40; esp_log("Raising IRQ...\n"); } else { picintclevel(1 << dev->irq, &dev->irq_state); + dev->dma_86c01.mode &= ~0x40; esp_log("Lowering IRQ...\n"); } } else { @@ -307,8 +310,8 @@ esp_irq(esp_t *dev, int level) * DMA_STAT_DONE and the ESP IRQ arriving which is visible to the * guest that can cause confusion e.g. Linux */ - if ((dev->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 && - dev->dma_regs[DMA_WBC] == 0) + if (((dev->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x03) && + (dev->dma_regs[DMA_WBC] == 0)) dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; } else dev->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT; @@ -383,7 +386,7 @@ esp_get_tc(esp_t *dev) { uint32_t dmalen; - dmalen = dev->rregs[ESP_TCLO]; + dmalen = dev->rregs[ESP_TCLO] & 0xff; dmalen |= dev->rregs[ESP_TCMID] << 8; dmalen |= dev->rregs[ESP_TCHI] << 16; @@ -395,10 +398,11 @@ esp_set_tc(esp_t *dev, uint32_t dmalen) { uint32_t old_tc = esp_get_tc(dev); - dev->rregs[ESP_TCLO] = dmalen; + dev->rregs[ESP_TCLO] = dmalen & 0xff; dev->rregs[ESP_TCMID] = dmalen >> 8; dev->rregs[ESP_TCHI] = dmalen >> 16; + esp_log("OLDTC=%d, DMALEN=%d.\n", old_tc, dmalen); if (old_tc && !dmalen) dev->rregs[ESP_RSTAT] |= STAT_TC; } @@ -408,10 +412,11 @@ esp_get_stc(esp_t *dev) { uint32_t dmalen; - dmalen = dev->wregs[ESP_TCLO]; - dmalen |= dev->wregs[ESP_TCMID] << 8; - dmalen |= dev->wregs[ESP_TCHI] << 16; + dmalen = dev->wregs[ESP_TCLO] & 0xff; + dmalen |= (dev->wregs[ESP_TCMID] << 8); + dmalen |= (dev->wregs[ESP_TCHI] << 16); + esp_log("STCW=%d.\n", dmalen); return dmalen; } @@ -459,25 +464,25 @@ esp_transfer_data(esp_t *dev) dev->rregs[ESP_RSEQ] = SEQ_CD; break; - case CMD_SELATNS: - case (CMD_SELATNS | CMD_DMA): - /* - * Initial incoming data xfer is complete so raise command - * completion interrupt - */ - dev->rregs[ESP_RINTR] |= INTR_BS; - dev->rregs[ESP_RSEQ] = SEQ_MO; - break; + case CMD_SELATNS: + case (CMD_SELATNS | CMD_DMA): + /* + * Initial incoming data xfer is complete so raise command + * completion interrupt + */ + dev->rregs[ESP_RINTR] |= INTR_BS; + dev->rregs[ESP_RSEQ] = SEQ_MO; + break; - case CMD_TI: - case (CMD_TI | CMD_DMA): - /* - * Bus service interrupt raised because of initial change to - * DATA phase - */ - dev->rregs[ESP_CMD] = 0; - dev->rregs[ESP_RINTR] |= INTR_BS; - break; + case CMD_TI: + case (CMD_TI | CMD_DMA): + /* + * Bus service interrupt raised because of initial change to + * DATA phase + */ + dev->rregs[ESP_CMD] = 0; + dev->rregs[ESP_RINTR] |= INTR_BS; + break; } esp_raise_irq(dev); @@ -621,16 +626,13 @@ esp_hard_reset(esp_t *dev) { memset(dev->rregs, 0, ESP_REGS); memset(dev->wregs, 0, ESP_REGS); - dev->tchi_written = 0; dev->ti_size = 0; fifo8_reset(&dev->fifo); fifo8_reset(&dev->cmdfifo); dev->dma = 0; - dev->do_cmd = 0; + dev->tchi_written = 0; dev->rregs[ESP_CFG1] = dev->mca ? dev->HostID : 7; esp_log("ESP Reset\n"); - for (uint8_t i = 0; i < 16; i++) - scsi_device_reset(&scsi_devices[dev->bus][i]); timer_stop(&dev->timer); } @@ -681,7 +683,7 @@ esp_do_dma(esp_t *dev) len = esp_get_tc(dev); - switch (esp_get_phase(dev)) { + switch (esp_get_phase(dev)) { case STAT_MO: len = MIN(len, fifo8_num_free(&dev->cmdfifo)); if (dev->mca) { @@ -787,7 +789,6 @@ esp_do_dma(esp_t *dev) esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, WRITE_TO_DEVICE); esp_set_tc(dev, esp_get_tc(dev) - len); - dev->buffer_pos += len; dev->xfer_counter -= len; dev->ti_size += len; @@ -827,6 +828,7 @@ esp_do_dma(esp_t *dev) /* Defer until data is available. */ return; } + if (len > dev->xfer_counter) len = dev->xfer_counter; @@ -861,14 +863,6 @@ esp_do_dma(esp_t *dev) break; } - if ((dev->xfer_counter <= 0) && !dev->ti_size && esp_get_tc(dev)) { - /* If the guest underflows TC then terminate SCSI request */ - esp_log("ESP SCSI Read finished (underflow).\n"); - scsi_device_command_phase1(sd); - esp_command_complete(dev, sd->status); - return; - } - if ((dev->xfer_counter <= 0) && (fifo8_num_used(&dev->fifo) < 2)) { /* Defer until the scsi layer has completed */ if (dev->ti_size <= 0) { @@ -1241,10 +1235,8 @@ handle_pad(esp_t *dev) } static void -handle_ti(void *priv) +handle_ti(esp_t *dev) { - esp_t *dev = (esp_t *) priv; - if (dev->dma) { esp_log("ESP Handle TI, do data, minlen = %i\n", esp_get_tc(dev)); esp_do_dma(dev); @@ -1329,8 +1321,6 @@ esp_callback(void *priv) handle_pad(dev); } } - - esp_log("ESP DMA activated = %d, CMD activated = %d, CMD = %02x\n", dev->dma_enabled, dev->do_cmd, (dev->rregs[ESP_CMD] & CMD_CMD)); } static uint32_t @@ -1353,13 +1343,15 @@ esp_reg_read(esp_t *dev, uint32_t saddr) esp_lower_irq(dev); esp_log("ESP RINTR read old val = %02x\n", ret); break; - case ESP_TCHI: - /* Return the unique id if the value has never been written */ - if (!dev->tchi_written && !dev->mca) { - esp_log("ESP TCHI read id 0x12\n"); - ret = TCHI_AM53C974; - } else - ret = dev->rregs[saddr]; + case ESP_TCHI: /* Return the unique id if the value has never been written */ + if (dev->mca) { + ret = dev->rregs[ESP_TCHI]; + } else { + if (!dev->tchi_written) + ret = TCHI_AM53C974; + else + ret = dev->rregs[ESP_TCHI]; + } break; case ESP_RFLAGS: ret = fifo8_num_used(&dev->fifo); @@ -1376,14 +1368,13 @@ static void esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) { esp_log("Write reg %02x = %02x\n", saddr, val); - switch (saddr) { case ESP_TCHI: dev->tchi_written = 1; fallthrough; case ESP_TCLO: case ESP_TCMID: - esp_log("Transfer count regs %02x = %i\n", saddr, val); + esp_log("ESP TCW reg%02x = %02x.\n", saddr, val); dev->rregs[ESP_RSTAT] &= ~STAT_TC; break; case ESP_FIFO: @@ -1393,14 +1384,18 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) esp_do_nodma(dev); break; case ESP_CMD: - dev->rregs[saddr] = val; + dev->rregs[ESP_CMD] = val; if (val & CMD_DMA) { dev->dma = 1; /* Reload DMA counter. */ esp_set_tc(dev, esp_get_stc(dev)); - if (!esp_get_stc(dev)) - esp_set_tc(dev, 0x10000); + if (!esp_get_stc(dev)) { + if (dev->rregs[ESP_CFG2] & 0x40) + esp_set_tc(dev, 0x1000000); + else + esp_set_tc(dev, 0x10000); + } } else { dev->dma = 0; esp_log("ESP Command not for DMA\n"); @@ -1481,6 +1476,8 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) } break; case ESP_WBUSID: + esp_log("ESP BUS ID=%d.\n", val & BUSID_DID); + break; case ESP_WSEL: case ESP_WSYNTP: case ESP_WSYNO: @@ -1505,6 +1502,7 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) static void esp_pci_dma_memory_rw(esp_t *dev, uint8_t *buf, uint32_t len, int dir) { + uint32_t sg_pos = 0; uint32_t addr; int expected_dir; @@ -1513,31 +1511,58 @@ esp_pci_dma_memory_rw(esp_t *dev, uint8_t *buf, uint32_t len, int dir) else expected_dir = WRITE_TO_DEVICE; - esp_log("ESP DMA WBC = %d, addr = %06x, expected direction = %d, dir = %i\n", dev->dma_regs[DMA_WBC], dev->dma_regs[DMA_SPA], expected_dir, dir); - if (dir != expected_dir) { esp_log("ESP unexpected direction\n"); return; } - addr = dev->dma_regs[DMA_WAC]; - if (dev->dma_regs[DMA_WBC] < len) - len = dev->dma_regs[DMA_WBC]; + if (dev->dma_regs[DMA_CMD] & DMA_CMD_MDL) { + if (dev->dma_regs[DMA_STC]) { + if (dev->dma_regs[DMA_WBC] > len) + dev->dma_regs[DMA_WBC] = len; - if (expected_dir) - dma_bm_write(addr, buf, len, 4); - else - dma_bm_read(addr, buf, len, 4); + esp_log("WAC MDL=%08x, STC=%d, ID=%d.\n", dev->dma_regs[DMA_WAC] | (dev->dma_regs[DMA_WMAC] & 0xff000), dev->dma_regs[DMA_STC], dev->id); + for (uint32_t i = 0; i < len; i++) { + addr = dev->dma_regs[DMA_WAC]; - esp_log("DMA: Address = %08X, Length = %08X (%02X %02X %02X %02X -> %02X %02X %02X %02X)\n", dev->dma_regs[DMA_SPA], len, - ram[dev->dma_regs[DMA_SPA]], ram[dev->dma_regs[DMA_SPA] + 1], ram[dev->dma_regs[DMA_SPA] + 2], ram[dev->dma_regs[DMA_SPA] + 3], - buf[0], buf[1], buf[2], buf[3]); + if (expected_dir) + dma_bm_write(addr | (dev->dma_regs[DMA_WMAC] & 0xff000), &buf[sg_pos], len, 4); + else + dma_bm_read(addr | (dev->dma_regs[DMA_WMAC] & 0xff000), &buf[sg_pos], len, 4); + + sg_pos++; + dev->dma_regs[DMA_WBC]--; + dev->dma_regs[DMA_WAC]++; + + if (dev->dma_regs[DMA_WAC] & 0x1000) { + dev->dma_regs[DMA_WAC] = 0; + dev->dma_regs[DMA_WMAC] += 0x1000; + } - /* update status registers */ - dev->dma_regs[DMA_WBC] -= len; - dev->dma_regs[DMA_WAC] += len; - if (dev->dma_regs[DMA_WBC] == 0) - dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; + if (dev->dma_regs[DMA_WBC] <= 0) { + dev->dma_regs[DMA_WBC] = 0; + dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; + } + } + } + } else { + if (dev->dma_regs[DMA_WBC] < len) + len = dev->dma_regs[DMA_WBC]; + + addr = dev->dma_regs[DMA_WAC]; + + if (expected_dir) + dma_bm_write(addr, buf, len, 4); + else + dma_bm_read(addr, buf, len, 4); + + /* update status registers */ + dev->dma_regs[DMA_WBC] -= len; + dev->dma_regs[DMA_WAC] += len; + + if (dev->dma_regs[DMA_WBC] == 0) + dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; + } } static uint32_t @@ -1566,7 +1591,7 @@ esp_pci_dma_write(esp_t *dev, uint16_t saddr, uint32_t val) switch (saddr) { case DMA_CMD: - dev->dma_regs[saddr] = val; + dev->dma_regs[DMA_CMD] = val; esp_log("ESP PCI DMA Write CMD = %02x\n", val & DMA_CMD_MASK); switch (val & DMA_CMD_MASK) { case 0: /*IDLE*/ @@ -1580,21 +1605,32 @@ esp_pci_dma_write(esp_t *dev, uint16_t saddr, uint32_t val) scsi_device_command_stop(&scsi_devices[dev->bus][dev->id]); break; case 3: /*START*/ + dev->dma_regs[DMA_WAC] = dev->dma_regs[DMA_SPA]; + dev->dma_regs[DMA_WMAC] = dev->dma_regs[DMA_SMDLA] & 0xfffffffc; + if (!dev->dma_regs[DMA_STC]) + dev->dma_regs[DMA_STC] = 0x1000000; + dev->dma_regs[DMA_WBC] = dev->dma_regs[DMA_STC]; - dev->dma_regs[DMA_WAC] = dev->dma_regs[DMA_SPA]; - dev->dma_regs[DMA_WMAC] = dev->dma_regs[DMA_SMDLA]; dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT | DMA_STAT_DONE | DMA_STAT_ABORT | DMA_STAT_ERROR | DMA_STAT_PWDN); esp_dma_enable(dev, 1); - esp_log("PCI DMA enable\n"); + esp_log("PCI DMA enable, MDL bit=%02x, SPA=%08x, SMDLA=%08x, STC=%d, ID=%d, SCSICMD=%02x.\n", val & DMA_CMD_MDL, dev->dma_regs[DMA_SPA], dev->dma_regs[DMA_SMDLA], dev->dma_regs[DMA_STC], dev->id, dev->cmdfifo.data[1]); break; default: /* can't happen */ abort(); + break; } break; case DMA_STC: + dev->dma_regs[DMA_STC] = val; + esp_log("DMASTC PCI write=%08x.\n", val); + break; case DMA_SPA: + dev->dma_regs[DMA_SPA] = val; + esp_log("DMASPA PCI write=%08x.\n", val); + break; case DMA_SMDLA: - dev->dma_regs[saddr] = val; + dev->dma_regs[DMA_SMDLA] = val; + esp_log("DMASMDLA PCI write=%08x.\n", val); break; case DMA_STAT: if (dev->sbac & SBAC_STATUS) { @@ -1629,7 +1665,7 @@ esp_pci_hard_reset(esp_t *dev) dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT | DMA_STAT_DONE | DMA_STAT_ABORT | DMA_STAT_ERROR); - dev->dma_regs[DMA_WMAC] = 0xfffffffd; + dev->dma_regs[DMA_WMAC] = 0xfffffffc; } static uint32_t @@ -1680,7 +1716,7 @@ esp_io_pci_write(esp_t *dev, uint32_t addr, uint32_t val, unsigned int size) current = dev->wregs[addr >> 2]; } else if (addr < 0x60) { current = dev->dma_regs[(addr - 0x40) >> 2]; - } else if (addr < 0x74) { + } else if (addr == 0x70) { current = dev->sbac; } @@ -2008,7 +2044,7 @@ esp_pci_read(UNUSED(int func), int addr, void *priv) case 0x07: return esp_pci_regs[0x07] | 0x02; case 0x08: - return 0; /*Revision ID*/ + return 0x10; /*Revision ID*/ case 0x09: return 0; /*Programming interface*/ case 0x0A: @@ -2018,7 +2054,7 @@ esp_pci_read(UNUSED(int func), int addr, void *priv) case 0x0E: return 0; /*Header type */ case 0x10: - return (esp_pci_bar[0].addr_regs[0] & 0x80) | 0x01; /*I/O space*/ + return esp_pci_bar[0].addr_regs[0] | 0x01; /*I/O space*/ case 0x11: return esp_pci_bar[0].addr_regs[1]; case 0x12: @@ -2082,7 +2118,7 @@ esp_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) switch (addr) { case 0x04: - valxor = (val & 3) ^ esp_pci_regs[addr]; + valxor = (val & 0x01) ^ esp_pci_regs[addr]; if (valxor & PCI_COMMAND_IO) { esp_io_remove(dev, dev->PCIBase, 0x80); if ((val & PCI_COMMAND_IO) && (dev->PCIBase != 0)) @@ -2215,6 +2251,8 @@ dc390_init(UNUSED(const device_t *info)) } esp_pci_hard_reset(dev); + for (uint8_t i = 0; i < 16; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); timer_add(&dev->timer, esp_callback, dev, 0); @@ -2240,12 +2278,12 @@ ncr53c9x_in(uint16_t port, void *priv) break; case 0x0c: - if (dev->rregs[ESP_RSTAT] & STAT_INT) + if (dev->dma_86c01.mode & 0x40) dev->dma_86c01.status |= 0x01; else dev->dma_86c01.status &= ~0x01; - if ((dev->dma_86c01.mode & 0x40) || dev->dma_enabled) + if (dev->dma_enabled) dev->dma_86c01.status |= 0x02; else dev->dma_86c01.status &= ~0x02; @@ -2258,7 +2296,7 @@ ncr53c9x_in(uint16_t port, void *priv) } } - esp_log("[%04X:%08X]: NCR53c9x DMA read port = %02x, ret = %02x.\n\n", CS, cpu_state.pc, port, ret); + esp_log("[%04X:%08X]: NCR53c9x DMA read port = %02x, ret = %02x, local = %d.\n\n", CS, cpu_state.pc, port, ret, dev->local); return ret; } @@ -2282,7 +2320,7 @@ ncr53c9x_out(uint16_t port, uint16_t val, void *priv) port &= 0x1f; - esp_log("[%04X:%08X]: NCR53c9x DMA write port = %02x, val = %02x\n", CS, cpu_state.pc, port, val); + esp_log("[%04X:%08X]: NCR53c9x DMA write port = %02x, val = %02x.\n\n", CS, cpu_state.pc, port, val); if (port >= 0x10) esp_reg_write(dev, port - 0x10, val); @@ -2360,6 +2398,8 @@ ncr53c9x_mca_write(int port, uint8_t val, void *priv) ncr53c9x_outb, ncr53c9x_outw, NULL, dev); esp_hard_reset(dev); + for (uint8_t i = 0; i < 8; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); } /* Say hello. */ @@ -2377,7 +2417,7 @@ ncr53c9x_mca_feedb(void *priv) } static void * -ncr53c9x_mca_init(UNUSED(const device_t *info)) +ncr53c9x_mca_init(const device_t *info) { esp_t *dev; @@ -2387,6 +2427,7 @@ ncr53c9x_mca_init(UNUSED(const device_t *info)) dev->bus = scsi_get_bus(); dev->mca = 1; + dev->local = info->local; fifo8_create(&dev->fifo, ESP_FIFO_SZ); fifo8_create(&dev->cmdfifo, ESP_CMDFIFO_SZ); @@ -2396,6 +2437,8 @@ ncr53c9x_mca_init(UNUSED(const device_t *info)) mca_add(ncr53c9x_mca_read, ncr53c9x_mca_write, ncr53c9x_mca_feedb, NULL, dev); esp_hard_reset(dev); + for (uint8_t i = 0; i < 8; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); timer_add(&dev->timer, esp_callback, dev, 0); @@ -2446,7 +2489,7 @@ const device_t dc390_pci_device = { }; const device_t am53c974_pci_device = { - .name = "AMD 53c974 PCI", + .name = "AMD 53c974A PCI", .internal_name = "am53c974", .flags = DEVICE_PCI, .local = 1, diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 3a49f599f7..c878bbb911 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -509,6 +509,9 @@ t128_init(const device_t *info) if (!t128->bios_enabled && !(info->flags & DEVICE_MCA)) t128->status |= 0x80; + if (info->flags & DEVICE_MCA) + t128->status |= 0x08; + if (info->local == 0) timer_add(&t128->timer, t128_callback, t128, 0); diff --git a/src/sio/sio_pc87307.c b/src/sio/sio_pc87307.c index 63e19c03d5..cb772aa5b9 100644 --- a/src/sio/sio_pc87307.c +++ b/src/sio/sio_pc87307.c @@ -34,6 +34,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/sio.h> +#include <86box/plat_fallthrough.h> typedef struct pc87307_t { uint8_t id; @@ -323,8 +324,12 @@ pc87307_write(uint16_t port, uint8_t val, void *priv) } break; case 0x60: + if (dev->regs[0x07] == 0x04) { + val &= 0x03; + } + fallthrough; case 0x62: - dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; + dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07)) break; switch (dev->regs[0x07]) { diff --git a/src/sound/midi.c b/src/sound/midi.c index 78794ef243..e9b4a82b67 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -71,7 +71,7 @@ typedef struct const device_t *device; } MIDI_OUT_DEVICE, MIDI_IN_DEVICE; -static const MIDI_OUT_DEVICE devices[] = { +static const MIDI_OUT_DEVICE midi_out_devices[] = { // clang-format off { &device_none }, #ifdef USE_FLUIDSYNTH @@ -106,8 +106,8 @@ static const MIDI_IN_DEVICE midi_in_devices[] = { int midi_out_device_available(int card) { - if (devices[card].device) - return device_available(devices[card].device); + if (midi_out_devices[card].device) + return device_available(midi_out_devices[card].device); return 1; } @@ -115,21 +115,21 @@ midi_out_device_available(int card) const device_t * midi_out_device_getdevice(int card) { - return devices[card].device; + return midi_out_devices[card].device; } int midi_out_device_has_config(int card) { - if (!devices[card].device) + if (!midi_out_devices[card].device) return 0; - return devices[card].device->config ? 1 : 0; + return midi_out_devices[card].device->config ? 1 : 0; } const char * midi_out_device_get_internal_name(int card) { - return device_get_internal_name(devices[card].device); + return device_get_internal_name(midi_out_devices[card].device); } int @@ -137,8 +137,8 @@ midi_out_device_get_from_internal_name(char *s) { int c = 0; - while (devices[c].device != NULL) { - if (!strcmp(devices[c].device->internal_name, s)) + while (midi_out_devices[c].device != NULL) { + if (!strcmp(midi_out_devices[c].device->internal_name, s)) return c; c++; } @@ -149,8 +149,8 @@ midi_out_device_get_from_internal_name(char *s) void midi_out_device_init(void) { - if ((midi_output_device_current > 0) && devices[midi_output_device_current].device) - device_add(devices[midi_output_device_current].device); + if ((midi_output_device_current > 0) && midi_out_devices[midi_output_device_current].device) + device_add(midi_out_devices[midi_output_device_current].device); midi_output_device_last = midi_output_device_current; } diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 7338a11fcb..07add50627 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -1,22 +1,24 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. * - * This file is part of the 86Box distribution. + * This file is part of the 86Box distribution. * - * Ensoniq AudioPCI family emulation. + * Ensoniq AudioPCI family emulation. * + * Authors: Sarah Walker, + * RichardG, + * Miran Grca, + * Jasmine Iwanek, + * Cacodemon345 * - * - * Authors: Sarah Walker, - * RichardG, - * Miran Grca, - * - * Copyright 2008-2021 Sarah Walker. - * Copyright 2021-2024 RichardG. - * Copyright 2021 Miran Grca. + * Copyright 2008-2021 Sarah Walker. + * Copyright 2021-2024 RichardG. + * Copyright 2021 Miran Grca. + * Copyright 2024-2025 Jasmine Iwanek. + * Copyright 2024-2025 Cacodemon345. */ #include #include @@ -39,14 +41,15 @@ #include <86box/sound.h> #include <86box/timer.h> #include <86box/plat_unused.h> +#include <86box/snd_akm4531.h> #define N 16 -#define ES1371_NCoef 91 +#define ES137x_NCoef 91 -static float low_fir_es1371_coef[ES1371_NCoef]; +static float low_fir_es137x_coef[ES137x_NCoef]; -typedef struct es1371_t { +typedef struct es137x_t { uint8_t pci_command; uint8_t pci_serr; @@ -111,6 +114,9 @@ typedef struct es1371_t { int16_t out_l; int16_t out_r; + int16_t prev_out_l; + int16_t prev_out_r; + int32_t vol_l; int32_t vol_r; } dac[2], adc; @@ -130,14 +136,40 @@ typedef struct es1371_t { uint8_t pci_slot; int pos; - int16_t buffer[SOUNDBUFLEN * 2]; + int16_t buffer[WTBUFLEN * 2]; uint32_t type; -} es1371_t; -#define AUDIOPCI_ES1371 0x13710200 -#define AUDIOPCI_ES1373 0x13710400 -#define AUDIOPCI_CT5880 0x58800400 + akm4531_t akm_codec; + + uint32_t calc_sample_rate; + uint32_t calc_sample_rate_synth; + + double interp_factor; + uint32_t interp_step; + + double interp_factor_synth; + uint32_t interp_step_synth; + + uint32_t step_pcm; + uint32_t step_synth; +} es137x_t; + +static const double akm4531_att_2dbstep_5bits[] = { + // clang-format off + 25.0, 32.0, 41.0, 51.0, 65.0, 82.0, 103.0, 130.0, + 164.0, 206.0, 260.0, 327.0, 412.0, 519.0, 653.0, 822.0, + 1036.0, 1304.0, 1641.0, 2067.0, 2602.0, 3276.0, 4125.0, 5192.0, + 6537.0, 8230.0, 10362.0, 13044.0, 16422.0, 20674.0, 26027.0, 32767.0 + // clang-format on +}; + +static double akm4531_gain_2dbstep_5bits[0x20]; + +#define AUDIOPCI_ES1370 0x50000000 +#define AUDIOPCI_ES1371 0x13710200 +#define AUDIOPCI_ES1373 0x13710400 +#define AUDIOPCI_CT5880 0x58800400 #define LEGACY_SB_ADDR (1 << 29) #define LEGACY_SSCAPE_ADDR_SHIFT 27 @@ -204,8 +236,8 @@ typedef struct es1371_t { #define FORMAT_MONO_16 2 #define FORMAT_STEREO_16 3 -static void es1371_fetch(es1371_t *dev, int dac_nr); -static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl); +static void es137x_fetch(es137x_t *dev, int dac_nr); +static void update_legacy(es137x_t *dev, uint32_t old_legacy_ctrl); #ifdef ENABLE_AUDIOPCI_LOG int audiopci_do_log = ENABLE_AUDIOPCI_LOG; @@ -226,7 +258,7 @@ audiopci_log(const char *fmt, ...) #endif static void -es1371_update_irqs(es1371_t *dev) +es137x_update_irqs(es137x_t *dev) { int irq = 0; @@ -257,63 +289,63 @@ es1371_update_irqs(es1371_t *dev) } static void -es1371_update_tx_irq(es1371_t *dev) +es137x_update_tx_irq(es137x_t *dev) { dev->uart_status &= ~UART_STATUS_TXINT; if (((dev->uart_ctrl & UART_CTRL_TXINTEN) == 0x20) && (dev->uart_status & UART_STATUS_TXRDY)) dev->uart_status |= UART_STATUS_TXINT; - es1371_update_irqs(dev); + es137x_update_irqs(dev); } static void -es1371_set_tx_irq(es1371_t *dev, int set) +es137x_set_tx_irq(es137x_t *dev, int set) { dev->uart_status &= ~UART_STATUS_TXRDY; if (set) dev->uart_status |= UART_STATUS_TXRDY; - es1371_update_tx_irq(dev); + es137x_update_tx_irq(dev); } static void -es1371_update_rx_irq(es1371_t *dev) +es137x_update_rx_irq(es137x_t *dev) { dev->uart_status &= ~UART_STATUS_RXINT; if ((dev->uart_ctrl & UART_CTRL_RXINTEN) && (dev->uart_status & UART_STATUS_RXRDY)) dev->uart_status |= UART_STATUS_RXINT; - es1371_update_irqs(dev); + es137x_update_irqs(dev); } static void -es1371_set_rx_irq(es1371_t *dev, int set) +es137x_set_rx_irq(es137x_t *dev, int set) { dev->uart_status &= ~UART_STATUS_RXRDY; if (set) dev->uart_status |= UART_STATUS_RXRDY; - es1371_update_rx_irq(dev); + es137x_update_rx_irq(dev); } static void -es1371_scan_fifo(es1371_t *dev) +es137x_scan_fifo(es137x_t *dev) { if (dev->read_fifo_pos != dev->write_fifo_pos) { dev->uart_data = dev->uart_fifo[dev->read_fifo_pos]; dev->read_fifo_pos = (dev->read_fifo_pos + 1) & 7; - es1371_set_rx_irq(dev, 1); + es137x_set_rx_irq(dev, 1); } else - es1371_set_rx_irq(dev, 0); + es137x_set_rx_irq(dev, 0); } static void -es1371_write_fifo(es1371_t *dev, uint8_t val) +es137x_write_fifo(es137x_t *dev, uint8_t val) { if (dev->write_fifo_pos < 8) { dev->uart_fifo[dev->write_fifo_pos] = val | UART_FIFO_BYTE_VALID; @@ -322,27 +354,91 @@ es1371_write_fifo(es1371_t *dev, uint8_t val) } static void -es1371_reset_fifo(es1371_t *dev) +es137x_reset_fifo(es137x_t *dev) { for (uint8_t i = 0; i < 8; i++) dev->uart_fifo[i] = 0x00000000; dev->read_fifo_pos = dev->write_fifo_pos = 0; - es1371_set_rx_irq(dev, 0); + es137x_set_rx_irq(dev, 0); +} + +static void +akm4531_reset(es137x_t *dev) +{ + akm4531_t *codec = &dev->akm_codec; + + memset(codec->registers, 0, sizeof(codec->registers)); + + codec->registers[0] = 0x80; + codec->registers[1] = 0x80; + + for (int i = 0x02; i <= 0x0E; i++) { + codec->registers[i] = 0b10000110; + } + + codec->registers[0xf] = 0x80; + + codec->registers[0x17] = 0x3; + codec->registers[0x16] = 0x3; +} + +static double +lerp(double v0, double v1, double t) +{ + return (1. - t) * v0 + t * v1; +} + +static void +es1370_calc_sample_rate(es137x_t *dev) +{ + if (dev->type != AUDIOPCI_ES1370) + return; + + dev->calc_sample_rate = 1411200 / (((dev->int_ctrl >> 16) & 0x1fff) + 2); + + // audiopci_log("ES1370 calc sample rate %u\n", dev->calc_sample_rate); + + dev->interp_factor = 1.0; + dev->interp_step = 1; + + if (dev->calc_sample_rate >= 44100 || dev->calc_sample_rate < 11025) { + dev->interp_factor = 1.0; + dev->interp_step = 1; + dev->calc_sample_rate = 44100; + } + if (dev->calc_sample_rate == 22050) { + dev->interp_factor = 0.5; + dev->interp_step = 2; + } + if (dev->calc_sample_rate == 11025) { + dev->interp_factor = 0.25; + dev->interp_step = 4; + } + if ((((dev->int_ctrl >> 16) & 0x1fff) + 2) == 256) { + /* 5512.5 Hz */ + dev->interp_factor = 0.125; + dev->interp_step = 8; + dev->calc_sample_rate = 5512; + } + + dev->calc_sample_rate_synth = 44100 / (1 << (((dev->int_ctrl >> 12) & 3) ^ 3)); + dev->interp_factor_synth = 1. / (double) ((1 << ((dev->int_ctrl >> 12) & 3) ^ 3)); + dev->interp_step_synth = (1 << (((dev->int_ctrl >> 12) & 3) ^ 3)); } static void -es1371_reset(void *priv) +es137x_reset(void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; nmi = 0; /* Default subsystem ID. */ - dev->subsys_lock = 0x00; - *((uint16_t *) &dev->subsys_id[0]) = 0x1274; - *((uint16_t *) &dev->subsys_id[2]) = 0x1371; + dev->subsys_lock = 0x00; + *((uint16_t *) &dev->subsys_id[0]) = (dev->type == AUDIOPCI_ES1370) ? 0x4942 : 0x1274; + *((uint16_t *) &dev->subsys_id[2]) = (dev->type == AUDIOPCI_ES1370) ? 0x4c4c : 0x1371; /* Interrupt/Chip Select Control Register, Address 00H Addressable as byte, word, longword */ @@ -350,11 +446,13 @@ es1371_reset(void *priv) /* Interrupt/Chip Select Status Register, Address 04H Addressable as longword only */ - if (dev->type >= AUDIOPCI_CT5880) + if (dev->type == AUDIOPCI_ES1370) + dev->int_status = 0x00000060; + else if (dev->type == AUDIOPCI_CT5880) dev->int_status = 0x52080ec0; - else if (dev->type >= AUDIOPCI_ES1373) + else if (dev->type == AUDIOPCI_ES1373) dev->int_status = 0x7f080ec0; - else + else /* AUDIOPCI_ES1371 */ dev->int_status = 0x7ffffec0; /* UART Status Register, Address 09H @@ -441,17 +539,20 @@ es1371_reset(void *priv) dev->uart_fifo[i] = 0xffff0000; /* Reset the UART TX. */ - es1371_set_tx_irq(dev, 0); + es137x_set_tx_irq(dev, 0); /* Reset the UART (RX) FIFO. */ - es1371_reset_fifo(dev); + es137x_reset_fifo(dev); /* Update interrupts to ensure they're all correctly cleared. */ - es1371_update_irqs(dev); + es137x_update_irqs(dev); + + /* Reset the codec. */ + akm4531_reset(dev); } static uint32_t -es1371_read_frame_reg(es1371_t *dev, int frame, int page) +es137x_read_frame_reg(es137x_t *dev, int frame, int page) { uint32_t ret = 0xffffffff; @@ -559,7 +660,7 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page) } static void -es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val) +es137x_write_frame_reg(es137x_t *dev, int frame, int page, uint32_t val) { switch (frame) { case 0x30: @@ -666,9 +767,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val) } static uint8_t -es1371_inb(uint16_t port, void *priv) +es137x_inb(uint16_t port, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint8_t ret = 0xff; switch (port & 0x3f) { @@ -685,7 +786,7 @@ es1371_inb(uint16_t port, void *priv) break; case 0x03: ret = dev->int_ctrl >> 24; - if (dev->type < AUDIOPCI_ES1373) + if (dev->type == AUDIOPCI_ES1371) ret |= 0xfc; break; @@ -713,7 +814,7 @@ es1371_inb(uint16_t port, void *priv) Addressable as byte only */ case 0x08: ret = dev->uart_data; - es1371_set_rx_irq(dev, 0); + es137x_set_rx_irq(dev, 0); audiopci_log("[R] UART DATA = %02X\n", ret); break; @@ -758,19 +859,19 @@ es1371_inb(uint16_t port, void *priv) /* S/PDIF Channel Status Control Register, Address 1CH Addressable as byte, word, longword */ case 0x1c: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus & 0xff; break; case 0x1d: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 8; break; case 0x1e: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 16; break; case 0x1f: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 24; break; @@ -783,24 +884,29 @@ es1371_inb(uint16_t port, void *priv) ret = dev->si_cr >> 8; break; case 0x22: - ret = (dev->si_cr >> 16) | 0x80; + ret = dev->si_cr >> 16; + if (dev->type != AUDIOPCI_ES1370) + ret |= 0x80; break; case 0x23: - ret = 0xff; + if (dev->type == AUDIOPCI_ES1370) + ret = 0x00; + else + ret = 0xff; break; default: - audiopci_log("Bad es1371_inb: port=%04x\n", port); + audiopci_log("Bad es137x_inb: port=%04x\n", port); } - audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret); + audiopci_log("es137x_inb: port=%04x ret=%02x\n", port, ret); return ret; } static uint16_t -es1371_inw(uint16_t port, void *priv) +es137x_inw(uint16_t port, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint16_t ret = 0xffff; switch (port & 0x3e) { @@ -811,7 +917,7 @@ es1371_inw(uint16_t port, void *priv) break; case 0x02: ret = (dev->int_ctrl >> 16) & 0xff0f; - if (dev->type < AUDIOPCI_ES1373) + if (dev->type == AUDIOPCI_ES1371) ret |= 0xfc00; break; @@ -836,11 +942,11 @@ es1371_inw(uint16_t port, void *priv) /* S/PDIF Channel Status Control Register, Address 1CH Addressable as byte, word, longword */ case 0x1c: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus & 0xffff; break; case 0x1e: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus >> 16; break; @@ -850,7 +956,9 @@ es1371_inw(uint16_t port, void *priv) ret = dev->si_cr & 0xffff; break; case 0x22: - ret = (dev->si_cr >> 16) | 0xff80; + ret = dev->si_cr >> 16; + if (dev->type != AUDIOPCI_ES1370) + ret |= 0xff80; break; /* DAC1 Channel Sample Count Register, Address 24H @@ -884,36 +992,39 @@ es1371_inw(uint16_t port, void *priv) case 0x34: case 0x38: case 0x3c: - ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) & 0xffff; + ret = es137x_read_frame_reg(dev, port & 0x3c, dev->mem_page) & 0xffff; break; case 0x32: case 0x36: case 0x3a: case 0x3e: - ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) >> 16; + ret = es137x_read_frame_reg(dev, port & 0x3c, dev->mem_page) >> 16; break; default: break; } - audiopci_log("es1371_inw: port=%04x ret=%04x\n", port, ret); + audiopci_log("es137x_inw: port=%04x ret=%04x\n", port, ret); return ret; } static uint32_t -es1371_inl(uint16_t port, void *priv) +es137x_inl(uint16_t port, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint32_t ret = 0xffffffff; + if ((dev->type == AUDIOPCI_ES1370) && (port & 0x3c) == 0x14) + port = 0x10; + switch (port & 0x3c) { /* Interrupt/Chip Select Control Register, Address 00H Addressable as byte, word, longword */ case 0x00: ret = dev->int_ctrl & 0xff0fffff; - if (ret < AUDIOPCI_ES1373) + if ((ret < AUDIOPCI_ES1373) && (ret != AUDIOPCI_ES1370)) ret |= 0xfc000000; break; @@ -940,6 +1051,8 @@ es1371_inl(uint16_t port, void *priv) /* CODEC Read Register, Address 14H Addressable as longword only */ case 0x14: + if (dev->type == AUDIOPCI_ES1370) + break; ret = dev->codec_ctrl | CODEC_READY; break; @@ -952,14 +1065,16 @@ es1371_inl(uint16_t port, void *priv) /* S/PDIF Channel Status Control Register, Address 1CH Addressable as byte, word, longword */ case 0x1c: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) ret = dev->spdif_chstatus; break; /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - ret = dev->si_cr | 0xff800000; + ret = dev->si_cr; + if (dev->type != AUDIOPCI_ES1370) + ret |= 0xff800000; break; /* DAC1 Channel Sample Count Register, Address 24H @@ -984,24 +1099,24 @@ es1371_inl(uint16_t port, void *priv) case 0x34: case 0x38: case 0x3c: - ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page); + ret = es137x_read_frame_reg(dev, port & 0x3c, dev->mem_page); break; default: break; } - audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret); + audiopci_log("es137x_inl: port=%04x ret=%08x\n", port, ret); return ret; } static void -es1371_outb(uint16_t port, uint8_t val, void *priv) +es137x_outb(uint16_t port, uint8_t val, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint32_t old_legacy_ctrl; - audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val); + audiopci_log("es137x_outb: port=%04x val=%02x\n", port, val); switch (port & 0x3f) { /* Interrupt/Chip Select Control Register, Address 00H @@ -1011,36 +1126,44 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) dev->dac[0].addr = dev->dac[0].addr_latch; dev->dac[0].buffer_pos = 0; dev->dac[0].buffer_pos_end = 0; - es1371_fetch(dev, 0); + dev->dac[0].prev_out_l = 0; + dev->dac[0].prev_out_r = 0; + es137x_fetch(dev, 0); } if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { dev->dac[1].addr = dev->dac[1].addr_latch; dev->dac[1].buffer_pos = 0; dev->dac[1].buffer_pos_end = 0; - es1371_fetch(dev, 1); + dev->dac[1].prev_out_l = 0; + dev->dac[1].prev_out_r = 0; + es137x_fetch(dev, 1); } + // audiopci_log("INTCTRL 0x%02X\n", val & 0xff); dev->int_ctrl = (dev->int_ctrl & 0xffffff00) | val; break; case 0x01: dev->int_ctrl = (dev->int_ctrl & 0xffff00ff) | (val << 8); + es1370_calc_sample_rate(dev); break; case 0x02: dev->int_ctrl = (dev->int_ctrl & 0xff00ffff) | (val << 16); + es1370_calc_sample_rate(dev); break; case 0x03: dev->int_ctrl = (dev->int_ctrl & 0x00ffffff) | (val << 24); gameport_remap(dev->gameport, 0x200 | ((val & 0x03) << 3)); + es1370_calc_sample_rate(dev); break; /* Interrupt/Chip Select Status Register, Address 04H Addressable as longword only, but PCem implements byte access, which must be for a reason */ case 0x06: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) dev->int_status = (dev->int_status & 0xff08ffff) | (val << 16); break; case 0x07: - if (dev->type >= AUDIOPCI_CT5880) + if (dev->type == AUDIOPCI_CT5880) dev->int_status = (dev->int_status & 0xd2ffffff) | (val << 24); break; @@ -1050,7 +1173,7 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) audiopci_log("MIDI data = %02x\n", val); /* TX does not use FIFO. */ midi_raw_out_byte(val); - es1371_set_tx_irq(dev, 1); + es137x_set_tx_irq(dev, 1); break; /* UART Control Register, Address 09H @@ -1061,15 +1184,15 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) if ((val & 0x03) == 0x03) { /* Reset TX */ - es1371_set_tx_irq(dev, 1); + es137x_set_tx_irq(dev, 1); /* Software reset */ - es1371_reset_fifo(dev); + es137x_reset_fifo(dev); } else { - es1371_set_tx_irq(dev, 1); + es137x_set_tx_irq(dev, 1); - es1371_update_tx_irq(dev); - es1371_update_rx_irq(dev); + es137x_update_tx_irq(dev); + es137x_update_rx_irq(dev); } break; @@ -1101,7 +1224,7 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) case 0x1b: old_legacy_ctrl = dev->legacy_ctrl; dev->legacy_ctrl = (dev->legacy_ctrl & 0x00ffffff) | (val << 24); - es1371_update_irqs(dev); + es137x_update_irqs(dev); update_legacy(dev, old_legacy_ctrl); break; @@ -1123,29 +1246,39 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - dev->si_cr = (dev->si_cr & 0xffffff00) | val; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xffff00) | val; + else + dev->si_cr = (dev->si_cr & 0xffffff00) | val; break; case 0x21: - dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xff00ff) | (val << 8); + else + dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); if (!(dev->si_cr & SI_P1_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC1; if (!(dev->si_cr & SI_P2_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(dev); + + es137x_update_irqs(dev); break; case 0x22: - dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16); + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xc0ffff) | ((val & 0x3f) << 16); + else + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 16); break; default: - audiopci_log("Bad es1371_outb: port=%04x val=%02x\n", port, val); + audiopci_log("Bad es137x_outb: port=%04x val=%02x\n", port, val); } } static void -es1371_outw(uint16_t port, uint16_t val, void *priv) +es137x_outw(uint16_t port, uint16_t val, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint32_t old_legacy_ctrl; switch (port & 0x3f) { @@ -1156,19 +1289,27 @@ es1371_outw(uint16_t port, uint16_t val, void *priv) dev->dac[0].addr = dev->dac[0].addr_latch; dev->dac[0].buffer_pos = 0; dev->dac[0].buffer_pos_end = 0; - es1371_fetch(dev, 0); + dev->dac[0].prev_out_l = 0; + dev->dac[0].prev_out_r = 0; + dev->step_synth = dev->interp_step_synth; + es137x_fetch(dev, 0); } if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { dev->dac[1].addr = dev->dac[1].addr_latch; dev->dac[1].buffer_pos = 0; dev->dac[1].buffer_pos_end = 0; - es1371_fetch(dev, 1); + dev->dac[1].prev_out_l = 0; + dev->dac[1].prev_out_r = 0; + dev->step_pcm = dev->interp_step; + es137x_fetch(dev, 1); } + // audiopci_log("INTCTRL 0x%02X\n", val & 0xff); dev->int_ctrl = (dev->int_ctrl & 0xffff0000) | val; break; case 0x02: dev->int_ctrl = (dev->int_ctrl & 0x0000ffff) | (val << 16); gameport_remap(dev->gameport, 0x200 | ((val & 0x0300) >> 5)); + es1370_calc_sample_rate(dev); break; /* Memory Page Register, Address 0CH @@ -1179,6 +1320,17 @@ es1371_outw(uint16_t port, uint16_t val, void *priv) case 0x0e: break; + /* CODEC Write Register, Address 10H + Addressable as word, longword */ + case 0x10: + if (dev->type != AUDIOPCI_ES1370) + break; + + dev->akm_codec.registers[(val >> 8) & 0xFF] = val & 0xFF; + if ((val >> 8) == 0x16 && !(val & 1)) + akm4531_reset(dev); + break; + /* Legacy Control/Status Register, Address 18H Addressable as byte, word, longword */ case 0x18: @@ -1187,7 +1339,7 @@ es1371_outw(uint16_t port, uint16_t val, void *priv) case 0x1a: old_legacy_ctrl = dev->legacy_ctrl; dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val << 16); - es1371_update_irqs(dev); + es137x_update_irqs(dev); update_legacy(dev, old_legacy_ctrl); break; @@ -1203,15 +1355,22 @@ es1371_outw(uint16_t port, uint16_t val, void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - dev->si_cr = (dev->si_cr & 0xffff0000) | val; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xff0000) | val; + else + dev->si_cr = (dev->si_cr & 0xffff0000) | val; + if (!(dev->si_cr & SI_P1_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC1; if (!(dev->si_cr & SI_P2_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(dev); + es137x_update_irqs(dev); break; case 0x22: - dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = (dev->si_cr & 0xc0ffff) | ((val & 0x3f) << 16); + else + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); break; /* DAC1 Channel Sample Count Register, Address 24H @@ -1238,40 +1397,57 @@ es1371_outw(uint16_t port, uint16_t val, void *priv) } static void -es1371_outl(uint16_t port, uint32_t val, void *priv) +es137x_outl(uint16_t port, uint32_t val, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint32_t old_legacy_ctrl; - audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val); + audiopci_log("es137x_outl: port=%04x val=%08x\n", port, val); switch (port & 0x3f) { /* Interrupt/Chip Select Control Register, Address 00H Addressable as byte, word, longword */ case 0x00: - if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { - dev->dac[0].addr = dev->dac[0].addr_latch; - dev->dac[0].buffer_pos = 0; - dev->dac[0].buffer_pos_end = 0; - es1371_fetch(dev, 0); - } - if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { - dev->dac[1].addr = dev->dac[1].addr_latch; - dev->dac[1].buffer_pos = 0; - dev->dac[1].buffer_pos_end = 0; - es1371_fetch(dev, 1); + { + uint8_t dac1start = 0; + uint8_t dac2start = 0; + + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + dev->dac[0].prev_out_l = 0; + dev->dac[0].prev_out_r = 0; + dac1start = 1; + es137x_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + dev->dac[1].prev_out_l = 0; + dev->dac[1].prev_out_r = 0; + dac2start = 1; + es137x_fetch(dev, 1); + } + // audiopci_log("INTCTRL 0x%02X\n", val & 0xff); + dev->int_ctrl = val; + gameport_remap(dev->gameport, 0x200 | ((val & 0x03000000) >> 21)); + es1370_calc_sample_rate(dev); + if (dac1start) + dev->step_synth = dev->interp_step_synth; + if (dac2start) + dev->step_pcm = dev->interp_step; + break; } - dev->int_ctrl = val; - gameport_remap(dev->gameport, 0x200 | ((val & 0x03000000) >> 21)); - break; /* Interrupt/Chip Select Status Register, Address 04H Addressable as longword only */ case 0x04: audiopci_log("[W] STATUS = %08X\n", val); - if (dev->type >= AUDIOPCI_CT5880) + if (dev->type == AUDIOPCI_CT5880) dev->int_status = (dev->int_status & 0xd208ffff) | (val & 0x2df70000); - else if (dev->type >= AUDIOPCI_ES1373) + else if (dev->type == AUDIOPCI_ES1373) dev->int_status = (dev->int_status & 0xff08ffff) | (val & 0x00f70000); break; @@ -1284,6 +1460,12 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) /* Sample Rate Converter Interface Register, Address 10H Addressable as longword only */ case 0x10: + if (dev->type == AUDIOPCI_ES1370) { + dev->akm_codec.registers[(val >> 8) & 0xFF] = val & 0xFF; + if ((val >> 8) == 0x16 && !(val & 1)) + akm4531_reset(dev); + break; + } dev->sr_cir = val & 0xfff8ffff; /*Bits 16 to 18 are undefined*/ if (dev->sr_cir & SRC_RAM_WE) { dev->sr_ram[dev->sr_cir >> 25] = val & 0xffff; @@ -1334,6 +1516,8 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) /* CODEC Write Register, Address 14H Addressable as longword only */ case 0x14: + if (dev->type == AUDIOPCI_ES1370) + break; if (val & CODEC_READ) { dev->codec_ctrl &= 0x00ff0000; dev->codec_ctrl |= ac97_codec_readw(dev->codec, val >> 16); @@ -1354,7 +1538,7 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) old_legacy_ctrl = dev->legacy_ctrl; dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val & 0xffff0000); dev->legacy_ctrl |= LEGACY_INT; - es1371_update_irqs(dev); + es137x_update_irqs(dev); update_legacy(dev, old_legacy_ctrl); break; @@ -1367,12 +1551,15 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: - dev->si_cr = (val & 0x007fffff) | 0xff800000; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = val & 0x3fffff; + else + dev->si_cr = (val & 0x007fffff) | 0xff800000; if (!(dev->si_cr & SI_P1_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC1; if (!(dev->si_cr & SI_P2_INTR_EN)) dev->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(dev); + es137x_update_irqs(dev); break; /* DAC1 Channel Sample Count Register, Address 24H @@ -1397,7 +1584,7 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) case 0x34: case 0x38: case 0x3c: - es1371_write_frame_reg(dev, port & 0x3c, dev->mem_page, val); + es137x_write_frame_reg(dev, port & 0x3c, dev->mem_page, val); break; default: @@ -1406,7 +1593,7 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) } static void -capture_event(es1371_t *dev, int type, int rw, uint16_t port) +capture_event(es137x_t *dev, int type, int rw, uint16_t port) { dev->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK); dev->legacy_ctrl |= type; @@ -1524,7 +1711,7 @@ capture_read_slave_dma(uint16_t port, void *priv) } static void -update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl) +update_legacy(es137x_t *dev, uint32_t old_legacy_ctrl) { if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE) { switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { @@ -1713,10 +1900,106 @@ update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl) } } +static uint8_t +es1370_pci_read(int func, int addr, void *priv) +{ + const es137x_t *dev = (es137x_t *) priv; + + if (func > 0) + return 0xff; + + if ((addr > 0x3f) && ((addr < 0xdc) || (addr > 0xe1))) + return 0x00; + + switch (addr) { + case 0x00: /* Vendor ID */ + return 0x74; /* Ensoniq */ + case 0x01: + return 0x12; + + case 0x02: /* Device ID */ + return dev->type >> 16; /* ES1370 */ + case 0x03: + return dev->type >> 24; + + case 0x04: /* Command TODO */ + return dev->pci_command; + case 0x05: + return dev->pci_serr; + + case 0x06: /* Status TODO */ + return 0x10; /* Supports ACPI */ + case 0x07: + return 0x00; + + case 0x08: /* Class Code & Revision ID */ + return dev->type >> 8; /* Revision ID - 0x00 is actual Ensoniq-branded ES1370 */ + case 0x09: + return 0x00; /* Multimedia audio device */ + case 0x0a: + return 0x01; + case 0x0b: + return 0x04; + +// case 0x0c: /* Cache Line Size TODO */ +// case 0x0d: /* Latency Timer TODO */ +// case 0x0e: /* Header Type TODO */ +// case 0x0f: /* BIST TODO */ + + case 0x10: /* Base Address TODO */ + return 0x01 | (dev->base_addr & 0xc0); /* memBaseAddr */ + case 0x11: + return dev->base_addr >> 8; + case 0x12: + return dev->base_addr >> 16; + case 0x13: + return dev->base_addr >> 24; + + case 0x2c ... 0x2f: + return dev->subsys_id[addr & 3]; /* Subsystem vendor ID */ + +#if 0 + case 0x34: // TODO + return 0xdc; /* Capabilites pointer */ +#endif + + case 0x3c: + return dev->int_line; + case 0x3d: + return 0x01; /* INTA */ + + case 0x3e: + return 0xc; /* Minimum grant */ + case 0x3f: + return 0x80; /* Maximum latency */ + +#if 0 + case 0xdc: + return 0x01; /* Capabilities identifier */ + case 0xdd: + return 0x00; /* Next item pointer */ + case 0xde: + return 0x31; /* Power management capabilities */ + case 0xdf: + return 0x6c; + + case 0xe0: + return dev->pmcsr & 0xff; + case 0xe1: + return dev->pmcsr >> 8; +#endif + + default: + break; + } + + return 0x00; +} + static uint8_t es1371_pci_read(int func, int addr, void *priv) { - const es1371_t *dev = (es1371_t *) priv; + const es137x_t *dev = (es137x_t *) priv; if (func > 0) return 0xff; @@ -1780,7 +2063,7 @@ es1371_pci_read(int func, int addr, void *priv) return 0x80; /* Maximum latency */ case 0x40: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) return dev->subsys_lock; break; @@ -1806,42 +2089,93 @@ es1371_pci_read(int func, int addr, void *priv) } static void -es1371_io_set(es1371_t *dev, int set) +es137x_io_set(es137x_t *dev, int set) { if (dev->pci_command & PCI_COMMAND_IO) { io_handler(set, dev->base_addr, 0x0040, - es1371_inb, es1371_inw, es1371_inl, - es1371_outb, es1371_outw, es1371_outl, dev); + es137x_inb, es137x_inw, es137x_inl, + es137x_outb, es137x_outw, es137x_outl, dev); + } +} + +static void +es1370_pci_write(int func, int addr, uint8_t val, void *priv) +{ + es137x_t *dev = (es137x_t *) priv; + + if (func) + return; + + switch (addr) { + case 0x04: + es137x_io_set(dev, 0); + dev->pci_command = val & 0x05; + es137x_io_set(dev, 1); + break; + case 0x05: + dev->pci_serr = val & 1; + break; + + case 0x10: + es137x_io_set(dev, 0); + dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0); + es137x_io_set(dev, 1); + break; + case 0x11: + es137x_io_set(dev, 0); + dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8); + es137x_io_set(dev, 1); + break; + case 0x12: + dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16); + break; + case 0x13: + dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24); + break; + + case 0x3c: + dev->int_line = val; + break; + + case 0xe0: + dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03); + break; + case 0xe1: + dev->pmcsr = (dev->pmcsr & 0x00ff) | ((val & 0x01) << 8); + break; + + default: + break; } } static void es1371_pci_write(int func, int addr, uint8_t val, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; if (func) return; switch (addr) { case 0x04: - es1371_io_set(dev, 0); + es137x_io_set(dev, 0); dev->pci_command = val & 0x05; - es1371_io_set(dev, 1); + es137x_io_set(dev, 1); break; case 0x05: dev->pci_serr = val & 1; break; case 0x10: - es1371_io_set(dev, 0); + es137x_io_set(dev, 0); dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0); - es1371_io_set(dev, 1); + es137x_io_set(dev, 1); break; case 0x11: - es1371_io_set(dev, 0); + es137x_io_set(dev, 0); dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8); - es1371_io_set(dev, 1); + es137x_io_set(dev, 1); break; case 0x12: dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16); @@ -1860,7 +2194,7 @@ es1371_pci_write(int func, int addr, uint8_t val, void *priv) break; case 0x40: - if (dev->type >= AUDIOPCI_ES1373) + if ((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) dev->subsys_lock = val; break; @@ -1877,7 +2211,7 @@ es1371_pci_write(int func, int addr, uint8_t val, void *priv) } static void -es1371_fetch(es1371_t *dev, int dac_nr) +es137x_fetch(es137x_t *dev, int dac_nr) { if (dev->si_cr & (dac_nr ? SI_P2_PAUSE : SI_P1_PAUSE)) return; @@ -1981,8 +2315,8 @@ low_fir_es1371(int dac_nr, int i, float NewSample) read_pos = (pos + 15) & (127 & ~15); n_coef = (16 - pos) & 15; - while (n_coef < ES1371_NCoef) { - out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; + while (n_coef < ES137x_NCoef) { + out += low_fir_es137x_coef[n_coef] * x[dac_nr][i][read_pos]; read_pos = (read_pos + 16) & (127 & ~15); n_coef += 16; } @@ -1997,13 +2331,13 @@ low_fir_es1371(int dac_nr, int i, float NewSample) } static void -es1371_next_sample_filtered(es1371_t *dev, int dac_nr, int out_idx) +es137x_next_sample_filtered(es137x_t *dev, int dac_nr, int out_idx) { int out_l; int out_r; if ((dev->dac[dac_nr].buffer_pos - dev->dac[dac_nr].buffer_pos_end) >= 0) - es1371_fetch(dev, dac_nr); + es137x_fetch(dev, dac_nr); out_l = dev->dac[dac_nr].buffer_l[dev->dac[dac_nr].buffer_pos & 63]; out_r = dev->dac[dac_nr].buffer_r[dev->dac[dac_nr].buffer_pos & 63]; @@ -2020,21 +2354,35 @@ es1371_next_sample_filtered(es1371_t *dev, int dac_nr, int out_idx) } static void -es1371_update(es1371_t *dev) +es137x_update(es137x_t *dev) { int32_t l; int32_t r; - l = (dev->dac[0].out_l * dev->dac[0].vol_l) >> 12; - l += ((dev->dac[1].out_l * dev->dac[1].vol_l) >> 12); - r = (dev->dac[0].out_r * dev->dac[0].vol_r) >> 12; - r += ((dev->dac[1].out_r * dev->dac[1].vol_r) >> 12); + if (dev->type == AUDIOPCI_ES1370) { + l = dev->dac[0].out_l * (((dev->akm_codec.registers[0x4] & 0x80) ? 0 : akm4531_gain_2dbstep_5bits[(dev->akm_codec.registers[0x4] & 0x1f)]) / 32767.0); + r = dev->dac[0].out_r * (((dev->akm_codec.registers[0x5] & 0x80) ? 0 : akm4531_gain_2dbstep_5bits[(dev->akm_codec.registers[0x5] & 0x1f)]) / 32767.0); + + l += dev->dac[1].out_l * (((dev->akm_codec.registers[0x2] & 0x80) ? 0 : akm4531_gain_2dbstep_5bits[(dev->akm_codec.registers[0x2] & 0x1f)]) / 32767.0); + r += dev->dac[1].out_r * (((dev->akm_codec.registers[0x3] & 0x80) ? 0 : akm4531_gain_2dbstep_5bits[(dev->akm_codec.registers[0x3] & 0x1f)]) / 32767.0); - l >>= 1; - r >>= 1; + l >>= 1; + r >>= 1; - l = (((l * dev->pcm_vol_l) >> 15) * dev->master_vol_l) >> 15; - r = (((r * dev->pcm_vol_r) >> 15) * dev->master_vol_r) >> 15; + l *= (((dev->akm_codec.registers[0x0] & 0x80) ? 0 : akm4531_att_2dbstep_5bits[(dev->akm_codec.registers[0x0] & 0x1f) ^ 0x1f]) / 32767.0); + r *= (((dev->akm_codec.registers[0x1] & 0x80) ? 0 : akm4531_att_2dbstep_5bits[(dev->akm_codec.registers[0x1] & 0x1f) ^ 0x1f]) / 32767.0); + } else { + l = (dev->dac[0].out_l * dev->dac[0].vol_l) >> 12; + l += ((dev->dac[1].out_l * dev->dac[1].vol_l) >> 12); + r = (dev->dac[0].out_r * dev->dac[0].vol_r) >> 12; + r += ((dev->dac[1].out_r * dev->dac[1].vol_r) >> 12); + + l >>= 1; + r >>= 1; + + l = (((l * dev->pcm_vol_l) >> 15) * dev->master_vol_l) >> 15; + r = (((r * dev->pcm_vol_r) >> 15) * dev->master_vol_r) >> 15; + } if (l < -32768) l = -32768; @@ -2045,16 +2393,16 @@ es1371_update(es1371_t *dev) else if (r > 32767) r = 32767; - for (; dev->pos < sound_pos_global; dev->pos++) { + for (; dev->pos < ((dev->type == AUDIOPCI_ES1370) ? wavetable_pos_global : sound_pos_global); dev->pos++) { dev->buffer[dev->pos * 2] = l; dev->buffer[dev->pos * 2 + 1] = r; } } static void -es1371_poll(void *priv) +es137x_poll(void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; int frac; int idx; int samp1_l; @@ -2064,21 +2412,41 @@ es1371_poll(void *priv) timer_advance_u64(&dev->dac[1].timer, dev->dac[1].latch); - es1371_scan_fifo(dev); + es137x_scan_fifo(dev); - es1371_update(dev); + es137x_update(dev); if (dev->int_ctrl & INT_DAC1_EN) { - if ((dev->type >= AUDIOPCI_ES1373) && (dev->int_ctrl & INT_DAC1_BYPASS)) { - /* SRC bypass. */ - if ((dev->dac[0].buffer_pos - dev->dac[0].buffer_pos_end) >= 0) - es1371_fetch(dev, 0); + if ((((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) && (dev->int_ctrl & INT_DAC1_BYPASS)) || (dev->type == AUDIOPCI_ES1370)) { + if ((dev->calc_sample_rate_synth != 44100) && (dev->type == AUDIOPCI_ES1370)) { + if ((dev->dac[0].buffer_pos - dev->dac[0].buffer_pos_end) >= 0 && dev->step_synth >= dev->interp_step_synth) + es137x_fetch(dev, 0); + + if (dev->step_synth >= dev->interp_step_synth) { + dev->step_synth = 0; + } + + dev->dac[0].out_l = lerp(dev->dac[0].prev_out_l, dev->dac[0].buffer_l[(dev->dac[0].buffer_pos) & 63], (dev->step_synth + 1) * dev->interp_factor_synth); + dev->dac[0].out_r = lerp(dev->dac[0].prev_out_r, dev->dac[0].buffer_r[(dev->dac[0].buffer_pos) & 63], (dev->step_synth + 1) * dev->interp_factor_synth); + + dev->step_synth++; + if (dev->step_synth >= dev->interp_step_synth) { + dev->dac[0].prev_out_l = dev->dac[0].out_l; + dev->dac[0].prev_out_r = dev->dac[0].out_r; + dev->dac[0].buffer_pos++; + goto dac0_count; + } + } else { + /* SRC bypass. */ + if ((dev->dac[0].buffer_pos - dev->dac[0].buffer_pos_end) >= 0) + es137x_fetch(dev, 0); - dev->dac[0].out_l = dev->dac[0].buffer_l[dev->dac[0].buffer_pos & 63]; - dev->dac[0].out_r = dev->dac[0].buffer_r[dev->dac[0].buffer_pos & 63]; - dev->dac[0].buffer_pos++; + dev->dac[0].out_l = dev->dac[0].buffer_l[dev->dac[0].buffer_pos & 63]; + dev->dac[0].out_r = dev->dac[0].buffer_r[dev->dac[0].buffer_pos & 63]; + dev->dac[0].buffer_pos++; - goto dac0_count; + goto dac0_count; + } } else { frac = dev->dac[0].ac & 0x7fff; idx = dev->dac[0].ac >> 15; @@ -2092,14 +2460,14 @@ es1371_poll(void *priv) dev->dac[0].ac += dev->dac[0].vf; dev->dac[0].ac &= ((32 << 15) - 1); if ((dev->dac[0].ac >> (15 + 4)) != dev->dac[0].f_pos) { - es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); + es137x_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; dac0_count: dev->dac[0].curr_samp_ct--; if (dev->dac[0].curr_samp_ct < 0) { dev->int_status |= INT_STATUS_DAC1; - es1371_update_irqs(dev); + es137x_update_irqs(dev); dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct; } } @@ -2107,16 +2475,36 @@ es1371_poll(void *priv) } if (dev->int_ctrl & INT_DAC2_EN) { - if ((dev->type >= AUDIOPCI_ES1373) && (dev->int_ctrl & INT_DAC2_BYPASS)) { - /* SRC bypass. */ - if ((dev->dac[1].buffer_pos - dev->dac[1].buffer_pos_end) >= 0) - es1371_fetch(dev, 1); + if ((((dev->type == AUDIOPCI_ES1373) || (dev->type == AUDIOPCI_CT5880)) && (dev->int_ctrl & INT_DAC2_BYPASS)) || (dev->type == AUDIOPCI_ES1370)) { + if ((dev->calc_sample_rate != 44100) && (dev->type == AUDIOPCI_ES1370)) { + if ((dev->dac[1].buffer_pos - dev->dac[1].buffer_pos_end) >= 0 && dev->step_pcm >= dev->interp_step) + es137x_fetch(dev, 1); + + if (dev->step_pcm >= dev->interp_step) { + dev->step_pcm = 0; + } + + dev->dac[1].out_l = lerp(dev->dac[1].prev_out_l, dev->dac[1].buffer_l[(dev->dac[1].buffer_pos) & 63], (dev->step_pcm + 1) * dev->interp_factor); + dev->dac[1].out_r = lerp(dev->dac[1].prev_out_r, dev->dac[1].buffer_r[(dev->dac[1].buffer_pos) & 63], (dev->step_pcm + 1) * dev->interp_factor); + + dev->step_pcm++; + if (dev->step_pcm >= dev->interp_step) { + dev->dac[1].prev_out_l = dev->dac[1].out_l; + dev->dac[1].prev_out_r = dev->dac[1].out_r; + dev->dac[1].buffer_pos++; + goto dac1_count; + } + } else { + /* SRC bypass. */ + if ((dev->dac[1].buffer_pos - dev->dac[1].buffer_pos_end) >= 0) + es137x_fetch(dev, 1); - dev->dac[1].out_l = dev->dac[1].buffer_l[dev->dac[1].buffer_pos & 63]; - dev->dac[1].out_r = dev->dac[1].buffer_r[dev->dac[1].buffer_pos & 63]; - dev->dac[1].buffer_pos++; + dev->dac[1].out_l = dev->dac[1].buffer_l[dev->dac[1].buffer_pos & 63]; + dev->dac[1].out_r = dev->dac[1].buffer_r[dev->dac[1].buffer_pos & 63]; + dev->dac[1].buffer_pos++; - goto dac1_count; + goto dac1_count; + } } else { frac = dev->dac[1].ac & 0x7fff; idx = dev->dac[1].ac >> 15; @@ -2130,14 +2518,14 @@ es1371_poll(void *priv) dev->dac[1].ac += dev->dac[1].vf; dev->dac[1].ac &= ((32 << 15) - 1); if ((dev->dac[1].ac >> (15 + 4)) != dev->dac[1].f_pos) { - es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); + es137x_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; dac1_count: dev->dac[1].curr_samp_ct--; if (dev->dac[1].curr_samp_ct < 0) { dev->int_status |= INT_STATUS_DAC2; - es1371_update_irqs(dev); + es137x_update_irqs(dev); dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct; } } @@ -2146,11 +2534,11 @@ es1371_poll(void *priv) } static void -es1371_get_buffer(int32_t *buffer, int len, void *priv) +es137x_get_buffer(int32_t *buffer, int len, void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; - es1371_update(dev); + es137x_update(dev); for (int c = 0; c < len * 2; c++) buffer[c] += (dev->buffer[c] / 2); @@ -2158,10 +2546,22 @@ es1371_get_buffer(int32_t *buffer, int len, void *priv) dev->pos = 0; } +static void +es1370_filter_cd_audio(int channel, double *buffer, void *priv) +{ + const es137x_t *dev = (es137x_t *) priv; + double c = 0.0; + double mastervol = ((dev->akm_codec.registers[channel] & 0x80) ? 0 : akm4531_att_2dbstep_5bits[(dev->akm_codec.registers[channel] & 0x1f) ^ 0x1f]) / 32767.0; + double cdvol = ((dev->akm_codec.registers[channel + 0x6] & 0x80) ? 0 : akm4531_gain_2dbstep_5bits[(dev->akm_codec.registers[channel + 0x6] & 0x1f)]) / 32767.0; + + c = *buffer * mastervol * cdvol; + *buffer = c; +} + static void es1371_filter_cd_audio(int channel, double *buffer, void *priv) { - const es1371_t *dev = (es1371_t *) priv; + const es137x_t *dev = (es137x_t *) priv; double c; int cd = channel ? dev->cd_vol_r : dev->cd_vol_l; int master = channel ? dev->master_vol_r : dev->master_vol_l; @@ -2177,49 +2577,49 @@ sinc(double x) } static void -generate_es1371_filter(void) +generate_es137x_filter(void) { /* Cutoff frequency = 1 / 32 */ float fC = 1.0 / 32.0; float gain; int n; - for (n = 0; n < ES1371_NCoef; n++) { + for (n = 0; n < ES137x_NCoef; n++) { /* Blackman window */ - double w = 0.42 - (0.5 * cos((2.0 * n * M_PI) / (double) (ES1371_NCoef - 1))) + (0.08 * cos((4.0 * n * M_PI) / (double) (ES1371_NCoef - 1))); + double w = 0.42 - (0.5 * cos((2.0 * n * M_PI) / (double) (ES137x_NCoef - 1))) + (0.08 * cos((4.0 * n * M_PI) / (double) (ES137x_NCoef - 1))); /* Sinc filter */ - double h = sinc(2.0 * fC * ((double) n - ((double) (ES1371_NCoef - 1) / 2.0))); + double h = sinc(2.0 * fC * ((double) n - ((double) (ES137x_NCoef - 1) / 2.0))); /* Create windowed-sinc filter */ - low_fir_es1371_coef[n] = w * h; + low_fir_es137x_coef[n] = w * h; } - low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0; + low_fir_es137x_coef[(ES137x_NCoef - 1) / 2] = 1.0; gain = 0.0; - for (n = 0; n < ES1371_NCoef; n++) - gain += low_fir_es1371_coef[n] / (float) N; + for (n = 0; n < ES137x_NCoef; n++) + gain += low_fir_es137x_coef[n] / (float) N; gain /= 0.65; /* Normalise filter, to produce unity gain */ - for (n = 0; n < ES1371_NCoef; n++) - low_fir_es1371_coef[n] /= gain; + for (n = 0; n < ES137x_NCoef; n++) + low_fir_es137x_coef[n] /= gain; } static void -es1371_input_msg(void *priv, uint8_t *msg, uint32_t len) +es137x_input_msg(void *priv, uint8_t *msg, uint32_t len) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; for (uint32_t i = 0; i < len; i++) - es1371_write_fifo(dev, msg[i]); + es137x_write_fifo(dev, msg[i]); } static int -es1371_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) +es137x_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; uint32_t i = -1; audiopci_log("Abort = %i\n", abort); @@ -2229,7 +2629,7 @@ es1371_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) if (!abort) { for (i = 0; i < len; i++) { - es1371_write_fifo(dev, buffer[i]); + es137x_write_fifo(dev, buffer[i]); if (dev->uart_status & UART_STATUS_RXRDY) break; } @@ -2240,17 +2640,63 @@ es1371_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort) return 7 - i; } +static void es137x_speed_changed(void *priv); + +static void * +es1370_init(const device_t *info) +{ + es137x_t *dev = malloc(sizeof(es137x_t)); + memset(dev, 0x00, sizeof(es137x_t)); + dev->type = info->local; + + if (device_get_config_int("receive_input")) + midi_in_handler(1, es137x_input_msg, es137x_input_sysex, dev); + + wavetable_add_handler(es137x_get_buffer, dev); + sound_set_cd_audio_filter(es1370_filter_cd_audio, dev); + + dev->gameport = gameport_add(&gameport_pnp_device); + gameport_remap(dev->gameport, 0x200); + + pci_add_card((info->local & 1) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1370_pci_read, es1370_pci_write, dev, &dev->pci_slot); + + timer_add(&dev->dac[1].timer, es137x_poll, dev, 1); + + generate_es137x_filter(); + + dev->dac[0].vol_l = 1 << 12; + dev->dac[0].vol_r = 1 << 12; + dev->dac[1].vol_l = 1 << 12; + dev->dac[1].vol_r = 1 << 12; + + dev->pcm_vol_l = 1 << 15; + dev->pcm_vol_r = 1 << 15; + dev->master_vol_l = 1 << 15; + dev->master_vol_r = 1 << 15; + + es137x_reset(dev); + + es137x_speed_changed(dev); + + for (int i = 0; i < 0x20; i++) { + double attn = (12.0 - (i * 2.0)); + akm4531_gain_2dbstep_5bits[i] = pow(10, attn / 10.) * 32767.0; + } + + return dev; +} + static void * es1371_init(const device_t *info) { - es1371_t *dev = malloc(sizeof(es1371_t)); - memset(dev, 0x00, sizeof(es1371_t)); + es137x_t *dev = malloc(sizeof(es137x_t)); + memset(dev, 0x00, sizeof(es137x_t)); dev->type = info->local & 0xffffff00; if (device_get_config_int("receive_input")) - midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev); + midi_in_handler(1, es137x_input_msg, es137x_input_sysex, dev); - sound_add_handler(es1371_get_buffer, dev); + sound_add_handler(es137x_get_buffer, dev); sound_set_cd_audio_filter(es1371_filter_cd_audio, dev); dev->gameport = gameport_add(&gameport_pnp_device); @@ -2258,9 +2704,9 @@ es1371_init(const device_t *info) pci_add_card((info->local & 1) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev, &dev->pci_slot); - timer_add(&dev->dac[1].timer, es1371_poll, dev, 1); + timer_add(&dev->dac[1].timer, es137x_poll, dev, 1); - generate_es1371_filter(); + generate_es137x_filter(); ac97_codec = &dev->codec; ac97_codec_count = 1; @@ -2269,29 +2715,42 @@ es1371_init(const device_t *info) if (!(info->local & 1)) device_add(ac97_codec_get(device_get_config_int("codec"))); - es1371_reset(dev); + es137x_reset(dev); return dev; } static void -es1371_close(void *priv) +es137x_close(void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; free(dev); } static void -es1371_speed_changed(void *priv) +es137x_speed_changed(void *priv) { - es1371_t *dev = (es1371_t *) priv; + es137x_t *dev = (es137x_t *) priv; - dev->dac[1].latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) SOUND_FREQ)); + dev->dac[1].latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ((dev->type == AUDIOPCI_ES1370) ? WT_FREQ : SOUND_FREQ))); } +static const device_config_t es1370_config[] = { + // clang-format off + { + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + static const device_config_t es1371_config[] = { - // clang-format off + // clang-format off { .name = "codec", .description = "Codec", @@ -2317,11 +2776,11 @@ static const device_config_t es1371_config[] = { .default_int = 1 }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t es1373_config[] = { - // clang-format off + // clang-format off { .name = "codec", .description = "Codec", @@ -2351,11 +2810,11 @@ static const device_config_t es1373_config[] = { .default_int = 1 }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t ct5880_config[] = { - // clang-format off + // clang-format off { .name = "codec", .description = "Codec", @@ -2369,6 +2828,10 @@ static const device_config_t ct5880_config[] = { .description = "SigmaTel STAC9721T (stereo)", .value = AC97_CODEC_STAC9721 }, + { + .description = "TriTech TR28023 / Creative CT1297", + .value = AC97_CODEC_TR28023 + }, { .description = "" } }, .default_int = AC97_CODEC_STAC9708 @@ -2381,11 +2844,11 @@ static const device_config_t ct5880_config[] = { .default_int = 1 }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t es1371_onboard_config[] = { - // clang-format off + // clang-format off { .name = "receive_input", .description = "Receive MIDI input", @@ -2394,7 +2857,21 @@ static const device_config_t es1371_onboard_config[] = { .default_int = 1 }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on +}; + +const device_t es1370_device = { + .name = "Ensoniq AudioPCI (ES1370)", + .internal_name = "es1370", + .flags = DEVICE_PCI, + .local = AUDIOPCI_ES1370, + .init = es1370_init, + .close = es137x_close, + .reset = es137x_reset, + .available = NULL, + .speed_changed = es137x_speed_changed, + .force_redraw = NULL, + .config = es1370_config }; const device_t es1371_device = { @@ -2403,10 +2880,10 @@ const device_t es1371_device = { .flags = DEVICE_PCI, .local = AUDIOPCI_ES1371, .init = es1371_init, - .close = es1371_close, - .reset = es1371_reset, + .close = es137x_close, + .reset = es137x_reset, .available = NULL, - .speed_changed = es1371_speed_changed, + .speed_changed = es137x_speed_changed, .force_redraw = NULL, .config = es1371_config }; @@ -2417,10 +2894,10 @@ const device_t es1371_onboard_device = { .flags = DEVICE_PCI, .local = AUDIOPCI_ES1371 | 1, .init = es1371_init, - .close = es1371_close, - .reset = es1371_reset, + .close = es137x_close, + .reset = es137x_reset, .available = NULL, - .speed_changed = es1371_speed_changed, + .speed_changed = es137x_speed_changed, .force_redraw = NULL, .config = es1371_onboard_config }; @@ -2431,10 +2908,10 @@ const device_t es1373_device = { .flags = DEVICE_PCI, .local = AUDIOPCI_ES1373, .init = es1371_init, - .close = es1371_close, - .reset = es1371_reset, + .close = es137x_close, + .reset = es137x_reset, .available = NULL, - .speed_changed = es1371_speed_changed, + .speed_changed = es137x_speed_changed, .force_redraw = NULL, .config = es1373_config }; @@ -2445,10 +2922,10 @@ const device_t es1373_onboard_device = { .flags = DEVICE_PCI, .local = AUDIOPCI_ES1373 | 1, .init = es1371_init, - .close = es1371_close, - .reset = es1371_reset, + .close = es137x_close, + .reset = es137x_reset, .available = NULL, - .speed_changed = es1371_speed_changed, + .speed_changed = es137x_speed_changed, .force_redraw = NULL, .config = es1371_onboard_config }; @@ -2459,10 +2936,10 @@ const device_t ct5880_device = { .flags = DEVICE_PCI, .local = AUDIOPCI_CT5880, .init = es1371_init, - .close = es1371_close, - .reset = es1371_reset, + .close = es137x_close, + .reset = es137x_reset, .available = NULL, - .speed_changed = es1371_speed_changed, + .speed_changed = es137x_speed_changed, .force_redraw = NULL, .config = ct5880_config }; @@ -2473,10 +2950,10 @@ const device_t ct5880_onboard_device = { .flags = DEVICE_PCI, .local = AUDIOPCI_CT5880 | 1, .init = es1371_init, - .close = es1371_close, - .reset = es1371_reset, + .close = es137x_close, + .reset = es137x_reset, .available = NULL, - .speed_changed = es1371_speed_changed, + .speed_changed = es137x_speed_changed, .force_redraw = NULL, .config = es1371_onboard_config }; diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index a3a763244a..cf05203f3e 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1238,7 +1238,7 @@ azt_init(const device_t *info) fm_driver_get(FM_YMF262, &azt2316a->sb->opl); sb_dsp_set_real_opl(&azt2316a->sb->dsp, 1); - sb_dsp_init(&azt2316a->sb->dsp, SBPRO2, azt2316a->type, azt2316a); + sb_dsp_init(&azt2316a->sb->dsp, SBPRO2_DSP_302, azt2316a->type, azt2316a); sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr); sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq); sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma); diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index 8ba344ec9b..833124bb2c 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -497,7 +497,7 @@ cmi8x38_sb_mixer_write(uint16_t addr, uint8_t val, void *priv) /* Set TDMA channels if auto-detection is enabled. */ if ((dev->io_regs[0x27] & 0x01) && (mixer->index == 0x81)) { dev->tdma_8 = dev->sb->dsp.sb_8_dmanum; - if (dev->sb->dsp.sb_type >= SB16) + if (dev->sb->dsp.sb_type >= SB16_DSP_404) dev->tdma_16 = dev->sb->dsp.sb_16_dmanum; } } else { @@ -879,7 +879,7 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) dev->sb->dsp.sbleftright_default = !!(val & 0x02); /* Enable or disable SB16 mode. */ - dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2 : SB16; + dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2_DSP_302 : SB16_DSP_405; break; case 0x22: diff --git a/src/sound/snd_optimc.c b/src/sound/snd_optimc.c index 9c8b0b460c..d69986d98f 100644 --- a/src/sound/snd_optimc.c +++ b/src/sound/snd_optimc.c @@ -394,7 +394,7 @@ optimc_init(const device_t *info) optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262; sb_dsp_set_real_opl(&optimc->sb->dsp, optimc->fm_type != FM_YMF278B); - sb_dsp_init(&optimc->sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, optimc); + sb_dsp_init(&optimc->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, optimc); sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr); sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq); sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma); diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index f9bab8d87f..fab2a6a752 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -2314,7 +2314,7 @@ pas16_init(const device_t *info) pas16->has_scsi = (!pas16->type) || (pas16->type == 0x0f); fm_driver_get(FM_YMF262, &pas16->opl); sb_dsp_set_real_opl(&pas16->dsp, 1); - sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16); + sb_dsp_init(&pas16->dsp, SB_DSP_201, SB_SUBTYPE_DEFAULT, pas16); pas16->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(pas16->mpu, 0, sizeof(mpu_t)); mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index df0547fdc6..016e50c40f 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1,23 +1,21 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. * - * This file is part of the 86Box distribution. + * This file is part of the 86Box distribution. * - * Sound Blaster emulation. + * Sound Blaster emulation. * + * Authors: Sarah Walker, + * Miran Grca, + * TheCollector1995, + * Jasmine Iwanek, * - * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, - * Jasmine Iwanek, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2024 Jasmine Iwanek. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2024-2025 Jasmine Iwanek. */ #include #include @@ -45,6 +43,10 @@ #include <86box/snd_sb.h> #include <86box/plat_unused.h> +#define SB_1 0 +#define SB_15 1 +#define SB_2 2 + #define SB_16_PNP_NOIDE 0 #define SB_16_PNP_IDE 1 @@ -64,6 +66,7 @@ #define PNP_ROM_SB_VIBRA16C "roms/sound/creative/CT4180 PnP.BIN" #define PNP_ROM_SB_VIBRA16CL "roms/sound/creative/CT4100 PnP.BIN" #define PNP_ROM_SB_VIBRA16XV "roms/sound/creative/CT4170 PnP.BIN" +#define PNP_ROM_SB_GOLDFINCH "roms/sound/creative/CT1920 PnP.BIN" #define PNP_ROM_SB_32_PNP "roms/sound/creative/CT3600 PnP.BIN" #define PNP_ROM_SB_AWE32_PNP "roms/sound/creative/CT3980 PnP.BIN" #define PNP_ROM_SB_AWE64_VALUE "roms/sound/creative/CT4520 PnP.BIN" @@ -145,8 +148,8 @@ sb_log(const char *fmt, ...) static void sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) { - sb_t *sb = (sb_t *) priv; - const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + sb_t *sb = (sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; double out_mono; sb_dsp_update(&sb->dsp); @@ -155,8 +158,8 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) cms_update(&sb->cms); for (int c = 0; c < len * 2; c += 2) { - double out_l = 0.0; - double out_r = 0.0; + double out_l = 0.0; + double out_r = 0.0; if (sb->cms_enabled) { out_l += sb->cms.buffer[c]; @@ -196,15 +199,15 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *priv) static void sb_get_music_buffer_sb2(int32_t *buffer, int len, void *priv) { - const sb_t *sb = (const sb_t *) priv; - const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - const int32_t *opl_buf = NULL; + const sb_t *sb = (const sb_t *) priv; + const sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + const int32_t *opl_buf = NULL; opl_buf = sb->opl.update(sb->opl.priv); for (int c = 0; c < len * 2; c += 2) { - double out_l = 0.0; - double out_r = 0.0; + double out_l = 0.0; + double out_r = 0.0; const double out_mono = ((double) opl_buf[c]) * 0.7171630859375; @@ -289,7 +292,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) if (!sb->opl_enabled) return; - if (sb->dsp.sb_type == SBPRO) { + if (sb->dsp.sb_type == SBPRO_DSP_300) { opl_buf = sb->opl.update(sb->opl.priv); opl2_buf = sb->opl2.update(sb->opl2.priv); } else @@ -301,7 +304,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) out_l = 0.0; out_r = 0.0; - if (sb->dsp.sb_type == SBPRO) { + if (sb->dsp.sb_type == SBPRO_DSP_300) { /* Two chips for LEFT and RIGHT channels. Each chip stores data into the LEFT channel only (no sample alternating.) */ out_l = (((double) opl_buf[c]) * mixer->fm_l) * 0.7171630859375; @@ -323,7 +326,7 @@ sb_get_music_buffer_sbpro(int32_t *buffer, int len, void *priv) } sb->opl.reset_buffer(sb->opl.priv); - if (sb->dsp.sb_type == SBPRO) + if (sb->dsp.sb_type == SBPRO_DSP_300) sb->opl2.reset_buffer(sb->opl2.priv); } @@ -342,8 +345,8 @@ sbpro_filter_cd_audio(int channel, double *buffer, void *priv) static void sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *priv) { - sb_t *sb = (sb_t *) priv; - const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; double bass_treble; sb_dsp_update(&sb->dsp); @@ -509,11 +512,32 @@ sb_get_music_buffer_sb16_awe32(int32_t *buffer, const int len, void *priv) sb->opl.reset_buffer(sb->opl.priv); } +static void +sb_get_wavetable_buffer_goldfinch(int32_t *buffer, const int len, void *priv) +{ + goldfinch_t *goldfinch = (goldfinch_t *) priv; + + emu8k_update(&goldfinch->emu8k); + + for (int c = 0; c < len * 2; c += 2) { + double out_l = 0.0; + double out_r = 0.0; + + out_l += ((double) goldfinch->emu8k.buffer[c]); + out_r += ((double) goldfinch->emu8k.buffer[c + 1]); + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + goldfinch->emu8k.pos = 0; +} + static void sb_get_wavetable_buffer_sb16_awe32(int32_t *buffer, const int len, void *priv) { - sb_t *sb = (sb_t *) priv; - const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + sb_t *sb = (sb_t *) priv; + const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; double bass_treble; emu8k_update(&sb->emu8k); @@ -1137,7 +1161,7 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0xff: - if ((sb->dsp.sb_type > SBAWE32) && !sb->dsp.sb_16_dma_supported) { + if ((sb->dsp.sb_type > SBAWE32_DSP_412) && !sb->dsp.sb_16_dma_supported) { /* Bit 5: High DMA channel enabled (0 = yes, 1 = no); Bit 2: ????; @@ -1194,7 +1218,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) { const sb_t *sb = (sb_t *) priv; const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - uint8_t ret = 0xff; + uint8_t ret = 0xff; sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); @@ -1321,10 +1345,10 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) /* http://the.earth.li/~tfm/oldpage/sb_mixer.html - 0x10, 0x20, 0x80. */ const uint8_t temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | ((sb->dsp.sb_irq401) ? 4 : 0); - if (sb->dsp.sb_type >= SBAWE32) - ret = temp | 0x80; + if (sb->dsp.sb_type >= SBAWE32_DSP_412) + ret = temp | 0x80; else - ret = temp | 0x40; + ret = temp | 0x40; break; case 0x83: @@ -1350,23 +1374,23 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) ret |= 0x01; break; - case 0x49: /* Undocumented register used by some Creative drivers. */ - case 0x4a: /* Undocumented register used by some Creative drivers. */ - case 0x8c: /* Undocumented register used by some Creative drivers. */ - case 0x8e: /* Undocumented register used by some Creative drivers. */ - case 0x90: /* 3D Enhancement switch. */ - case 0xfd: /* Undocumented register used by some Creative drivers. */ - case 0xfe: /* Undocumented register used by some Creative drivers. */ + case 0x49: /* Undocumented register used by some Creative drivers. */ + case 0x4a: /* Undocumented register used by some Creative drivers. */ + case 0x8c: /* Undocumented register used by some Creative drivers. */ + case 0x8e: /* Undocumented register used by some Creative drivers. */ + case 0x90: /* 3D Enhancement switch. */ + case 0xfd: /* Undocumented register used by some Creative drivers. */ + case 0xfe: /* Undocumented register used by some Creative drivers. */ ret = mixer->regs[mixer->index]; break; - case 0xff: /* Undocumented register used by some Creative drivers. - This and the upper bits of 0x82 seem to affect the - playback volume: - - Register FF = FF: Volume playback normal. - - Register FF = Not FF: Volume playback low unless - bit 6 of 82h is set. */ - if (sb->dsp.sb_type > SBAWE32) + case 0xff: /* Undocumented register used by some Creative drivers. + This and the upper bits of 0x82 seem to affect the + playback volume: + - Register FF = FF: Volume playback normal. + - Register FF = Not FF: Volume playback low unless + bit 6 of 82h is set. */ + if (sb->dsp.sb_type > SBAWE32_DSP_412) ret = mixer->regs[mixer->index]; break; @@ -1395,7 +1419,7 @@ sb_ct1745_mixer_reset(sb_t *sb) static void ess_base_write(uint16_t addr, uint8_t val, void *priv) { - sb_t * ess = (sb_t *) priv; + sb_t *ess = (sb_t *) priv; switch (addr & 0x000f) { case 0x0002: @@ -1414,7 +1438,7 @@ ess_base_write(uint16_t addr, uint8_t val, void *priv) static uint8_t ess_base_read(uint16_t addr, void *priv) { - sb_t * ess = (sb_t *) priv; + sb_t *ess = (sb_t *) priv; switch (addr & 0x000f) { case 0x0002: @@ -1441,7 +1465,7 @@ ess_base_read(uint16_t addr, void *priv) static void ess_fm_midi_write(uint16_t addr, uint8_t val, void *priv) { - sb_t * ess = (sb_t *) priv; + sb_t *ess = (sb_t *) priv; ess->dsp.activity &= 0x7f; } @@ -1449,7 +1473,7 @@ ess_fm_midi_write(uint16_t addr, uint8_t val, void *priv) static uint8_t ess_fm_midi_read(uint16_t addr, void *priv) { - sb_t * ess = (sb_t *) priv; + sb_t *ess = (sb_t *) priv; ess->dsp.activity &= 0x7f; @@ -1527,8 +1551,8 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0x0E: - mixer->output_filter = !(mixer->regs[0xE] & 0x20); - mixer->stereo = mixer->regs[0xE] & 2; + mixer->output_filter = !(mixer->regs[0xE] & 0x20); + mixer->stereo = mixer->regs[0xE] & 2; sb_dsp_set_stereo(&ess->dsp, val & 2); break; @@ -1565,12 +1589,18 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) /* More compatibility: SoundBlaster Pro selects register 020h for 030h, 022h for 032h, 026h for 036h, and 028h for 038h. */ - case 0x30: case 0x32: case 0x36: case 0x38: + case 0x30: + case 0x32: + case 0x36: + case 0x38: case 0x3e: mixer->regs[mixer->index - 0x10] = (val & 0xee); break; - case 0x00: case 0x04: case 0x3a: case 0x3c: + case 0x00: + case 0x04: + case 0x3a: + case 0x3c: break; case 0x64: @@ -1604,43 +1634,44 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) } } - if (ess->mpu != NULL) switch ((mixer->regs[0x40] >> 5) & 0x7) { - default: - break; - case 0: - mpu401_base_addr = 0x0000; - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, -1); - break; - case 1: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, -1); - break; - case 2: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, ess->dsp.sb_irqnum); - break; - case 3: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, 11); - break; - case 4: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, 9); - break; - case 5: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, 5); - break; - case 6: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, 7); - break; - case 7: - mpu401_change_addr(ess->mpu, mpu401_base_addr); - mpu401_setirq(ess->mpu, 10); - break; - } + if (ess->mpu != NULL) + switch ((mixer->regs[0x40] >> 5) & 0x7) { + default: + break; + case 0: + mpu401_base_addr = 0x0000; + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, -1); + break; + case 1: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, -1); + break; + case 2: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, ess->dsp.sb_irqnum); + break; + case 3: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 11); + break; + case 4: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 9); + break; + case 5: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 5); + break; + case 6: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 7); + break; + case 7: + mpu401_change_addr(ess->mpu, mpu401_base_addr); + mpu401_setirq(ess->mpu, 10); + break; + } ess->midi_addr = mpu401_base_addr; io_sethandler(addr, 0x0002, ess_fm_midi_read, NULL, NULL, @@ -1675,85 +1706,86 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) uint8_t ess_mixer_read(uint16_t addr, void *priv) { - const sb_t * ess = (sb_t *) priv; + const sb_t *ess = (sb_t *) priv; const ess_mixer_t *mixer = &ess->mixer_ess; uint8_t ret = 0x0a; if (!(addr & 1)) ret = mixer->index; - else switch (mixer->index) { - case 0x00: - case 0x0a: - case 0x0c: - case 0x0e: - case 0x14: - case 0x1a: - case 0x02: - case 0x06: - case 0x30: - case 0x32: - case 0x36: - case 0x38: - case 0x3e: - ret = mixer->regs[mixer->index]; - break; + else + switch (mixer->index) { + case 0x00: + case 0x0a: + case 0x0c: + case 0x0e: + case 0x14: + case 0x1a: + case 0x02: + case 0x06: + case 0x30: + case 0x32: + case 0x36: + case 0x38: + case 0x3e: + ret = mixer->regs[mixer->index]; + break; - case 0x04: - case 0x22: - case 0x26: - case 0x28: - case 0x2e: - ret = mixer->regs[mixer->index] | 0x11; - break; + case 0x04: + case 0x22: + case 0x26: + case 0x28: + case 0x2e: + ret = mixer->regs[mixer->index] | 0x11; + break; - /* Bit 1 always set, bits 7-6 always clear on both the real ES688 and ES1688. */ - case 0x1c: - ret = mixer->regs[mixer->index] | 0x10; - break; + /* Bit 1 always set, bits 7-6 always clear on both the real ES688 and ES1688. */ + case 0x1c: + ret = mixer->regs[mixer->index] | 0x10; + break; - /* - Real ES688: Always 0x00; - Real ES1688: Bit 2 always clear. - */ - case 0x40: - if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) - ret = mixer->regs[mixer->index]; - else if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) - ret = mixer->regs[mixer->index] & 0xfb; - else - ret = 0x00; - break; + /* + Real ES688: Always 0x00; + Real ES1688: Bit 2 always clear. + */ + case 0x40: + if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index]; + else if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index] & 0xfb; + else + ret = 0x00; + break; - /* - Real ES688: Always 0x00; - Real ES1688: All bits writable. - */ - case 0x48: - if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) - ret = mixer->regs[mixer->index]; - else - ret = 0x00; - break; + /* + Real ES688: Always 0x00; + Real ES1688: All bits writable. + */ + case 0x48: + if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index]; + else + ret = 0x00; + break; - /* - Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788. - Bit 3 set and writable: ESSCFG detects the card as ES1788 if register 70h is read-only, - otherwise, as ES1887. - Bit 3 set and read-only: ESSCFG detects the card as ES1788 if register 70h is read-only, - otherwise, as ES1888. - Real ES688 and ES1688: Always 0x00. - */ - case 0x64: - if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) - ret = (mixer->regs[mixer->index] & 0xf7) | 0x20; - else - ret = 0x00; - break; + /* + Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788. + Bit 3 set and writable: ESSCFG detects the card as ES1788 if register 70h is read-only, + otherwise, as ES1887. + Bit 3 set and read-only: ESSCFG detects the card as ES1788 if register 70h is read-only, + otherwise, as ES1888. + Real ES688 and ES1688: Always 0x00. + */ + case 0x64: + if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) + ret = (mixer->regs[mixer->index] & 0xf7) | 0x20; + else + ret = 0x00; + break; - default: - sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } + default: + sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } sb_log("[%04X:%08X] [R] %04X = %02X (%02X)\n", CS, cpu_state.pc, addr, ret, mixer->index); @@ -1780,8 +1812,8 @@ sb_mcv_read(int port, void *priv) void sb_mcv_write(int port, uint8_t val, void *priv) { - uint16_t addr; - sb_t *sb = (sb_t *) priv; + uint16_t addr = 0; + sb_t *sb = (sb_t *) priv; if (port < 0x102) return; @@ -1833,8 +1865,8 @@ sb_mcv_feedb(void *priv) static uint8_t sb_pro_mcv_read(int port, void *priv) { - const sb_t *sb = (sb_t *) priv; - uint8_t ret = sb->pos_regs[port & 7]; + const sb_t *sb = (sb_t *) priv; + uint8_t ret = sb->pos_regs[port & 7]; sb_log("sb_pro_mcv_read: port=%04x ret=%02x\n", port, ret); @@ -1844,8 +1876,8 @@ sb_pro_mcv_read(int port, void *priv) static void sb_pro_mcv_write(int port, uint8_t val, void *priv) { - uint16_t addr; - sb_t *sb = (sb_t *) priv; + uint16_t addr = 0; + sb_t *sb = (sb_t *) priv; if (port < 0x102) return; @@ -1904,8 +1936,8 @@ sb_pro_mcv_write(int port, uint8_t val, void *priv) static uint8_t sb_16_reply_mca_read(int port, void *priv) { - const sb_t *sb = (sb_t *) priv; - uint8_t ret = sb->pos_regs[port & 7]; + const sb_t *sb = (sb_t *) priv; + uint8_t ret = sb->pos_regs[port & 7]; sb_log("sb_16_reply_mca_read: port=%04x ret=%02x\n", port, ret); @@ -1915,8 +1947,8 @@ sb_16_reply_mca_read(int port, void *priv) static void sb_16_reply_mca_write(const int port, const uint8_t val, void *priv) { - uint16_t addr; - sb_t *sb = (sb_t *) priv; + uint16_t addr = 0; + sb_t *sb = (sb_t *) priv; if (port < 0x102) return; @@ -2132,7 +2164,7 @@ sb_16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void mpu401_change_addr(sb->mpu, 0); if (config->activate) { - uint8_t val = config->irq[0].irq; + uint8_t val = config->irq[0].irq; addr = config->io[0].base; if (addr != ISAPNP_IO_DISABLED) { @@ -2191,7 +2223,7 @@ sb_16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void break; case 2: /* Reserved (16) / WaveTable (32+) */ - if (sb->dsp.sb_type > SB16) + if (sb->dsp.sb_type >= SBAWE32_DSP_412) emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); break; @@ -2204,7 +2236,7 @@ sb_16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void static void sb_vibra16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) { - sb_t *sb = (sb_t *) priv; + sb_t *sb = (sb_t *) priv; switch (ld) { case 0: /* Audio */ @@ -2217,6 +2249,21 @@ sb_vibra16_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, } } +static void +goldfinch_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + goldfinch_t *goldfinch = (goldfinch_t *) priv; + + switch (ld) { + default: + break; + + case 0: /* WaveTable */ + emu8k_change_addr(&goldfinch->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); + break; + } +} + static void sb_awe32_pnp_config_changed(const uint8_t ld, isapnp_device_config_t *config, void *priv) { @@ -2477,7 +2524,7 @@ ess_x688_mca_read(const int port, void *priv) static void ess_soundpiper_mca_write(const int port, const uint8_t val, void *priv) { - sb_t *ess = (sb_t *) priv; + sb_t *ess = (sb_t *) priv; if (port < 0x102) return; @@ -2640,7 +2687,7 @@ ess_soundpiper_mca_write(const int port, const uint8_t val, void *priv) static void ess_chipchat_mca_write(int port, uint8_t val, void *priv) { - sb_t *ess = (sb_t *) priv; + sb_t *ess = (sb_t *) priv; if (port < 0x102) return; @@ -2769,78 +2816,67 @@ ess_chipchat_mca_write(int port, uint8_t val, void *priv) } void * -sb_1_init(UNUSED(const device_t *info)) +sb_init(UNUSED(const device_t *info)) { - /* SB1/2 port mappings, 210h to 260h in 10h steps - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip */ - sb_t * sb = malloc(sizeof(sb_t)); - const uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); - - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - fm_driver_get(FM_YM3812, &sb->opl); - - sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb); - sb_dsp_setaddr(&sb->dsp, addr); - sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); - sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (sb->opl_enabled) { - io_sethandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_sethandler(0x0388, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - - sb->cms_enabled = 1; - memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, - cms_read, NULL, NULL, - cms_write, NULL, NULL, - &sb->cms); - - sb->mixer_enabled = 0; - sound_add_handler(sb_get_buffer_sb2, sb); - if (sb->opl_enabled) - music_add_handler(sb_get_music_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); + /* SB1.x port mappings, 210h to 260h in 10h steps: + (SB2 port mappings are 220h or 240h) + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip + SB2 "CD version" also uses 250h or 260h: + 2x0 to 2x3 -> CDROM interface + 2x4 to 2x5 -> Mixer interface */ + /* My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is disabled when the + CMS chips are present. + This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't + exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror + for music to play. */ + sb_t *sb = calloc(1, sizeof(sb_t)); + const uint16_t addr = device_get_config_hex16("base"); + uint16_t mixer_addr = 0x0000; + uint8_t model = 0; - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + switch (info->local) { + default: + case SB_1: + model = SB_DSP_105; + sb->cms_enabled = 1; + break; - return sb; -} + case SB_15: + model = SB_DSP_200; + sb->cms_enabled = device_get_config_int("cms"); + break; -void * -sb_15_init(UNUSED(const device_t *info)) -{ - /* SB1/2 port mappings, 210h to 260h in 10h steps - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip */ - sb_t * sb = malloc(sizeof(sb_t)); - const uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); + case SB_2: + model = SB_DSP_201; + sb->cms_enabled = device_get_config_int("cms"); + mixer_addr = device_get_config_int("mixaddr"); + break; + } sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, model, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); + + if (mixer_addr > 0x0000) + sb_ct1335_mixer_reset(sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { + // TODO: See if this applies to the SB1.5 as well + if ((!sb->cms_enabled) && ((model == SB_DSP_201) || (model == SB_DSP_202))) { + io_sethandler(addr, 0x0002, + sb->opl.read, NULL, NULL, + sb->opl.write, NULL, NULL, + sb->opl.priv); + } io_sethandler(addr + 8, 0x0002, sb->opl.read, NULL, NULL, sb->opl.write, NULL, NULL, @@ -2851,7 +2887,6 @@ sb_15_init(UNUSED(const device_t *info)) sb->opl.priv); } - sb->cms_enabled = device_get_config_int("cms"); if (sb->cms_enabled) { memset(&sb->cms, 0, sizeof(cms_t)); io_sethandler(addr, 0x0004, @@ -2860,7 +2895,15 @@ sb_15_init(UNUSED(const device_t *info)) &sb->cms); } - sb->mixer_enabled = 0; + if (mixer_addr > 0x000) { + sb->mixer_enabled = 1; + io_sethandler(mixer_addr + 4, 0x0002, + sb_ct1335_mixer_read, NULL, NULL, + sb_ct1335_mixer_write, NULL, NULL, + sb); + } else + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); if (sb->opl_enabled) music_add_handler(sb_get_music_buffer_sb2, sb); @@ -2878,15 +2921,14 @@ sb_mcv_init(UNUSED(const device_t *info)) /* SB1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip */ - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get(FM_YM3812, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB_DSP_105, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, 0); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -2908,85 +2950,6 @@ sb_mcv_init(UNUSED(const device_t *info)) return sb; } -void * -sb_2_init(UNUSED(const device_t *info)) -{ - /* SB2 port mappings, 220h or 240h. - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip - "CD version" also uses 250h or 260h for - 2x0 to 2x3 -> CDROM interface - 2x4 to 2x5 -> Mixer interface */ - /* My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is disabled when the - CMS chips are present. - This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't - exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror - for music to play.*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - uint16_t mixer_addr = device_get_config_int("mixaddr"); - - memset(sb, 0, sizeof(sb_t)); - - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - fm_driver_get(FM_YM3812, &sb->opl); - - sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb); - sb_dsp_setaddr(&sb->dsp, addr); - sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); - sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - if (mixer_addr > 0x000) - sb_ct1335_mixer_reset(sb); - - sb->cms_enabled = device_get_config_int("cms"); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (sb->opl_enabled) { - if (!sb->cms_enabled) { - io_sethandler(addr, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - io_sethandler(addr + 8, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - io_sethandler(0x0388, 0x0002, - sb->opl.read, NULL, NULL, - sb->opl.write, NULL, NULL, - sb->opl.priv); - } - - if (sb->cms_enabled) { - memset(&sb->cms, 0, sizeof(cms_t)); - io_sethandler(addr, 0x0004, - cms_read, NULL, NULL, - cms_write, NULL, NULL, - &sb->cms); - } - - if (mixer_addr > 0x000) { - sb->mixer_enabled = 1; - io_sethandler(mixer_addr + 4, 0x0002, - sb_ct1335_mixer_read, NULL, NULL, - sb_ct1335_mixer_write, NULL, NULL, - sb); - } else - sb->mixer_enabled = 0; - sound_add_handler(sb_get_buffer_sb2, sb); - if (sb->opl_enabled) - music_add_handler(sb_get_music_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - - return sb; -} - static uint8_t sb_pro_v1_opl_read(uint16_t port, void *priv) { @@ -3016,9 +2979,8 @@ sb_pro_v1_init(UNUSED(const device_t *info)) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) { @@ -3029,7 +2991,7 @@ sb_pro_v1_init(UNUSED(const device_t *info)) } sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO_DSP_300, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3079,16 +3041,15 @@ sb_pro_v2_init(UNUSED(const device_t *info)) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface. */ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3133,14 +3094,13 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) 2x4 to 2x5 -> Mixer interface 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) */ - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); sb->mixer_enabled = 1; @@ -3162,13 +3122,12 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) static void * sb_pro_compat_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb); sb_ct1345_mixer_reset(sb); sb->mixer_enabled = 1; @@ -3176,8 +3135,7 @@ sb_pro_compat_init(UNUSED(const device_t *info)) if (sb->opl_enabled) music_add_handler(sb_get_music_buffer_sbpro, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, 1); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3187,18 +3145,16 @@ sb_pro_compat_init(UNUSED(const device_t *info)) static void * sb_16_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); const uint16_t addr = device_get_config_hex16("base"); const uint16_t mpu_addr = device_get_config_hex16("base401"); - memset(sb, 0x00, sizeof(sb_t)); - sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get((int) (intptr_t) info->local, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32PNP : SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32_DSP_413 : SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3234,8 +3190,7 @@ sb_16_init(UNUSED(const device_t *info)) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, device_get_config_int("receive_input401")); } else @@ -3245,7 +3200,7 @@ sb_16_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; gameport_remap(sb->gameport, sb->gameport_addr); @@ -3255,14 +3210,13 @@ sb_16_init(UNUSED(const device_t *info)) static void * sb_16_reply_mca_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0x00, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3275,8 +3229,7 @@ sb_16_reply_mca_init(UNUSED(const device_t *info)) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3310,15 +3263,14 @@ sb_16_pnp_ide_available(void) static void * sb_16_pnp_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0x00, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->pnp = 1; sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3330,8 +3282,7 @@ sb_16_pnp_init(UNUSED(const device_t *info)) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3349,7 +3300,7 @@ sb_16_pnp_init(UNUSED(const device_t *info)) } const char *pnp_rom_file = NULL; - uint16_t pnp_rom_len = 512; + uint16_t pnp_rom_len = 512; switch (info->local) { case SB_16_PNP_NOIDE: pnp_rom_file = PNP_ROM_SB_16_PNP_NOIDE; @@ -3411,12 +3362,10 @@ sb_vibra16xv_available(void) return rom_present(PNP_ROM_SB_VIBRA16XV); } - static void * sb_vibra16_pnp_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0x00, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); sb->pnp = 1; @@ -3424,7 +3373,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, (info->local == SB_VIBRA16XV) ? SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, (info->local == SB_VIBRA16XV) ? SBAWE64_DSP_416 : SBAWE32_DSP_413, SB_SUBTYPE_DEFAULT, sb); /* The ViBRA 16XV does 16-bit DMA through 8-bit DMA. */ sb_dsp_setdma16_supported(&sb->dsp, info->local != SB_VIBRA16XV); sb_ct1745_mixer_reset(sb); @@ -3437,8 +3386,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3446,7 +3394,7 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); switch (info->local) { - case SB_VIBRA16C: /* CTL7001 */ + case SB_VIBRA16C: /* CTL7001 */ case SB_VIBRA16CL: /* CTL7002 */ sb->gameport = gameport_add(&gameport_pnp_device); break; @@ -3516,28 +3464,27 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info)) static void * sb_16_compat_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SB16_DSP_405, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_dsp_setdma16_enabled(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); - sb->opl_enabled = 1; + sb->opl_enabled = 1; sb->mixer_enabled = 1; sound_add_handler(sb_get_buffer_sb16_awe32, sb); music_add_handler(sb_get_music_buffer_sb16_awe32, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, (int) (intptr_t) info->local); sb_dsp_set_mpu(&sb->dsp, sb->mpu); - sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; gameport_remap(sb->gameport, sb->gameport_addr); @@ -3550,6 +3497,12 @@ sb_awe32_available(void) return rom_present(EMU8K_ROM_PATH); } +static int +sb_goldfinch_available(void) +{ + return sb_awe32_available() && rom_present(PNP_ROM_SB_GOLDFINCH); +} + static int sb_32_pnp_available(void) { @@ -3589,7 +3542,7 @@ sb_awe64_gold_available(void) static void * sb_awe32_init(UNUSED(const device_t *info)) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); uint16_t mpu_addr = device_get_config_hex16("base401"); uint16_t emu_addr = device_get_config_hex16("emu_base"); @@ -3602,7 +3555,7 @@ sb_awe32_init(UNUSED(const device_t *info)) fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_set_real_opl(&sb->dsp, 1); - sb_dsp_init(&sb->dsp, SBAWE32, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_init(&sb->dsp, SBAWE32_DSP_412, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); @@ -3639,7 +3592,7 @@ sb_awe32_init(UNUSED(const device_t *info)) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, device_get_config_int("receive_input401")); @@ -3652,28 +3605,72 @@ sb_awe32_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport = gameport_add(&gameport_pnp_device); sb->gameport_addr = 0x200; gameport_remap(sb->gameport, sb->gameport_addr); return sb; } +static void * +sb_goldfinch_init(const device_t *info) +{ + goldfinch_t *goldfinch = calloc(1, sizeof(goldfinch_t)); + int onboard_ram = device_get_config_int("onboard_ram"); + + wavetable_add_handler(sb_get_wavetable_buffer_goldfinch, goldfinch); + + emu8k_init(&goldfinch->emu8k, 0, onboard_ram); + + const char *pnp_rom_file = NULL; + switch (info->local) { + case 0: + pnp_rom_file = PNP_ROM_SB_GOLDFINCH; + break; + + default: + break; + } + + uint8_t *pnp_rom = NULL; + if (pnp_rom_file) { + FILE *fp = rom_fopen(pnp_rom_file, "rb"); + uint16_t pnp_rom_len = 256; + if (fp) { + if (fread(goldfinch->pnp_rom, 1, pnp_rom_len, fp) == pnp_rom_len) + pnp_rom = goldfinch->pnp_rom; + fclose(fp); + } + } + + switch (info->local) { + case 0: + isapnp_add_card(pnp_rom, sizeof(goldfinch->pnp_rom), goldfinch_pnp_config_changed, + NULL, NULL, NULL, goldfinch); + break; + + default: + break; + } + + emu8k_change_addr(&goldfinch->emu8k, 0); + + return goldfinch; +} + static void * sb_awe32_pnp_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = calloc(1, sizeof(sb_t)); int onboard_ram = device_get_config_int("onboard_ram"); - memset(sb, 0x00, sizeof(sb_t)); - sb->pnp = 1; sb->opl_enabled = 1; fm_driver_get(FM_YMF262, &sb->opl); sb_dsp_init(&sb->dsp, (info->local >= SB_AWE64_VALUE) ? - SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb); + SBAWE64_DSP_416 : SBAWE32_DSP_413, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setdma16_supported(&sb->dsp, 1); sb_ct1745_mixer_reset(sb); @@ -3687,8 +3684,7 @@ sb_awe32_pnp_init(const device_t *info) if (device_get_config_int("control_pc_speaker")) sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb); - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); + sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3797,7 +3793,7 @@ sb_awe32_pnp_init(const device_t *info) static void * ess_x688_init(UNUSED(const device_t *info)) { - sb_t *ess = calloc(sizeof(sb_t), 1); + sb_t *ess = calloc(sizeof(sb_t), 1); const uint16_t addr = device_get_config_hex16("base"); const uint16_t ide_ctrl = (const uint16_t) device_get_config_int("ide_ctrl"); const uint16_t ide_base = ide_ctrl & 0x0fff; @@ -3807,7 +3803,7 @@ ess_x688_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setaddr(&ess->dsp, addr); sb_dsp_setirq(&ess->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma")); @@ -3911,18 +3907,18 @@ ess_1688_968_pnp_available(void) static void * ess_x688_pnp_init(UNUSED(const device_t *info)) { - sb_t *ess = calloc(sizeof(sb_t), 1); + sb_t *ess = calloc(sizeof(sb_t), 1); ess->pnp = 1 + (int) info->local; fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); - ess->mixer_enabled = 1; + ess->mixer_enabled = 1; sound_add_handler(sb_get_buffer_ess, ess); music_add_handler(sb_get_music_buffer_ess, ess); sound_set_cd_audio_filter(ess_filter_cd_audio, ess); @@ -4004,11 +4000,11 @@ ess_x688_mca_init(UNUSED(const device_t *info)) fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl); sb_dsp_set_real_opl(&ess->dsp, 1); - sb_dsp_init(&ess->dsp, SBPRO2, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); + sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess); sb_dsp_setdma16_supported(&ess->dsp, 0); ess_mixer_reset(ess); - ess->mixer_enabled = 1; + ess->mixer_enabled = 1; sound_add_handler(sb_get_buffer_ess, ess); music_add_handler(sb_get_music_buffer_ess, ess); sound_set_cd_audio_filter(ess_filter_cd_audio, ess); @@ -4054,6 +4050,16 @@ sb_close(void *priv) free(sb); } +static void +sb_goldfinch_close(void *priv) +{ + goldfinch_t *goldfinch = (goldfinch_t *) priv; + + emu8k_close(&goldfinch->emu8k); + + free(goldfinch); +} + static void sb_awe32_close(void *priv) { @@ -4105,7 +4111,8 @@ static const device_config_t sb_config[] = { }, { .description = "0x260", - .value = 0x260 }, + .value = 0x260 + }, { .description = "" } } }, @@ -4154,7 +4161,7 @@ static const device_config_t sb_config[] = { .description = "DMA 3", .value = 3 }, - { "" } + { .description = "" } } }, { @@ -4208,8 +4215,7 @@ static const device_config_t sb15_config[] = { .description = "0x260", .value = 0x260 }, - { - .description = "" } + { .description = "" } } }, { @@ -4302,10 +4308,6 @@ static const device_config_t sb2_config[] = { .description = "0x240", .value = 0x240 }, - { - .description = "0x260", - .value = 0x260 - }, { .description = "" } } }, @@ -4322,14 +4324,6 @@ static const device_config_t sb2_config[] = { .description = "Disabled", .value = 0 }, - { - .description = "0x220", - .value = 0x220 - }, - { - .description = "0x240", - .value = 0x240 - }, { .description = "0x250", .value = 0x250 @@ -4765,6 +4759,54 @@ static const device_config_t sb_16_pnp_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t sb_goldfinch_config[] = { + { + .name = "onboard_ram", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "None", + .value = 0 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "4 MB", + .value = 4096 + }, + { + .description = "8 MB", + .value = 8192 + }, + { + .description = "16 MB", + .value = 16384 + }, + { + .description = "28 MB", + .value = 28672 + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t sb_32_pnp_config[] = { { .name = "onboard_ram", @@ -5436,7 +5478,6 @@ static const device_config_t ess_688_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } }; -// clang-format on static const device_config_t ess_1688_config[] = { { @@ -5574,7 +5615,6 @@ static const device_config_t ess_1688_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } }; -// clang-format on static const device_config_t ess_688_pnp_config[] = { { @@ -5586,7 +5626,6 @@ static const device_config_t ess_688_pnp_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } }; -// clang-format on static const device_config_t ess_1688_pnp_config[] = { { @@ -5618,8 +5657,8 @@ const device_t sb_1_device = { .name = "Sound Blaster v1.0", .internal_name = "sb", .flags = DEVICE_ISA, - .local = 0, - .init = sb_1_init, + .local = SB_1, + .init = sb_init, .close = sb_close, .reset = NULL, .available = NULL, @@ -5632,8 +5671,8 @@ const device_t sb_15_device = { .name = "Sound Blaster v1.5", .internal_name = "sb1.5", .flags = DEVICE_ISA, - .local = 0, - .init = sb_15_init, + .local = SB_15, + .init = sb_init, .close = sb_close, .reset = NULL, .available = NULL, @@ -5660,8 +5699,8 @@ const device_t sb_2_device = { .name = "Sound Blaster v2.0", .internal_name = "sb2.0", .flags = DEVICE_ISA, - .local = 0, - .init = sb_2_init, + .local = SB_2, + .init = sb_init, .close = sb_close, .reset = NULL, .available = NULL, @@ -5922,6 +5961,20 @@ const device_t sb_16_compat_nompu_device = { .config = NULL }; +const device_t sb_goldfinch_device = { + .name = "Creative EMU8000 PnP (Goldfinch)", + .internal_name = "sb_goldfinch", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = sb_goldfinch_init, + .close = sb_goldfinch_close, + .reset = NULL, + .available = sb_goldfinch_available, + .speed_changed = NULL, + .force_redraw = NULL, + .config = sb_goldfinch_config +}; + const device_t sb_32_pnp_device = { .name = "Sound Blaster 32 PnP", .internal_name = "sb32_pnp", diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 2cabde8cc4..9ce0b9fb75 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -77,13 +77,33 @@ static int sb_commands[256] = { -1, -1, 0, 0, -1, -1, -1, -1, -1, 1, 2, -1, -1, -1, -1, 0 }; +#if 0 +// Currently unused, here for reference if ever needed +char sb202_copyright[] = "COPYRIGHT(C) CREATIVE TECHNOLOGY PTE. LTD. (1991) " +#endif char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; -uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40c, 0x40d, 0x410 }; +uint16_t sb_dsp_versions[] = { + 0, /* Pad */ + 0, /* SADLIB - No DSP */ + 0x105, /* SB_DSP_105 - SB1/1.5, DSP v1.05 */ + 0x200, /* SB_DSP_200 - SB1.5/2, DSP v2.00 */ + 0x201, /* SB_DSP_201 - SB1.5/2, DSP v2.01 - needed for high-speed DMA */ + 0x202, /* SB_DSP_202 - SB2, DSP v2.02 */ + 0x300, /* SB_PRO_DSP_300 - SB Pro, DSP v3.00 */ + 0x302, /* SBPRO2_DSP_302 - SB Pro 2, DSP v3.02 + OPL3 */ + 0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */ + 0x405, /* SB16_405 - DSP v4.05 + OPL3 */ + 0x406, /* SB16_406 - DSP v4.06 + OPL3 */ + 0x40b, /* SB16_411 - DSP v4.11 + OPL3 */ + 0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */ + 0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */ + 0x410 /* SBAWE64 - DSP v4.16 + OPL3 */ +}; /*These tables were 'borrowed' from DOSBox*/ int8_t scaleMap4[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, - 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, + 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, + 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 }; @@ -525,7 +545,7 @@ sb_doreset(sb_dsp_t *dsp) sb_commands[8] = 1; sb_commands[9] = 1; } else { - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) sb_commands[8] = 1; else sb_commands[8] = -1; @@ -1206,7 +1226,7 @@ sb_exec_command(sb_dsp_t *dsp) /* Update 8051 ram with the current DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_8051_ram[0x20] = dsp->sb_command; } @@ -1232,15 +1252,15 @@ sb_exec_command(sb_dsp_t *dsp) switch (dsp->sb_command) { case 0x01: /* ???? */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->asp_data_len = dsp->sb_data[0] + (dsp->sb_data[1] << 8) + 1; break; case 0x03: /* ASP status */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) sb_add_data(dsp, 0); break; case 0x04: /* ASP set mode register */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_asp_mode = dsp->sb_data[0]; if (dsp->sb_asp_mode & 4) dsp->sb_asp_ram_index = 0; @@ -1248,7 +1268,7 @@ sb_exec_command(sb_dsp_t *dsp) } /* else DSP Status (Obsolete) */ break; case 0x05: /* ASP set codec parameter */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]); } break; @@ -1278,9 +1298,9 @@ sb_exec_command(sb_dsp_t *dsp) sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */ break; } - if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */ + if (dsp->sb_type == SBAWE64_DSP_416) /* AWE64 has no ASP or a socket for it */ sb_add_data(dsp, 0xFF); - else if (dsp->sb_type >= SB16) + else if (dsp->sb_type >= SB16_DSP_404) sb_add_data(dsp, 0x18); break; case 0x09: /* AZTECH mode set */ @@ -1296,7 +1316,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x0E: /* ASP set register */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */ @@ -1315,7 +1335,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x0F: /* ASP get register */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */ if (dsp->sb_asp_mode & 8) dsp->sb_asp_ram_index = 0; @@ -1359,11 +1379,11 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x1C: /* 8-bit autoinit DMA output */ - if (dsp->sb_type >= SB15) + if (dsp->sb_type >= SB_DSP_200) sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x1F: /* 2-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { + if (dsp->sb_type >= SB_DSP_200) { sb_start_dma(dsp, 1, 1, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); dsp->sb_8_length--; @@ -1388,7 +1408,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0x28: /* Direct ADC, 8-bit (Burst) */ break; case 0x2C: /* 8-bit autoinit DMA input */ - if (dsp->sb_type >= SB15) + if (dsp->sb_type >= SB_DSP_200) sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); break; case 0x30: /* MIDI Polling mode input */ @@ -1405,7 +1425,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0x33: /* MIDI Read Timestamp Interrupt */ break; case 0x34: /* MIDI In poll */ - if (dsp->sb_type < SB2) + if (dsp->sb_type < SB_DSP_200) break; sb_dsp_log("MIDI poll in\n"); dsp->midi_in_poll = 1; @@ -1413,7 +1433,7 @@ sb_exec_command(sb_dsp_t *dsp) dsp->uart_irq = 0; break; case 0x35: /* MIDI In irq */ - if (dsp->sb_type < SB2) + if (dsp->sb_type < SB_DSP_200) break; sb_dsp_log("MIDI irq in\n"); dsp->midi_in_poll = 0; @@ -1432,7 +1452,7 @@ sb_exec_command(sb_dsp_t *dsp) temp = 256 - dsp->sb_data[0]; temp = 1000000 / temp; sb_dsp_log("Sample rate - %ihz (%f)\n", temp, dsp->sblatcho); - if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) + if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16_DSP_404)) recalc_sb16_filter(0, temp); dsp->sb_freq = temp; if (IS_ESS(dsp)) { @@ -1441,7 +1461,7 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0x41: /* Set output sampling rate */ case 0x42: /* Set input sampling rate */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sblatcho = (double) ((double) TIMER_USEC * (1000000.0 / (double) (dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); sb_dsp_log("Sample rate - %ihz (%f)\n", dsp->sb_data[1] + (dsp->sb_data[0] << 8), dsp->sblatcho); temp = dsp->sb_freq; @@ -1459,7 +1479,8 @@ sb_exec_command(sb_dsp_t *dsp) case 0x47: /* Continue Auto-Initialize DMA, 16-bit */ break; case 0x48: /* Set DSP block transfer size */ - dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); + if (dsp->sb_type >= SB_DSP_200) + dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8); break; case 0x65: /* 4-bit ESPCM output with reference */ case 0x64: /* 4-bit ESPCM output */ @@ -1534,7 +1555,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x7D: /* 4-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { + if (dsp->sb_type >= SB_DSP_200) { sb_start_dma(dsp, 1, 1, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); dsp->sb_8_length--; @@ -1542,7 +1563,7 @@ sb_exec_command(sb_dsp_t *dsp) } break; case 0x7F: /* 2.6-bit ADPCM autoinit output */ - if (dsp->sb_type >= SB15) { + if (dsp->sb_type >= SB_DSP_200) { sb_start_dma(dsp, 1, 1, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = dsp->dma_readb(dsp->dma_priv); dsp->sb_8_length--; @@ -1555,24 +1576,24 @@ sb_exec_command(sb_dsp_t *dsp) timer_set_delay_u64(&dsp->output_timer, (uint64_t) trunc(dsp->sblatcho)); break; case 0x90: /* High speed 8-bit autoinit DMA output */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x91: /* High speed 8-bit single cycle DMA output */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0x98: /* High speed 8-bit autoinit DMA input */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x99: /* High speed 8-bit single cycle DMA input */ - if (dsp->sb_type >= SB2) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0xA0: /* Set input mode to mono */ case 0xA8: /* Set input mode to stereo */ - if ((dsp->sb_type < SB2) || (dsp->sb_type > SBPRO2)) + if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO2_DSP_302)) break; /* TODO: Implement. 3.xx-only command. */ break; @@ -1584,7 +1605,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xB5: case 0xB6: case 0xB7: /* 16-bit DMA output */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1598,7 +1619,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xBD: case 0xBE: case 0xBF: /* 16-bit DMA input */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1612,7 +1633,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xC5: case 0xC6: case 0xC7: /* 8-bit DMA output */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1626,7 +1647,7 @@ sb_exec_command(sb_dsp_t *dsp) case 0xCD: case 0xCE: case 0xCF: /* 8-bit DMA input */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8)); dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8); @@ -1638,20 +1659,20 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0xD1: /* Speaker on */ if (IS_NOT_ESS(dsp)) { - if (dsp->sb_type < SB15) { + if (dsp->sb_type < SB_DSP_200) { dsp->sb_8_pause = 1; sb_stop_dma(dsp); - } else if (dsp->sb_type < SB16) + } else if (dsp->sb_type < SB16_DSP_404) dsp->muted = 0; } dsp->sb_speaker = 1; break; case 0xD3: /* Speaker off */ if (IS_NOT_ESS(dsp)) { - if (dsp->sb_type < SB15) { + if (dsp->sb_type < SB_DSP_201) { dsp->sb_8_pause = 1; sb_stop_dma(dsp); - } else if (dsp->sb_type < SB16) + } else if (dsp->sb_type < SB16_DSP_404) dsp->muted = 1; } dsp->sb_speaker = 0; @@ -1661,26 +1682,28 @@ sb_exec_command(sb_dsp_t *dsp) sb_resume_dma(dsp, 1); break; case 0xD5: /* Pause 16-bit DMA */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_16_pause = 1; sb_stop_dma(dsp); } break; case 0xD6: /* Continue 16-bit DMA */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { dsp->sb_16_pause = 0; sb_resume_dma(dsp, 1); } break; case 0xD8: /* Get speaker status */ - sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); + if (dsp->sb_type >= SB_DSP_200) + sb_add_data(dsp, dsp->sb_speaker ? 0xff : 0); break; case 0xD9: /* Exit 16-bit auto-init mode */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->sb_16_autoinit = 0; break; case 0xDA: /* Exit 8-bit auto-init mode */ - dsp->sb_8_autoinit = 0; + if (dsp->sb_type >= SB_DSP_200) + dsp->sb_8_autoinit = 0; break; case 0xE0: /* DSP identification */ sb_add_data(dsp, ~dsp->sb_data[0]); @@ -1721,7 +1744,7 @@ sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, dsp->sbe2); break; case 0xE3: /* DSP copyright */ - if (dsp->sb_type >= SB16) { + if (dsp->sb_type >= SB16_DSP_404) { c = 0; while (sb16_copyright[c]) sb_add_data(dsp, sb16_copyright[c++]); @@ -1782,15 +1805,15 @@ sb_exec_command(sb_dsp_t *dsp) timer_set_delay_u64(&dsp->irq16_timer, (10ULL * TIMER_USEC)); break; case 0xF8: - if (dsp->sb_type < SB16) + if (dsp->sb_type < SB16_DSP_404) sb_add_data(dsp, 0); break; case 0xF9: /* SB16 8051 RAM read */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) sb_add_data(dsp, dsp->sb_8051_ram[dsp->sb_data[0]]); break; case 0xFA: /* SB16 8051 RAM write */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->sb_8051_ram[dsp->sb_data[0]] = dsp->sb_data[1]; break; case 0xFF: /* No, that's not how you program auto-init DMA */ @@ -1800,11 +1823,24 @@ sb_exec_command(sb_dsp_t *dsp) * http://the.earth.li/~tfm/oldpage/sb_dsp.html * http://www.synchrondata.com/pheaven/www/area19.htm * http://www.dcee.net/Files/Programm/Sound/ - * 0E3h DSP Copyright SBPro2??? - * 0F0h Sine Generator SB - * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 - * 0F2h IRQ Request, 8-bit SB + * https://github.com/schlae/sb-firmware/blob/master/sbv202.asm + * 008h Halt (Infinate Loop) SB2??? + * 018h DMA playback with auto init DMA. SB2??? + * 028h Auto-init direct ADC SB2??? + * 036h (Timestamp) SB??? + * 037h (Timestamp) SB??? + * 050h Stops playback of SRAM samples SB??? + * 051h Plays back samples stored in SRAM. SB??? + * 058h Load data into SRAM SB??? + * 059h Fetches the samples and then immediately plays them back. SB??? + * 078h Auto-init DMA ADPCM SB2??? + * 07Ah 2.6-bit ADPCM SB??? + * 0E3h DSP Copyright SBPro2??? (SBPRO2_DSP_302) + * 0F0h Sine Generator SB (SB_DSP_105, DSP20x) + * 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (DSP20x, SBPRO2_DSP_302) + * 0F2h IRQ Request, 8-bit SB (SB_DSP_105, DSP20x) * 0F3h IRQ Request, 16-bit SB16 + * 0F4h Perform ROM checksum SB (SB_DSP_105, DSP20x) * 0FBh DSP Status SB16 * 0FCh DSP Auxiliary Status SB16 * 0FDh DSP Command Status SB16 @@ -1817,7 +1853,7 @@ sb_exec_command(sb_dsp_t *dsp) /* Update 8051 ram with the last DSP command. See https://github.com/joncampbell123/dosbox-x/issues/1044 */ - if (dsp->sb_type >= SB16) + if (dsp->sb_type >= SB16_DSP_404) dsp->sb_8051_ram[0x30] = dsp->sb_command; } @@ -1836,31 +1872,31 @@ sb_do_reset(sb_dsp_t *dsp, const uint8_t v) } void -sb_write(uint16_t a, uint8_t v, void *priv) +sb_write(uint16_t addr, uint8_t val, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; - sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, a, v); + sb_dsp_log("[%04X:%08X] DSP: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xE))) - a &= 0xfffe; + if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xE))) + addr &= 0xfffe; - switch (a & 0xF) { + switch (addr & 0xF) { case 6: /* Reset */ - sb_do_reset(dsp, v); + sb_do_reset(dsp, val); - if (!(v & 2) && (dsp->espcm_fifo_reset & 2)) { + if (!(val & 2) && (dsp->espcm_fifo_reset & 2)) { fifo_reset(dsp->espcm_fifo); } - dsp->espcm_fifo_reset = v; + dsp->espcm_fifo_reset = val; dsp->uart_midi = 0; dsp->uart_irq = 0; dsp->onebyte_midi = 0; return; case 0xC: /* Command/data write */ if (dsp->uart_midi || dsp->onebyte_midi) { - midi_raw_out_byte(v); + midi_raw_out_byte(val); dsp->onebyte_midi = 0; return; } @@ -1873,8 +1909,8 @@ sb_write(uint16_t a, uint8_t v, void *priv) return; } if (dsp->sb_data_stat == -1) { - dsp->sb_command = v; - if (v == 0x01) + dsp->sb_command = val; + if (val == 0x01) sb_add_data(dsp, 0); dsp->sb_data_stat++; if (IS_AZTECH(dsp)) { @@ -1901,7 +1937,7 @@ sb_write(uint16_t a, uint8_t v, void *priv) } } } else { - dsp->sb_data[dsp->sb_data_stat++] = v; + dsp->sb_data[dsp->sb_data_stat++] = val; } if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) { sb_exec_command(dsp); @@ -1920,17 +1956,17 @@ sb_write(uint16_t a, uint8_t v, void *priv) } uint8_t -sb_read(uint16_t a, void *priv) +sb_read(uint16_t addr, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *) priv; uint8_t ret = 0x00; /* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */ - if ((dsp->sb_type < SB16) && (IS_NOT_ESS(dsp) || ((a & 0xF) != 0xF))) + if ((dsp->sb_type < SB16_DSP_404) && (IS_NOT_ESS(dsp) || ((addr & 0xF) != 0xF))) /* Exception: ESS AudioDrive does not alias port base+0xf */ - a &= 0xfffe; + addr &= 0xfffe; - switch (a & 0xf) { + switch (addr & 0xf) { case 0x6: if (IS_ESS(dsp)) { ret = (dsp->espcm_fifo_reset & 0x03) | 0x08 | (dsp->activity & 0xe0); @@ -1968,7 +2004,7 @@ sb_read(uint16_t a, void *priv) if (dsp->state == DSP_S_RESET_WAIT) dsp->state = DSP_S_NORMAL; if ((dsp->state == DSP_S_NORMAL) || IS_ESS(dsp)) { - if (dsp->sb_8_enable || dsp->sb_type >= SB16) + if (dsp->sb_8_enable || dsp->sb_type >= SB16_DSP_404) dsp->busy_count = (dsp->busy_count + 1) & 3; else dsp->busy_count = 0; @@ -1993,7 +2029,7 @@ sb_read(uint16_t a, void *priv) ret = 0x80; } else { sb_dsp_log("SB Write Data Creative read 0xff\n"); - if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp)) ret = 0xaa; else ret = 0xff; @@ -2003,7 +2039,7 @@ sb_read(uint16_t a, void *priv) ret = 0x00; } else { sb_dsp_log("SB Write Data Creative read 0x7f\n"); - if ((dsp->sb_type >= SB2) && (dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp)) ret = 0x2a; else ret = 0x7f; @@ -2027,7 +2063,7 @@ sb_read(uint16_t a, void *priv) ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80; } else { sb_dsp_log("SB Read Data Creative read %02X\n", (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff); - if ((dsp->sb_type < SB16) && IS_NOT_ESS(dsp)) + if ((dsp->sb_type < SB16_DSP_404) && IS_NOT_ESS(dsp)) ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x2a : 0xaa; else ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; @@ -2138,11 +2174,11 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) /* Default values. Use sb_dsp_setxxx() methods to change. */ dsp->sb_irqnum = 7; dsp->sb_8_dmanum = 1; - if (type >= SB16) + if (type >= SB16_DSP_404) dsp->sb_16_dmanum = 5; else dsp->sb_16_dmanum = 0xff; - if ((type >= SB16) || IS_ESS(dsp)) + if ((type >= SB16_DSP_404) || IS_ESS(dsp)) dsp->sb_16_8_dmanum = 0x1; dsp->mpu = NULL; @@ -2174,7 +2210,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) a set frequency command is sent. */ recalc_sb16_filter(0, 3200 * 2); } - if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2)) { + if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2_DSP_302)) { /* OPL3 or dual OPL2 is stereo. */ if (dsp->sb_has_real_opl) recalc_opl_filter(FREQ_49716 * 2); diff --git a/src/sound/sound.c b/src/sound/sound.c index 4162b2fad1..9bb6d1ab1c 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -123,6 +123,7 @@ static const SOUND_CARD sound_cards[] = { { &sb_16_device }, { &sb_16_pnp_device }, { &sb_16_pnp_ide_device }, + { &sb_goldfinch_device }, { &sb_32_pnp_device }, { &sb_awe32_device }, { &sb_awe32_pnp_device }, @@ -152,6 +153,7 @@ static const SOUND_CARD sound_cards[] = { { &ess_soundpiper_32_mca_device }, { &cmi8338_device }, { &cmi8738_device }, + { &es1370_device }, { &es1371_device }, { &es1373_device }, { &ct5880_device }, diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index 8555642e65..4ed0333a7c 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -144,23 +144,6 @@ plat_cdrom_ext_medium_changed(void *local) return ret; } -void -plat_cdrom_get_audio_tracks(void *local, int *st_track, int *end, TMSF *lead_out) -{ - dummy_cdrom_ioctl_t *ioctl = (dummy_cdrom_ioctl_t *) local; - - plat_cdrom_read_toc(ioctl); - - *st_track = 1; - *end = 1; - lead_out->min = 0; - lead_out->sec = 0; - lead_out->fr = 2; - - dummy_cdrom_ioctl_log("plat_cdrom_get_audio_tracks(): %02i, %02i, %02i:%02i:%02i\n", - *st_track, *end, lead_out->min, lead_out->sec, lead_out->fr); -} - /* This replaces both Info and EndInfo, they are specified by a variable. */ int plat_cdrom_get_audio_track_info(void *local, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 810d403ab0..0e51feae4d 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -43,6 +43,11 @@ #include <86box/vid_ati_mach8.h> #include "cpu.h" +#ifdef CLAMP +# undef CLAMP +#endif + + #define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140_4k.BIN" static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); @@ -68,6 +73,17 @@ ibm8514_log(const char *fmt, ...) # define ibm8514_log(fmt, ...) #endif +static int16_t +CLAMP(int16_t in, int16_t min, int16_t max) +{ + if (in < min) + return min; + if (in > max) + return max; + + return in; +} + #define WRITE8(addr, var, val) \ switch ((addr) & 1) { \ case 0: \ @@ -416,14 +432,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 2) { dev->accel.short_stroke = val; - dev->accel.cx = dev->accel.cur_x; - if (dev->accel.cur_x >= 0x600) - dev->accel.cx |= ~0x5ff; - - dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_y >= 0x600) - dev->accel.cy |= ~0x5ff; - if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); @@ -969,6 +977,7 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t dev->accel.ssv_len = ssv & 0x0f; dev->accel.ssv_dir = ssv & 0xe0; dev->accel.ssv_draw = ssv & 0x10; + dev->accel.ssv_len_back = dev->accel.ssv_len; if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -1006,6 +1015,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat uint16_t bkgd_color = dev->accel.bkgd_color; uint32_t old_mix_dat; int and3 = dev->accel.cur_x & 3; + int poly_src; if (!dev->bpp) { compare &= 0xff; @@ -1121,13 +1131,24 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_mix_dat = mix_dat; + if (cmd == 5 || cmd == 1 || (cmd == 2 && (dev->accel.multifunc[0x0a] & 0x06))) + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06); + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (dev->accel.ssv_state == 0) + if (dev->accel.ssv_state == 0) { + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; break; + } if (dev->accel.cmd & 0x08) { while (count-- && dev->accel.ssv_len >= 0) { @@ -1289,7 +1310,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.ssv_len_back) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -1303,7 +1324,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cx--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.ssv_len_back) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; @@ -1454,6 +1475,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + if (!cpu_input) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } break; } @@ -1505,8 +1530,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy--; } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; dev->accel.x_count = 0; dev->accel.output = 0; } else { /*Bresenham Line*/ @@ -1580,7 +1603,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -1594,7 +1617,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cx--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; @@ -1673,6 +1696,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.sy) { dev->accel.cmd_back = 1; + if (!cpu_input) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } break; } @@ -1682,7 +1709,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -1696,7 +1723,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cx--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; @@ -1709,8 +1736,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy--; } } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; } break; @@ -2283,35 +2308,62 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } } else if ((dev->accel.multifunc[0x0a] & 0x06) == 0x04) { /*Polygon Draw Type A*/ + ibm8514_log("Polygon Draw Type A: Clipping: L=%d, R=%d, T=%d, B=%d, C(%d,%d), sx=%d, sy=%d.\n", clip_l, clip_r, clip_t, clip_b, dev->accel.cx, dev->accel.cy, dev->accel.sx, dev->accel.sy); while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - READ(dev->accel.dest + dev->accel.cx, mix_dat); - if ((mix_dat & rd_mask_polygon) == rd_mask_polygon) + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ(dev->accel.dest + dev->accel.cx, poly_src); + if ((poly_src & rd_mask_polygon) == rd_mask_polygon) dev->accel.fill_state ^= 1; READ(dev->accel.dest + dev->accel.cx, dest_dat); + old_dest_dat = dest_dat; if (dev->accel.fill_state) { - if (!(rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) { - MIX(mix_dat ^ rd_mask_polygon, dest_dat, mix_dat); - ibm8514_log("Filling c(%d,%d) without bit 0 of rdmask=%02x, wrtmask=%02x, mixdat=%02x, dest=%02x, old=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, old_dest_dat); - dest_dat &= ~rd_mask_polygon; - } else if ((rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) { - ibm8514_log("Filling c(%d,%d) with bit 0 of rdmask=%02x, wrtmask=%02x.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask); - dest_dat &= ~(rd_mask_polygon & wrt_mask); + if (rd_mask_polygon & 0x01) { + if (wrt_mask & 0x01) { + dest_dat &= ~(rd_mask_polygon & wrt_mask); /*Fill State On, Write Mask 1, Read Mask 1.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } else { + if (wrt_mask & 0x01) { + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat &= ~rd_mask_polygon; /*Fill State On, Write Mask 1, Read Mask 0.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } } } else { - if (!(rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) - dest_dat &= ~rd_mask_polygon; - else if ((rd_mask_polygon & 0x01) && (wrt_mask & 0x01)) - dest_dat &= ~(rd_mask_polygon & wrt_mask); + if (rd_mask_polygon & 0x01) { + if (wrt_mask & 0x01) { + dest_dat &= ~(rd_mask_polygon & wrt_mask); /*Fill State Off, Write Mask 1, Read Mask 1.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } else { + if (wrt_mask & 0x01) { + dest_dat &= ~rd_mask_polygon; /*Fill State Off, Write Mask 1, Read Mask 0.*/ + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } } - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || @@ -2322,7 +2374,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat ibm8514_log("Results c(%d,%d):rdmask=%02x, wrtmask=%02x, mix=%02x, destdat=%02x, nowrite=%d.\n", dev->accel.cx, dev->accel.cy, rd_mask_polygon, wrt_mask, mix_dat, dest_dat, dev->accel.cx_back); WRITE(dev->accel.dest + dev->accel.cx, dest_dat); } - } + } else + ibm8514_log("Out of bounds DrawA C(%d,%d).\n", dev->accel.cx, dev->accel.cy); + + mix_dat <<= 1; + mix_dat |= 1; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2356,6 +2412,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.sy < 0) { ibm8514_log(".\n"); dev->accel.cmd_back = 1; + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; return; } } @@ -2468,7 +2526,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.oldcy = dev->accel.cy - 1; - ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.clip_top, clip_b, dev->accel.multifunc[0x0a]); + ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, clip_l, clip_r, clip_t, clip_b, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -2483,8 +2541,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cmd & 0x08) { /*Vectored Boundary Line*/ while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < clip_l) - dev->accel.cx = clip_l; + dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r); if ((dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && @@ -2591,11 +2648,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } else { /*Vectored Bresenham*/ while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < clip_l) - dev->accel.cx = clip_l; + dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r); if ((dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r) && + (dev->accel.cx < clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -2658,7 +2714,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.cy--; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt_no_limit) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2673,7 +2729,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.cx--; dev->accel.oldcy = dev->accel.cy; - if (dev->accel.err_term >= 0) { + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt_no_limit) { dev->accel.err_term += dev->accel.destx_distp; if (dev->accel.cmd & 0x80) dev->accel.cy++; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 4e7d1ac094..bc54d0d7c7 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1361,7 +1361,7 @@ gd54xx_in(uint16_t addr, void *priv) 32-bit (Pre-5434)/64-bit (5434 and up) DRAM data bus width for 2M of memory */ - ret |= (gd54xx_is_5434(svga)) ? 0x98 : 0x18; + ret |= 0x18; break; case 4096: ret |= 0x98; /*64-bit (5434 and up) DRAM data bus width for 4M of memory*/ @@ -2281,6 +2281,9 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) + val = (val >> 8) | (val << 8); + gd54xx_write(addr, val, gd54xx); gd54xx_write(addr + 1, val >> 8, gd54xx); return; @@ -2308,6 +2311,9 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv) if (gd54xx->countminusone && !gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { + if ((gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) && (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + gd54xx_write(addr, val, gd54xx); gd54xx_write(addr + 1, val >> 8, gd54xx); gd54xx_write(addr + 2, val >> 16, gd54xx); @@ -3661,9 +3667,6 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) mask_shift = 31 - byte_pos; if (!(gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) cpu_dat >>= byte_pos; - else if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) - cpu_dat = ((cpu_dat & 0xff000000) >> 24) | ((cpu_dat & 0x00ff0000) >> 8) | - ((cpu_dat & 0x0000ff00) << 8) | ((cpu_dat & 0x000000ff) << 24); } else mask_shift = 7; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index abb2d70aa4..bb5c283ad9 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -273,6 +273,7 @@ typedef struct s3_t { int dat_count; int b2e8_pix, temp_cnt; int ssv_len; + int ssv_len_back; uint8_t ssv_dir; uint8_t ssv_draw; uint8_t dat_buf_16bit; @@ -511,7 +512,7 @@ s3_update_irqs(s3_t *s3) } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv); -void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); +void s3_short_stroke_start(s3_t *s3, uint8_t ssv); static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) \ @@ -922,15 +923,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cmd & 0x1000) { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); } else { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); } break; @@ -1787,15 +1785,12 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) s3->accel.short_stroke = val; s3->accel.ssv_state = 1; - s3->accel.cx = s3->accel.cur_x & 0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cmd & 0x1000) { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); } else { - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); - s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(s3, s3->accel.short_stroke & 0xff); } } } @@ -7823,19 +7818,16 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } void -s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) +s3_short_stroke_start(s3_t *s3, uint8_t ssv) { - if (!cpu_input) { - s3->accel.ssv_len = ssv & 0x0f; - s3->accel.ssv_dir = ssv & 0xe0; - s3->accel.ssv_draw = ssv & 0x10; + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = !!(ssv & 0x10); - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } + if (s3_cpu_src(s3)) + return; /*Wait for data from CPU*/ - s3->accel_start(count, cpu_input, mix_dat, cpu_dat, s3); + s3->accel_start(-1, 0, -1, 0, s3); } void @@ -7978,11 +7970,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ - if (s3->accel.ssv_state == 0) + if (s3->accel.ssv_state == 0) { + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; break; + } - if (s3->accel.cmd & 0x08) /*Radial*/ - { + if (s3->accel.cmd & 0x08) { /*Radial*/ while (count-- && s3->accel.ssv_len >= 0) { if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -8036,8 +8030,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else cpu_dat >>= 16; - if (!s3->accel.ssv_len) + if (!s3->accel.ssv_len) { + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; break; + } switch (s3->accel.ssv_dir & 0xe0) { case 0x00: @@ -8077,9 +8074,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cx &= 0xfff; s3->accel.cy &= 0xfff; } - - s3->accel.cur_x = s3->accel.cx & 0xfff; - s3->accel.cur_y = s3->accel.cy & 0xfff; } break; @@ -8270,7 +8264,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else s3->accel.cy--; - if (s3->accel.err_term >= 0) { + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; if (s3->accel.cmd & 0x20) s3->accel.cx++; @@ -8284,7 +8278,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi else s3->accel.cx--; - if (s3->accel.err_term >= 0) { + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; if (s3->accel.cmd & 0x80) s3->accel.cy++; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5054bd8e78..6a91713fb9 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -628,6 +628,8 @@ svga_recalctimings(svga_t *svga) int hsyncstart; int hsyncend; #endif + int old_monitor_overscan_x = svga->monitor->mon_overscan_x; + int old_monitor_overscan_y = svga->monitor->mon_overscan_y; svga->vtotal = svga->crtc[6]; svga->dispend = svga->crtc[0x12]; @@ -1009,6 +1011,9 @@ svga_recalctimings(svga_t *svga) svga->dpms_ui = 0; ui_sb_set_text_w(NULL); } + + if (enable_overscan && (svga->monitor->mon_overscan_x != old_monitor_overscan_x || svga->monitor->mon_overscan_y != old_monitor_overscan_y)) + video_force_resize_set_monitor(1, svga->monitor_index); } static void diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 0c5e5f7bbc..4fa27e2e45 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -1095,7 +1095,7 @@ banshee_status(banshee_t *banshee) int fifo_entries = FIFO_ENTRIES; int swap_count = voodoo->swap_count; int written = voodoo->cmd_written + voodoo->cmd_written_fifo; - int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] || voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] || voodoo->voodoo_busy; + int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || (voodoo->cmdfifo_depth_rd_2 != voodoo->cmdfifo_depth_wr_2) || voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] || voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] || voodoo->voodoo_busy; uint32_t ret = 0; if (fifo_entries < 0x20) @@ -1117,6 +1117,9 @@ banshee_status(banshee_t *banshee) if (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) ret |= (1 << 11); + if (voodoo->cmdfifo_depth_rd_2 != voodoo->cmdfifo_depth_wr_2) + ret |= (1 << 12); + if (!voodoo->voodoo_busy) voodoo_wake_fifo_thread(voodoo); diff --git a/src/video/vid_voodoo_fb.c b/src/video/vid_voodoo_fb.c index 5ae26b4c57..ddf68360fd 100644 --- a/src/video/vid_voodoo_fb.c +++ b/src/video/vid_voodoo_fb.c @@ -252,6 +252,9 @@ voodoo_fb_writew(uint32_t addr, uint16_t val, void *priv) { rgba8_t write_data = colour_data; uint16_t new_depth = depth_data; + int colbfog_r = 0; + int colbfog_g = 0; + int colbfog_b = 0; if (params->fbzMode & FBZ_DEPTH_ENABLE) { uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); @@ -262,6 +265,10 @@ voodoo_fb_writew(uint32_t addr, uint16_t val, void *priv) if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b) goto skip_pixel; + colbfog_r = write_data.r; + colbfog_g = write_data.g; + colbfog_b = write_data.b; + if (params->fogMode & FOG_ENABLE) { int32_t z = new_depth << 12; int64_t w_depth = (int64_t) (int32_t) new_depth; @@ -438,6 +445,9 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) for (int c = 0; c < count; c++) { rgba8_t write_data = colour_data[c]; uint16_t new_depth = depth_data[c]; + int colbfog_r = 0; + int colbfog_g = 0; + int colbfog_b = 0; if (params->fbzMode & FBZ_DEPTH_ENABLE) { uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); @@ -448,6 +458,10 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b) goto skip_pixel; + colbfog_r = write_data.r; + colbfog_g = write_data.g; + colbfog_b = write_data.b; + if (params->fogMode & FOG_ENABLE) { int32_t z = new_depth << 12; int64_t w_depth = new_depth; diff --git a/src/video/vid_voodoo_render.c b/src/video/vid_voodoo_render.c index 0f31fbc9f7..d8f812f7f4 100644 --- a/src/video/vid_voodoo_render.c +++ b/src/video/vid_voodoo_render.c @@ -967,6 +967,9 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t * int src_g = 0; int src_b = 0; int src_a = 0; + int colbfog_r = 0; + int colbfog_g = 0; + int colbfog_b = 0; int msel_r; int msel_g; int msel_b; @@ -1263,6 +1266,10 @@ voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t * if (cca_invert_output) src_a ^= 0xff; + colbfog_r = src_r; + colbfog_g = src_g; + colbfog_b = src_b; + if (params->fogMode & FOG_ENABLE) APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w);